hylogen 0.1.0.6 → 0.1.0.8
raw patch · 5 files changed
+136/−88 lines, 5 filesdep +fsnotifydep −hinotifyPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: fsnotify
Dependencies removed: hinotify
API changes (from Hackage documentation)
+ Hylogen.Globals: mix :: Vec1 -> Vec4 -> Vec4 -> Vec4
+ Hylogen.Globals: resolution :: Vec2
+ Hylogen.Globals: vec2 :: (Show tc, ConstructFrom tc Vec2) => tc -> Vec2
+ Hylogen.Globals: vec3 :: (Show tc, ConstructFrom tc Vec3) => tc -> Vec3
+ Hylogen.Globals: vec4 :: (Show tc, ConstructFrom tc Vec4) => tc -> Vec4
+ Hylogen.Types: Bcomp_ :: String -> Vec1 -> Vec1 -> Booly
+ Hylogen.Types: Dot :: a -> a -> Vec1
+ Hylogen.Types: instance Data.VectorSpace.InnerSpace Hylogen.Types.Vec1
+ Hylogen.Types: instance Data.VectorSpace.InnerSpace Hylogen.Types.Vec2
+ Hylogen.Types: instance Data.VectorSpace.InnerSpace Hylogen.Types.Vec3
+ Hylogen.Types: instance Data.VectorSpace.InnerSpace Hylogen.Types.Vec4
+ Hylogen.Types: toList :: HyloPrim v => v -> [Vec1]
- Hylogen.Types: Vec2 :: (Vec1, Vec1) -> Vec2
+ Hylogen.Types: Vec2 :: tc -> Vec2
- Hylogen.Types: Vec3 :: (Vec1, Vec1, Vec1) -> Vec3
+ Hylogen.Types: Vec3 :: tc -> Vec3
- Hylogen.Types: Vec4 :: (Vec1, Vec1, Vec1, Vec1) -> Vec4
+ Hylogen.Types: Vec4 :: tc -> Vec4
- Hylogen.Types: vec :: HyloPrim v => HyloConstructor v -> v
+ Hylogen.Types: vec :: (HyloPrim v, Show tc, ConstructFrom tc v) => tc -> v
Files
- app/Main.hs +12/−15
- app/index.html +53/−54
- hylogen.cabal +2/−2
- src/Hylogen/Globals.hs +15/−0
- src/Hylogen/Types.hs +54/−17
app/Main.hs view
@@ -17,8 +17,9 @@ import Network.WebSockets import System.Environment (getArgs) import System.FilePath-import System.INotify+import System.FSNotify import System.Process+ -- import System.Random main :: IO ()@@ -27,25 +28,21 @@ _ -> error "Name a file to watch!" main' :: FilePath -> IO ()-main' pathToWatch = do+main' pathToWatch = withManager $ \mgr -> do _ <- forkIO $ serveIndex- runServer "127.0.0.1" 8080 $ handleConnection pathToWatch+ runServer "127.0.0.1" 8080 $ handleConnection pathToWatch mgr -handleConnection :: FilePath -> PendingConnection -> IO ()-handleConnection pathToWatch pending = do+handleConnection :: FilePath -> WatchManager -> PendingConnection -> IO ()+handleConnection pathToWatch mgr pending = do let (dirToWatch, fileToWatch) = splitFileName pathToWatch- inotify <- initINotify- print inotify connection <- acceptRequest pending+ (sendTextData connection . T.pack) =<< getNewSource pathToWatch- -- withINotify $ \inotify ->- _ <- addWatch inotify [Modify] dirToWatch $ \case- Modified False (Just f) | f == fileToWatch ->- (sendTextData connection . T.pack) =<< getNewSource pathToWatch- _ -> return ()--- print wd--- removeWatch wd--- receiveDataMessage connection++ let onChange e = case e of+ Modified _ _ -> (sendTextData connection . T.pack) =<< getNewSource pathToWatch+ _ -> return ()+ _ <- watchDir mgr dirToWatch (const True) onChange _ <- getLine -- temp hack to keep the socket open return ()
app/index.html view
@@ -85,34 +85,31 @@ <canvas id="canvas"></canvas> <script>- const vsSource = `-attribute vec3 aPosition;-varying vec2 uvN;-void main() {- gl_Position = vec4(aPosition, 1.0);- uvN = aPosition.xy;-}-`;- const fsHeader=`-precision mediump float;-const float pi = 3.141592653589793238462643383;-uniform float time;-uniform vec2 mouse;-uniform vec4 audio;-uniform sampler2D backBuffer;-varying vec2 uvN;--vec2 uv() {- return 0.5 * uvN + 0.5;-}+ var vsSource = [ "attribute vec3 aPosition;"+ , "varying vec2 uvN;"+ , "void main() {"+ , " gl_Position = vec4(aPosition, 1.0);"+ , " uvN = aPosition.xy;"+ , "}"+ ].join("\n"); -`+ var fsHeader= [ "precision mediump float;"+ , "const float pi = 3.141592653589793238462643383;"+ , "uniform float time;"+ , "uniform vec2 mouse;"+ , "uniform vec2 resolution;"+ , "uniform vec4 audio;"+ , "uniform sampler2D backBuffer;"+ , "varying vec2 uvN;"+ , "vec2 uv() {"+ , " return 0.5 * uvN + 0.5;"+ , "}"+ ].join("\n"); - const initialFsSource = `-void main() {- gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);-}-`;+ var initialFsSource = [ "void main() {"+ , " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);"+ , "}"+ ].join("\n"); function loadProgram (gl, state, vsSource, fsSource) {@@ -123,13 +120,13 @@ function compileShader (gl, source, shaderType) { //assert(shaderType === gl.FRAGMENT_SHADER || shaderType === g.VERTEXT_SHADER); - let shader = gl.createShader(shaderType);+ var shader = gl.createShader(shaderType); gl.shaderSource(shader, source); gl.compileShader(shader); - let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);+ var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); if (!success) { console.log(source); throw "could not compile shader:" + gl.getShaderInfoLog(shader);@@ -140,18 +137,18 @@ - let vs = compileShader(gl, vsSource, gl.VERTEX_SHADER);- let fs = compileShader(gl, fsSource, gl.FRAGMENT_SHADER);+ var vs = compileShader(gl, vsSource, gl.VERTEX_SHADER);+ var fs = compileShader(gl, fsSource, gl.FRAGMENT_SHADER); - let program = gl.createProgram();+ var program = gl.createProgram(); gl.attachShader(program, vs); gl.attachShader(program, fs); gl.linkProgram(program); - let success = gl.getProgramParameter(program, gl.LINK_STATUS);+ var success = gl.getProgramParameter(program, gl.LINK_STATUS); if (!success) { throw ("program failed to link:" + gl.getProgramInfoLog(program)); }@@ -171,7 +168,7 @@ // backBuffer stuff function createTarget() {- let target = {+ var target = { texture: gl.createTexture(), framebuffer: gl.createFramebuffer() };@@ -201,18 +198,20 @@ gl.time = gl.getUniformLocation(program, "time"); gl.mouse = gl.getUniformLocation(program, "mouse"); gl.audio = gl.getUniformLocation(program, "audio");+ gl.resolution = gl.getUniformLocation(program, "resolution"); gl.backBuffer = gl.getUniformLocation(program, "backBuffer"); draw(gl, state); if (state.animationFrameRequest === null) {- state.animationFrameRequest = requestAnimationFrame(() => animate(gl, state));+ state.animationFrameRequest = requestAnimationFrame(function() {animate(gl, state);}); } } function draw (gl, state) { gl.uniform1f(gl.time, (new Date().getTime() / 1000 - state.time0)); gl.uniform2f(gl.mouse, state.mouse.x, state.mouse.y);+ gl.uniform2f(gl.resolution, WIDTH, HEIGHT); gl.uniform4f(gl.audio, state.audio.low, state.audio.mid, state.audio.upper, state.audio.high); gl.uniform1i(gl.backBuffer, 0); // Do I need to check for null?@@ -235,7 +234,7 @@ function animate (gl, state) { draw(gl, state);- state.animationFrameRequest = requestAnimationFrame(() => animate(gl, state));+ state.animationFrameRequest = requestAnimationFrame(function() { animate(gl, state);}); }; @@ -250,14 +249,14 @@ function setMouse (event) {- let r = event.target.getBoundingClientRect();+ var r = event.target.getBoundingClientRect(); state.mouse.x = (event.clientX - r.left) / (r.right - r.left) * 2 -1; state.mouse.y = (event.clientY - r.bottom) / (r.top - r.bottom) * 2 - 1; }; /* canvas.onmousedown = (event) => setMouse(event, 1); */ /* canvas.onmouseup = (event) => setMouse(event, 0); */ - canvas.onmousemove = (event) => setMouse(event);+ canvas.onmousemove = setMouse; state.mouse = {x: 0, y: 0}; @@ -265,14 +264,14 @@ state.audioAgain = null; function onAccept (stream) {- let audioCtx = new (window.AudioContext || window.webkitAudioContext)();- let source = audioCtx.createMediaStreamSource(stream);- let analyser = audioCtx.createAnalyser();+ var audioCtx = new (window.AudioContext || window.webkitAudioContext)();+ var source = audioCtx.createMediaStreamSource(stream);+ var analyser = audioCtx.createAnalyser(); source.connect(analyser); analyser.fftSize = 512;- let bufferLength = analyser.frequencyBinCount;- let dataArray = new Uint8Array(bufferLength);+ var bufferLength = analyser.frequencyBinCount;+ var dataArray = new Uint8Array(bufferLength); function toAudio() {@@ -280,8 +279,8 @@ analyser.getByteFrequencyData(dataArray); // Taken from The_Force- let k = 0, f = 0.0;- let a = 5, b = 11, c = 24, d = bufferLength, i = 0;+ var k = 0, f = 0.0;+ var a = 5, b = 11, c = 24, d = bufferLength, i = 0; for(; i < a; i++) { f += dataArray[i];@@ -332,20 +331,20 @@ // stateful variables - const canvas = document.getElementById("canvas");- let WIDTH = Math.max(window.innerHeight, window.innerWidth);- let HEIGHT = Math.max(window.innerHeight, window.innerWidth);+ var canvas = document.getElementById("canvas");+ var WIDTH = Math.max(window.innerHeight, window.innerWidth);+ var HEIGHT = Math.max(window.innerHeight, window.innerWidth); canvas.width = WIDTH; canvas.height = HEIGHT; - const gl = canvas.getContext("webgl");+ var gl = canvas.getContext("webgl"); - const state = {};+ var state = {}; setupState(state, canvas); - loadProgram (gl, state, vsSource, fsHeader + initialFsSource);+ loadProgram (gl, state, vsSource, fsHeader + "\n" + initialFsSource); function fadeOut(elem) {@@ -356,13 +355,13 @@ } function connectToHylogen() {- const wsConn = new WebSocket("ws://localhost:8080/");+ var wsConn = new WebSocket("ws://localhost:8080/"); wsConn.onopen = function() {- const landing = document.getElementById("landing");+ var landing = document.getElementById("landing"); if (landing) { fadeOut(document.getElementById("bg"));- window.setTimeout(() => {fadeOut(landing);}, 500);+ window.setTimeout(function() {fadeOut(landing);}, 500); } console.log('websocket opened'); @@ -375,7 +374,7 @@ wsConn.onmessage = function (m) { console.log(m.data);- loadProgram(gl, state, vsSource, fsHeader + m.data);+ loadProgram(gl, state, vsSource, fsHeader + "\n" + m.data); }; }
hylogen.cabal view
@@ -1,5 +1,5 @@ name: hylogen-version: 0.1.0.6+version: 0.1.0.8 synopsis: an EDSL for live-coding fragment shaders description: an EDSL for live-coding fragment shaders homepage: https://github.com/sleexyz/hylogen@@ -28,7 +28,7 @@ build-depends: base , bytestring , filepath- , hinotify+ , fsnotify , network , process , random
src/Hylogen/Globals.hs view
@@ -3,8 +3,17 @@ module Hylogen.Globals where import Hylogen.Types+import Data.VectorSpace +vec2 :: (Show tc, ConstructFrom tc Vec2) => tc -> Vec2+vec2 = Vec2 +vec3 :: (Show tc, ConstructFrom tc Vec3) => tc -> Vec3+vec3 = Vec3++vec4 :: (Show tc, ConstructFrom tc Vec4) => tc -> Vec4+vec4 = Vec4+ inverseSqrt :: (HyloPrim a) => a -> a inverseSqrt = vuop "inversesqrt" @@ -43,6 +52,9 @@ uvN :: Vec2 uvN = V2u "uvN" +resolution :: Vec2+resolution = V2u "resolution"+ mouse :: Vec2 mouse = V2u "mouse" @@ -52,6 +64,9 @@ backBuffer :: Texture backBuffer = Tu "backBuffer"++mix :: Vec1 -> Vec4 -> Vec4 -> Vec4+mix p a b = p *^ a + (1 - p) *^ b -- | Booly's
src/Hylogen/Types.hs view
@@ -1,25 +1,41 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE NoMonoLocalBinds #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ExtendedDefaultRules #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE MultiParamTypeClasses #-} module Hylogen.Types where + import Data.Monoid import Data.VectorSpace+import GHC.Exts (Constraint) --- | Darn I need injective type families.. waiting for GHC8-type family HyloConstructor v where- HyloConstructor Vec1 = Float- HyloConstructor Vec2 = (Vec1, Vec1)- HyloConstructor Vec3 = (Vec1, Vec1, Vec1)- HyloConstructor Vec4 = (Vec1, Vec1, Vec1, Vec1) +type family (ConstructFrom tc hprim) :: Constraint where+ ConstructFrom a Vec1 = a ~ Float+ ConstructFrom (a, b) Vec2 = (a ~ Vec1, b ~ Vec1)++ ConstructFrom (a, b, c) Vec3 = (a ~ Vec1, b ~ Vec1, c ~ Vec1)+ ConstructFrom (Vec2, b) Vec3 = (b ~ Vec1)+ ConstructFrom (a, Vec2) Vec3 = (a ~ Vec1)++ ConstructFrom (a, b, c, d) Vec4 = (a ~ Vec1, b ~ Vec1, c ~ Vec1, d ~ Vec1)+ ConstructFrom (Vec3, b) Vec4 = (b ~ Vec1)+ ConstructFrom (Vec2, b) Vec4 = (b ~ Vec2)+ ConstructFrom (a, Vec3) Vec4 = (a ~ Vec1)+ ConstructFrom (a, Vec2, c) Vec4 = (a ~ Vec1, c ~ Vec1)+ ConstructFrom (Vec2, b, c) Vec4 = (b ~ Vec1, c ~ Vec1)+ ConstructFrom (a, b, Vec2) Vec4 = (a ~ Vec1, b ~ Vec1)++ class (Show v) => HyloPrim v where- vec :: HyloConstructor v -> v+ vec :: (Show tc, ConstructFrom tc v) => tc -> v vu :: String -> v vuop :: String -> v -> v vuoppre :: String -> v -> v@@ -27,15 +43,16 @@ vboppre :: String -> v -> v -> v select :: Booly -> v -> v -> v fromVec1 :: Vec1 -> v+ toList :: v -> [Vec1] + class Show a => HasX a class HasX a => HasY a class HasY a => HasZ a class HasZ a => HasW a - data Vec1 where Vec1 :: Float -> Vec1 V1u :: String -> Vec1@@ -44,6 +61,7 @@ V1bop :: String -> Vec1 -> Vec1 -> Vec1 V1boppre :: String -> Vec1 -> Vec1 -> Vec1 V1select :: Booly -> Vec1 -> Vec1 -> Vec1+ Dot :: (HyloPrim a) => a -> a -> Vec1 X :: (HasX a) => a -> Vec1 Y :: (HasY a) => a -> Vec1 Z :: (HasZ a) => a -> Vec1@@ -60,6 +78,7 @@ V1bop b x y -> "(" <> show x <> " " <> b <> " " <> show y <> ")" V1boppre b x y -> b <> "(" <> show x <> ", " <> show y <> ")" V1select b x y -> "( " <> show b <> " ? " <> show x <> " : " <> show y <> ")"+ Dot x y -> "dot(" <> show x <> ", " <> show y <> ")" X x -> show x <> ".x" Y x -> show x <> ".y" Z x -> show x <> ".z"@@ -75,6 +94,7 @@ vboppre = V1boppre select = V1select fromVec1 = id+ toList x = [x] instance Num Vec1 where (+) = vbop "+"@@ -119,10 +139,13 @@ type Scalar Vec1 = Vec1 a *^ b = a * b +instance InnerSpace Vec1 where+ (<.>) = Dot+ -- | Vec2: data Vec2 where- Vec2 :: (Vec1, Vec1) -> Vec2+ Vec2 :: (Show tc, ConstructFrom tc Vec2) => tc -> Vec2 V2u :: String -> Vec2 V2uop :: String -> Vec2 -> Vec2 V2uoppre :: String -> Vec2 -> Vec2@@ -140,11 +163,12 @@ vboppre = V2boppre select = V2select fromVec1 x = Vec2 (x, x)+ toList x = [X x, Y x] instance Show Vec2 where show expr = case expr of- Vec2 (x, y) -> "vec2(" <> show x <> ", " <> show y <> ")"+ Vec2 tc -> "vec2" <> show tc V2u x -> x V2uop u x -> u <> "(" <> show x <> ")" V2uoppre u x -> "(" <> u <> show x <> ")"@@ -196,6 +220,9 @@ type Scalar Vec2 = Vec1 a *^ b = V2bops "*" a b +instance InnerSpace Vec2 where+ (<.>) = Dot+ instance HasX Vec2 instance HasY Vec2 @@ -203,7 +230,7 @@ -- | Vec3: data Vec3 where- Vec3 :: (Vec1, Vec1, Vec1) -> Vec3+ Vec3 :: (Show tc, ConstructFrom tc Vec3) => tc -> Vec3 V3u :: String -> Vec3 V3uop :: String -> Vec3 -> Vec3 V3uoppre :: String -> Vec3 -> Vec3@@ -221,10 +248,11 @@ vboppre = V3boppre select = V3select fromVec1 x = Vec3 (x, x, x)+ toList x = [X x, Y x, Z x] instance Show Vec3 where show expr = case expr of- Vec3 (x, y, z) -> "vec3(" <> show x <> ", " <> show y <> ", " <> show z <> ")"+ Vec3 tc -> "vec3" <> show tc V3u x -> x V3uop u x -> u <> "(" <> show x <> ")" V3uoppre u x -> "(" <> u <> show x <> ")"@@ -276,6 +304,9 @@ type Scalar Vec3 = Vec1 a *^ b = V3bops "*" a b +instance InnerSpace Vec3 where+ (<.>) = Dot+ instance HasX Vec3 instance HasY Vec3 instance HasZ Vec3@@ -285,7 +316,7 @@ -- | Vec4: data Vec4 where- Vec4 :: (Vec1, Vec1, Vec1, Vec1) -> Vec4+ Vec4 :: (Show tc, ConstructFrom tc Vec4) => tc -> Vec4 V4u :: String -> Vec4 V4uop :: String -> Vec4 -> Vec4 V4uoppre :: String -> Vec4 -> Vec4@@ -305,10 +336,11 @@ vboppre = V4boppre select = V4select fromVec1 x = Vec4 (x, x, x, x)+ toList x = [X x, Y x, Z x, W x] instance Show Vec4 where show expr = case expr of- Vec4 (x, y, z, w) -> "vec4(" <> show x <> ", " <> show y <> ", " <> show z <> ", " <> show w <> ")"+ Vec4 tc -> "vec4" <> show tc V4u x -> x V4uop u x -> u <> "(" <> show x <> ")" V4uoppre u x -> "(" <> u <> show x <> ")"@@ -361,6 +393,9 @@ type Scalar Vec4 = Vec1 a *^ b = V4bops "*" a b +instance InnerSpace Vec4 where+ (<.>) = Dot+ instance HasX Vec4 instance HasY Vec4 instance HasZ Vec4@@ -381,6 +416,7 @@ Buoppre :: String -> Booly -> Booly Bbop :: String -> Booly -> Booly -> Booly Bcomp :: (HyloPrim a) => String -> a -> a -> Booly+ Bcomp_ :: String -> Vec1 -> Vec1 -> Booly instance Show Booly where show expr = case expr of@@ -388,7 +424,8 @@ Buop u x -> u <> "(" <> show x <> ")" Buoppre u x -> "(" <> u <> show x <> ")" Bbop u x y -> "(" <> show x <> " " <> u <> " " <> show y <> ")"- Bcomp u x y -> "(" <> show x <> " " <> u <> " " <> show y <> ")"+ Bcomp u x y -> show . product $ zipWith (Bcomp_ u) (toList x) (toList y)+ Bcomp_ u x y -> "(" <> show x <> " " <> u <> " " <> show y <> ")" instance Num Booly where (+) = Bbop "||"