From 626a8be77cba1eb83f8cb9bec42af6b095e31a35 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Sun, 26 Nov 2023 02:24:47 +0100 Subject: [PATCH] Hydra looks better by default --- index.html | 4 +-- src/API.ts | 1 + src/WindowBehavior.ts | 10 ++++---- src/documentation/more/bonus.ts | 43 ++++++++++++++++++++++++--------- src/main.ts | 37 ++++++++++++++-------------- 5 files changed, 57 insertions(+), 38 deletions(-) diff --git a/index.html b/index.html index bf64537..3a96625 100644 --- a/index.html +++ b/index.html @@ -128,7 +128,7 @@ -[Hydra](https://hydra.ojack.xyz/?sketch_id=mahalia_1) is a popular live-codable video synthesizer developed by [Olivia Jack](https://ojack.xyz/) and other contributors. It follows the metaphor of analog synthesizer patching to allow its user to create complex live visuals from a web browser window. Being very easy to use, extremely powerful and also very rewarding to use, Hydra has become a popular choice for adding visuals into a live code performance. Topos provides a simple way to integrate Hydra into a live coding session and to blend it with regular Topos code. +[Hydra](https://hydra.ojack.xyz/?sketch_id=mahalia_1) is a popular live-codable video synthesizer developed by [Olivia Jack](https://ojack.xyz/) and other contributors. It follows an analog synthesizer patching metaphor to encourage live coding complex shaders. Being very easy to use, extremely powerful and also very rewarding to use, Hydra has become a popular choice for adding visuals into a live code performance. ${makeExample( "Hydra integration", - `beat(4) :: app.hydra.osc(3, 0.5, 2).out()`, - true, + `beat(4) :: hydra.osc(3, 0.5, 2).out()`, + true )} -You may feel like it's doing nothing! Press ${key_shortcut( - "Ctrl+D", - )} to close the documentation. **Boom, all shiny!** +Close the documentation to see the effect: ${key_shortcut( + "Ctrl+D" + )}! **Boom, all shiny!** -Be careful not to call app.hydra too often as it can impact performances. You can use any rhythmical function like mod() function to limit the number of function calls. You can write any Topos code like [1,2,3].beat() to bring some life and movement in your Hydra sketches. +Be careful not to call hydra too often as it can impact performances. You can use any rhythmical function like beat() function to limit the number of function calls. You can write any Topos code like [1,2,3].beat() to bring some life and movement in your Hydra sketches. Stopping **Hydra** is simple: @@ -35,16 +35,35 @@ ${makeExample( "Stopping Hydra", ` beat(4) :: stop_hydra() // this one -beat(4) :: app.hydra.hush() // or this one +beat(4) :: hydra.hush() // or this one `, - true, + true )} -I won't teach you how to play with Hydra. You can find some great resources on the [Hydra website](https://hydra.ojack.xyz/): + +### Changing the resolution + +You can change Hydra resolution using this simple method: + +${makeExample( + "Changing Hydra resolution", + `hydra.setResolution(1024, 768)`, + true +)} + +### Documentation + +I won't teach Hydra. You can find some great resources directly on the [Hydra website](https://hydra.ojack.xyz/): - [Hydra interactive documentation](https://hydra.ojack.xyz/docs/) - [List of Hydra Functions](https://hydra.ojack.xyz/api/) - [Source code on GitHub](https://github.com/hydra-synth/hydra) +### The Hydra namespace + +In comparison with the basic Hydra editor, please note that you have to prefix all Hydra functions with hydra. to avoid conflicts with Topos functions. For example, osc() becomes hydra.osc(). + +${makeExample("Hydra namespace", `hydra.voronoi(20).out()`, true)} + ## GIF player Topos embeds a small .gif picture player with a small API. GIFs are automatically fading out after the given duration. Look at the following example: @@ -63,7 +82,7 @@ beat(0.25)::gif({ posX: ir(1,1200), // CSS Horizontal Position posY: ir(1, 800), // CSS Vertical Position `, - true, + true )} `; }; diff --git a/src/main.ts b/src/main.ts index fcd60a8..1d3721a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -222,7 +222,7 @@ export class Editor { updateKnownUniversesView = () => { let itemTemplate = document.getElementById( - "ui-known-universe-item-template", + "ui-known-universe-item-template" ) as HTMLTemplateElement; if (!itemTemplate) { console.warn("Missing template #ui-known-universe-item-template"); @@ -250,10 +250,10 @@ export class Editor { item .querySelector(".delete-universe") ?.addEventListener("click", () => - api._deleteUniverseFromInterface(it), + api._deleteUniverseFromInterface(it) ); return item; - }), + }) ); existing_universes.innerHTML = ""; @@ -334,7 +334,7 @@ export class Editor { this.view.dispatch({ effects: this.chosenLanguage.reconfigure( - this.editor_mode == "notes" ? [markdown()] : [javascript()], + this.editor_mode == "notes" ? [markdown()] : [javascript()] ), }); @@ -343,7 +343,7 @@ export class Editor { setButtonHighlighting( button: "play" | "pause" | "stop" | "clear", - highlight: boolean, + highlight: boolean ) { document.getElementById("play-label")!.textContent = button !== "pause" ? "Pause" : "Play"; @@ -391,7 +391,7 @@ export class Editor { // All other buttons must lose the highlighting document .querySelectorAll( - possible_selectors.filter((_, index) => index != selector).join(","), + possible_selectors.filter((_, index) => index != selector).join(",") ) .forEach((button) => { button.children[0].classList.remove("animate-pulse"); @@ -437,28 +437,28 @@ export class Editor { flashBackground(color: string, duration: number): void { const domElement = this.view.dom; const gutters = domElement.getElementsByClassName( - "cm-gutter", + "cm-gutter" ) as HTMLCollectionOf; domElement.classList.add("fluid-bg-transition"); Array.from(gutters).forEach((gutter) => - gutter.classList.add("fluid-bg-transition"), + gutter.classList.add("fluid-bg-transition") ); domElement.style.backgroundColor = color; Array.from(gutters).forEach( - (gutter) => (gutter.style.backgroundColor = color), + (gutter) => (gutter.style.backgroundColor = color) ); setTimeout(() => { domElement.style.backgroundColor = ""; Array.from(gutters).forEach( - (gutter) => (gutter.style.backgroundColor = ""), + (gutter) => (gutter.style.backgroundColor = "") ); domElement.classList.remove("fluid-bg-transition"); Array.from(gutters).forEach((gutter) => - gutter.classList.remove("fluid-bg-transition"), + gutter.classList.remove("fluid-bg-transition") ); }, duration); } @@ -466,7 +466,7 @@ export class Editor { private initializeElements(): void { for (const [key, value] of Object.entries(singleElements)) { this.interface[key] = document.getElementById( - value, + value ) as ElementMap[keyof ElementMap]; } } @@ -474,7 +474,7 @@ export class Editor { private initializeButtonGroups(): void { for (const [key, ids] of Object.entries(buttonGroups)) { this.buttonElements[key] = ids.map( - (id) => document.getElementById(id) as HTMLButtonElement, + (id) => document.getElementById(id) as HTMLButtonElement ); } } @@ -501,20 +501,19 @@ export class Editor { enableStreamCapture: false, }); this.hydra = this.hydra_backend.synth; + (globalThis as any).hydra = this.hydra; + this.hydra.setResolution(1024, 768); } private setCanvas(canvas: HTMLCanvasElement): void { if (!canvas) return; const ctx = canvas.getContext("2d"); - const dpr = window.devicePixelRatio || 1; - // Assuming the canvas takes up the whole window - canvas.width = window.innerWidth * dpr * 0.25; - canvas.height = window.innerHeight * dpr * 0.25; - + canvas.width = window.innerWidth * dpr; + canvas.height = window.innerHeight * dpr; if (ctx) { - ctx.scale(dpr * 0.5, dpr * 0.5); + ctx.scale(dpr, dpr); } } }