User Tools

Site Tools


folkarc:touch

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
folkarc:touch [2023/11/03 19:50] discordfolkarc:touch [2024/09/15 19:11] (current) discord
Line 5: Line 5:
  
 <file tcl> <file tcl>
-# Tablet Touch Handler +# Tablet Touch Handler 9000 - Revamped live at folk0 on Jun 11 2024
 Wish the web server handles route "/tablet" with handler { Wish the web server handles route "/tablet" with handler {
     html {     html {
 <html> <html>
 + 
 <body > <body >
 <span id="status">Status</span> <span id="status">Status</span>
 +<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDBtbSIgaGVpZ2h0PSIxMDBtbSIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgo8cGF0aCBzdHlsZT0iZmlsbDojZmZmZmZmOyBzdHJva2U6bm9uZTsiIGQ9Ik0wIDBMMCAxMEwyMCAxMEwyMCAwTDAgMHoiPjwvcGF0aD4KPHBhdGggc3R5bGU9ImZpbGw6IzAwMDAwMDsgc3Ryb2tlOm5vbmU7IiBkPSJNMjAgMEwyMCAxMEwwIDEwTDAgMjBMMTAgMjBMMTAgNDBMMCA0MEwwIDYwTDEwIDYwTDEwIDcwTDAgNzBMMCAxMDBMNTAgMTAwTDUwIDkwTDYwIDkwTDYwIDEwMEw3MCAxMDBMNzAgOTBMOTAgOTBMOTAgMTAwTDEwMCAxMDBMMTAwIDYwTDkwIDYwTDkwIDQwTDEwMCA0MEwxMDAgMzBMOTAgMzBMOTAgMjBMMTAwIDIwTDEwMCAwTDkwIDBMOTAgMTBMODAgMTBMODAgMEwyMCAweiI+PC9wYXRoPgo8cGF0aCBzdHlsZT0iZmlsbDojZmZmZmZmOyBzdHJva2U6bm9uZTsiIGQ9Ik04MCAwTDgwIDEwTDkwIDEwTDkwIDBMODAgME0wIDIwTDAgNDBMMTAgNDBMMTAgMjBMMCAyME0yMCAyMEwyMCA4MEw4MCA4MEw4MCAyMEwyMCAyME05MCAyMEw5MCAzMEwxMDAgMzBMMTAwIDIwTDkwIDIweiI+PC9wYXRoPgo8cGF0aCBzdHlsZT0iZmlsbDojMDAwMDAwOyBzdHJva2U6bm9uZTsiIGQ9Ik00MCAzMEw0MCA0MEwzMCA0MEwzMCA1MEw1MCA1MEw1MCAzMEw0MCAzME02MCA0MEw2MCA1MEw3MCA1MEw3MCA0MEw2MCA0MHoiPjwvcGF0aD4KPHBhdGggc3R5bGU9ImZpbGw6I2ZmZmZmZjsgc3Ryb2tlOm5vbmU7IiBkPSJNOTAgNDBMOTAgNjBMMTAwIDYwTDEwMCA0MEw5MCA0ME0wIDYwTDAgNzBMMTAgNzBMMTAgNjBMMCA2MHoiPjwvcGF0aD4KPHBhdGggc3R5bGU9ImZpbGw6IzAwMDAwMDsgc3Ryb2tlOm5vbmU7IiBkPSJNNjAgNjBMNjAgNzBMNzAgNzBMNzAgNjBMNjAgNjB6Ij48L3BhdGg+CjxwYXRoIHN0eWxlPSJmaWxsOiNmZmZmZmY7IHN0cm9rZTpub25lOyIgZD0iTTUwIDkwTDUwIDEwMEw2MCAxMDBMNjAgOTBMNTAgOTBNNzAgOTBMNzAgMTAwTDkwIDEwMEw5MCA5MEw3MCA5MHoiPjwvcGF0aD4KPC9zdmc+" style="position: absolute;top: 0;right: 0; width: 30%; pointer-events:none" />
 +<button onClick="openFullscreen()">Fullscreen</button>
 <canvas id="body" style="width: 100%; height: 100%; border-style: solid;"></canvas> <canvas id="body" style="width: 100%; height: 100%; border-style: solid;"></canvas>
 +
 </body> </body>
 <script> <script>
Line 19: Line 21:
 let width = el.getBoundingClientRect().width; let width = el.getBoundingClientRect().width;
 let height = el.getBoundingClientRect().height; let height = el.getBoundingClientRect().height;
 + 
 const program = "tablet-touch-handler-" + ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); const program = "tablet-touch-handler-" + ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
 + 
 function touch(event) { function touch(event) {
     event.preventDefault();      event.preventDefault(); 
Line 28: Line 30:
     }     }
 } }
 +
 +/* Get the documentElement (<html>) to display the page in fullscreen */
 +let elem = document.documentElement;
 +
 +/* View in fullscreen */
 +function openFullscreen() {
 +  if (elem.requestFullscreen) {
 +    elem.requestFullscreen();
 +  } else if (elem.webkitRequestFullscreen) { /* Safari */
 +    elem.webkitRequestFullscreen();
 +  } else if (elem.msRequestFullscreen) { /* IE11 */
 +    elem.msRequestFullscreen();
 +  }
 +}
 +
 +
 el.addEventListener("touchstart", touch, false); el.addEventListener("touchstart", touch, false);
 el.addEventListener("touchmove", touch, false); el.addEventListener("touchmove", touch, false);
 + 
 function stop_touch(event) { send(`Commit { Claim ${program} has no touch }`); } function stop_touch(event) { send(`Commit { Claim ${program} has no touch }`); }
 el.addEventListener("touchend", stop_touch, false); el.addEventListener("touchend", stop_touch, false);
 + 
 let ws; let ws;
 let send; let send;
Line 39: Line 57:
  ws = new WebSocket(window.location.origin.replace("http", "ws") + "/ws");  ws = new WebSocket(window.location.origin.replace("http", "ws") + "/ws");
  send = function(s) { ws.send(s); }  send = function(s) { ws.send(s); }
 + 
  ws.onopen = () => { document.getElementById('status').innerHTML = "<span style=background-color:seagreen;color:white;>Connnected</span>"; };  ws.onopen = () => { document.getElementById('status').innerHTML = "<span style=background-color:seagreen;color:white;>Connnected</span>"; };
  ws.onclose = window.onbeforeunload = () => {  ws.onclose = window.onbeforeunload = () => {
      document.getElementById('status').innerHTML = "<span style=background-color:red;color:white;>Disconnnected</span>";      document.getElementById('status').innerHTML = "<span style=background-color:red;color:white;>Disconnnected</span>";
 + 
      send(`Commit { Claim ${program} has no touch }`);      send(`Commit { Claim ${program} has no touch }`);
      setTimeout(() => { wsConnect(); }, 1000);      setTimeout(() => { wsConnect(); }, 1000);
Line 66: Line 84:
 }; };
 wsConnect(); wsConnect();
 + 
 </script> </script>
 </html> </html>
 + 
 } }
 +}
 +
 +
 +When tag 48712 has corners /corners/ {
 +    # Setting aside this tag space (48600 to 48713) for calibration.
 +
 +    set tagCorners [lmap p $corners {::cameraToProjector $p}]
 +
 +    set vecBottom [sub [lindex $tagCorners 1] [lindex $tagCorners 0]]
 +    set vecRight [sub [lindex $tagCorners 2] [lindex $tagCorners 1]]
 +
 +    set offsets {{-4.7 -2.6} {1 -2.6} {1 0.8} {-4.7 0.8}}
 +    set scales [matmul $offsets [list $vecBottom $vecRight]]
 +    set corners [add $tagCorners $scales]
 +
 +    set edges [list]
 +    for {set i 0} {$i < [llength $corners]} {incr i} {
 +        if {$i > 0} { lappend edges [list [expr {$i - 1}] $i] }
 +    }
 +    lappend edges [list [expr {[llength $corners] - 1}] 0]
 +
 +    set angle [expr {atan2(-[lindex $vecBottom 1], [lindex $vecBottom 0])}]
 +    set region [region create $corners $edges $angle]
 +
 +    Claim 48712 has region $region
 +    Claim tag 48712 is a tag
 +    Claim 48712 is a tablet
 +    
 } }
 </file> </file>
Line 83: Line 129:
     Wish to draw a circle with x $posX y $posY radius 20 thickness 6 color white     Wish to draw a circle with x $posX y $posY radius 20 thickness 6 color white
          
 +}
 +</file>
 +
 +Tablet pointer!
 +
 +<file tcl>
 +set MARGIN 0.2
 +set LENGTH 0.5
 +
 +When /thing/ claims /thing2/ has touch number /i/ with x /x/ and y /y/ & 48712 has region /r/ {
 +
 +    if {$x < $MARGIN && $y > $MARGIN && $y < [expr {1 - $MARGIN}] } { # left
 +        Wish 48712 points left with length $LENGTH
 +    } elseif {$x > [expr {1 - $MARGIN}] && $y > $MARGIN && $y < [expr {1 - $MARGIN}] } { # right
 +        Wish 48712 points right with length $LENGTH
 +    } elseif {$y > [expr {1 - $MARGIN}] } { # down
 +        Wish 48712 points down with length $LENGTH
 +    } elseif {$y < $MARGIN } { # up
 +        Wish 48712 points up with length $LENGTH
 +    }
 +
 +}
 +</file>
 +
 +If you have [[:supercollider|Supercollider]] set up, play this little theremin!
 +
 +<file tcl>
 +# Supercollider touch demo
 +
 +When /thing/ claims /thing2/ has touch number /i/ with x /x/ and y /y/ {
 +    set freq [expr {int($Display::WIDTH * $x) % $Display::WIDTH} / 2.]
 +
 +    Wish Supercollider sound $thing2-touch-noise attr freq is $freq
 +    
 +    Wish $this is labelled "$freq Hz"
 +
 +    Wish Supercollider plays sound $thing2-touch-noise {
 +        arg freq = 0;
 +        var envgen;
 +        envgen = EnvGen.kr(Env.adsr(sustainLevel: 0.2));
 +        Pan2.ar(SinOsc.ar(freq) * 0.5 * envgen, 1.0);
 +    }
 } }
 </file> </file>
  
folkarc/touch.1699041013.txt.gz · Last modified: 2023/11/03 19:50 by discord

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki