This commit is contained in:
Sam Neurohack 2019-03-19 14:24:11 +01:00
parent 89462381db
commit 172ae79105
33 changed files with 1245 additions and 311 deletions

17
LJ.conf
View File

@ -1,5 +1,5 @@
[General]
lasernumber = 2
lasernumber = 4
debug = 0
ljayserverip = 127.0.0.1
nozoscip = 127.0.0.1
@ -58,9 +58,9 @@ swapx = 1
swapy = 1
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.],
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[laser3]
color = -1
@ -77,9 +77,9 @@ swapx = -1
swapy = -1
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.],
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[plugins]
plugins = {
@ -88,8 +88,9 @@ plugins = {
"planet": {"OSC": 8005, "command": "python3 plugins/planetarium/main.py"},
"words": {"OSC": 8006, "command": "python3 plugins/livewords.py"},
"cycl": {"OSC": 8007, "command": "python3 plugins/textcycl.py"},
"simu": {"OSC": 8008, "command": "python plugins/simu.py"},
"simu": {"OSC": 8008, "command": "python plugins/pysimu.py"},
"bank0": {"OSC": 8010, "command": "python3 plugins/VJing/bank0.py"},
"pose": {"OSC": 8011, "command": "python3 plugins/VJing/idiotia.py"},
"ljpong": {"OSC": 8020, "command": "python plugins/games/ljpong/main.py"},
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py"}
}

1
LJ.py Symbolic link
View File

@ -0,0 +1 @@
main.py

View File

@ -7,19 +7,28 @@ LICENCE : CC BY
![LJ](http://www.teamlaser.fr/thsf/images/fulls/THSF9-33.jpg)
A software laser server with GUI for up to 4 lasers live actions. Think creative like Laser "battles", planetarium,...
A software laser server with GUI for up to 4 lasers live actions. Think creative like Laser "battles", planetarium, sharing available lasers in demoparties for competition, ...
LJ has 3 main components :
LJ has 5 main components :
- A "tracer" per etherdream/laser that take its point list, correct geometry, recompute in etherdreams coordinates, send it to its controller,... and report etherdream status to the manager.
- A "tracer" per etherdream/laser that take its given point list, correct geometry, recompute in laser controller coordinates, send it to its controller and report its status to the "manager".
- A "manager" that talk to all tracers (which client number point lists to draw, new geometry correction,...), handle the webui functions, OSC commands,...
- To share the lasers between people, LJ accept up to 4 virtual "clients" that can simultaneously send one point list per laser. You select in WebUI wich client is actually sent to lasers.
- To share the lasers between people/computers, LJ accept up to 4 virtual "clients" that can simultaneously send one point list per laser. You select in WebUI wich "client" should be used by tracers.
- A web GUI in html, css, and vanilla js. No html server or js framework here : it's complex enough. This GUI has a (currently slow) simulator, but one can used a builtin python simulator (pysimu) or an etherdream/laser emulator (from nannou) to work without physical lasers !!
- A network available database (redis). "Clients" send directly their pointlists to redis and each "tracer" is instructed to get a given pointlist in redis.
4 clients can send 4 pointlists so up to 16 pointlists can be accessed at anytime from anywhere in the network. The server/network/webUI idea allows to share cpu intensive tasks and especially give tracers enough cpu to draw smoothly. Of course all this can happen in one computer. There is no real limits : 4 everything is tested and works smoothly if *you have enough cpu/computers/network ressources*.
It's obviously overkill for one laser in a garage, but for several laserS game events, laserS art, laserS competition, laserS planetarium,... LJ will handle the complexity. Content providers like artists, demomakers,... just need to send points.
Needs at least : an etherdream DAC connected to an ILDA laser, RJ 45 IP network (gigabits only !! no wifi, 100 mpbs doesn't work well with several lasers)
LJ supports Linux and OS X. Windows is unkown but welcome, if someone want to jump in and care about it.
LJ is tested with Firefox, supports Linux and OS X. Windows is unkown but welcome, if someone want to jump in and care about it.
LJ is in dev : versions in this repository will always be core functionnal : accept and draw pointlists. New features can be not fully implemented, wait for the next commit. Any feedback is welcome at any time.
@ -29,6 +38,7 @@ LJ supports Linux and OS X. Windows is unkown but welcome, if someone want to ju
(Doc in progress)
- Laser alignment like in laser mapping.
- OSC and websocket commands. Very cool : LJ can script or be scripted.
- Web ui : In your browser open webui/index.html. Javascript is needed. By default it connect to localhost. If you want to control a remote server, you need to change the uri line in LJ.js.
- Status update every 0.5 seconds : every etherdream DAC state, number of buffer points sent,...
@ -58,11 +68,11 @@ For Linux and OS X :
You probably want redis bound to all network interfaces : comment the bind line in /etc/redis/redis.conf and restart it.
In webui/index.html change the ws ip adress to the server IP if needed.
In webui/index.html change the websocket (ws) ip adress to the server IP if needed.
Using the same idea check all ip address in LJ.conf.
There is a nice ws debug tool websocat.
There is a nice websocket debug tool : websocat.
@ -94,8 +104,7 @@ python main.py -L 1
Run your client
3/ to monitor redis server, there is app for that or :
3/ to monitor redis server, there is an app for that (redis-manager/medis/...) or :
redis-cli monitor
@ -114,7 +123,7 @@ python main.py -r 192.168.1.13 -L 1
node nodeclient.js
4/ to monitor redis server :
4/ to monitor redis server use redis-manager/medis/... or :
redis-cli -h redisserverIP monitor
@ -123,12 +132,13 @@ redis-cli -h redisserverIP monitor
# Plugins
#
LJ comes with different plugins in python 3 :
A "plugin" is a software that send any number of pointlist(s). LJ comes with different plugins in python 3 :
- LiveWords : Fill the input form and it's displayed. One word / laser.
- Textcycl : Cycle some words with adjustable length on one laser.
- Anaglyph : A green/red rotating cube. Try it with green/red 3D glasses !
- Planetarium : A 4 lasers planetarium.
- pySimu : A full speed laser simulator (pygame, python 2.7)
- LaserPong : Our laser Pong is back ! (python 2.7)
@ -137,18 +147,21 @@ LJ comes with different plugins in python 3 :
#
The server approach is based on redis, so you write and run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients).
The server approach is based on redis, so you write and run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients). If you want some interaction with GUI, like in text status area, you also need OSC.
- Read all this readme ;-)
- There is a client and plugin folders with examples in different languages. If you want to do game especially with pygame, see ljpong in plugins/games directory.
- Generate at least one point list array (say a square) with *enough points*, one point is likely to fail for buffering reason.
- Feed your point list array in string format to redis server. i.e use "/pl/0/1" redis key to feed client 0, pointlist 1.
- Tell LJ.conf your plugin configuration : OSC port and command line to start it.
- lj3.py (python 3) and lj.py (python 2.7) have many very useful functions to not reinvent the wheel. Maybe it's better to symlink them in your directory than having a separated copy, to get future enhancements transparently.
- Read the Introduction part in this readme.
- There is a client and plugin folders with examples in different languages.
- Generate at least one point list array (say a square).
- Feed your point list array in string format to redis server.
- Tell LJ.conf your plugin configuration : OSC port and command line to start it ()
#
# Nannou etherdeam simulator
#
(Doc in Progress)
#
@ -160,6 +173,7 @@ The server approach is based on redis, so you write and run your laser client so
- kpps live modification for glitch art.
- A grid style warp correction process in webUI.
- IP change should not need a LJ relaunch
- Way faster WebUI simulator. Use pysimu plugin for full speed.
#
@ -171,9 +185,11 @@ LJ is network based and this is *critical and flickering reason #1* if not manag
Our "always working solution", as we regularly move our gear for different venues :
We use static network configuration. Our Etherdreams controllers have static IPs defined in their SDcard from 192.168.1.1 to 192.168.1.9. Because wifi will always finally sucks for many reasons, our computers (laser server and clients) are *gigabits wired connected* with 192.168.1.10 and after. Don't trust end user gear marketing on wifi, we have a big gigabits switch for laser only stuff. We provide Internet through wifi on different network like 192.168.2.x
- We use static network configuration. Our Etherdreams controllers have static IPs defined in their SDcard from 192.168.1.1 to 192.168.1.9.
Even if etherdreams are 100 Mbits, we use gigabits gear.
- Because wifi will always finally sucks for many reasons, our computers (laser server and clients) are *gigabits wired* with 192.168.1.10 and after. Don't trust end user gear marketing on wifi. We have a big gigabits switch for the *laser only lan*. We provide Internet through wifi on a different network like 192.168.2.x if really needed.
- Again, even if etherdreams are 100 Mbits, we use *gigabits* gear.
By default LJ uses on 127.0.0.1 (localhost) :

View File

@ -87,7 +87,7 @@ import plugins
r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0)
GenericCommands = ["start","ljclient","clientnumber","noteon","pong","mouse","emergency","simu","status","run","nozoid","planet","live","words","ai","bank0","lj"]
GenericCommands = ["start","ljclient","clientnumber","noteon","ljpong","ljwars","mouse","emergency","simu","status","run","nozoid","planet","live","words","ai","bank0","pose","lj","cycl","glyph"]
@ -177,7 +177,6 @@ def handler(oscpath, args):
# 2 incoming cases : generic or specific for a given lasernumber :
# Generic : Commands without a laser number
#if oscpath[1] == "client" or oscpath[1]=="clientnumber" or oscpath[1] =="noteon" or oscpath[1]=="pong" or oscpath[1]=="mouse" or oscpath[1]=="emergency" or oscpath[1]=="simu" or oscpath[1]=="status" or oscpath[1]=="run" or oscpath[1]=="nozoid" or oscpath[1]=="planet" or oscpath[1]=="live" or oscpath[1]=="planet" :
if oscpath[1] in GenericCommands:

View File

@ -385,6 +385,7 @@ def message_received(client, wserver, message):
sendWSall("/"+ plugin + "/start 0")
if gstt.debug >0:
print "plugin", plugin, "didn't answered."
plugins.sendWSall("/status Running...")
'''
if plugins.Send("planet",oscpath):

View File

@ -7,10 +7,11 @@ VJing Bank 0
was Franken for compo laser at coockie 2018 demoparty
0 : many Starfields
0 : Starfields
1 : generic pose animations
2 : Faces
3 : Dancers
4 : IdiotIA
LICENCE : CC
Sam Neurohack, Loloster,
@ -28,6 +29,7 @@ from random import randrange
import redis
import lj3
import sys,time
import os
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
@ -76,11 +78,6 @@ else:
lj3.Config(redisIP,ljclient)
def OSCljclient(value):
# Will receive message address, and message data flattened in s, x, y
print("I got /bank0/ljclient with value", value)
ljclient = value
lj3.LjClient(ljclient)
def hex2rgb(hexcode):
return tuple(map(ord,hexcode[1:].decode('hex')))
@ -440,7 +437,8 @@ CurrentPose = 1
def prepareFACES():
# anim format (name, xpos,ypos, resize, currentframe, totalframe, count, speed)
# anim format (name, xpos, ypos, resize, currentframe, totalframe, count, frame repeat)
# 0 1 2 3 4 5 6 7
# total frame is fetched from directory file count
anims[0] = [['detroit1', 300,300, 100,0,0,0,1]]
@ -470,32 +468,40 @@ def prepareFACES():
#by this one
#thanks to https://stackoverflow.com/questions/19184335/is-there-a-need-for-rangelena
for laseranims in anims:
if debug > 1:
print("anims:",laseranims)
for anim in laseranims:
anim[5]=lengthPOSE(anim[0])
if debug > 1:
print(anim[5])
for anim in laseranims:
anim[5] = lengthPOSE(anim[0])
if debug > 0:
print("anim :", anim)
print("length :", anim[5])
# display the face animation describe in PoseDir
def Faces():
for laseranims in range(3):
for anim in anims[laseranims]:
PL = laseranims
#print PL, anim
dots = []
#print anim, anim[5]
# repeat anim[7] time the same frame
# increase counter [6]
# compare to repeat [7] time the same frame
anim[6] +=1
if anim[6] == anim[7]:
# reset repeat
anim[6] = 0
# increase current frame and compare to total frame
# increase current frame [4]
anim[4] += 1
# compare to total frame [5]
if anim[4] == anim[5]:
anim[4] = 0
@ -509,7 +515,7 @@ def Faces():
for people in range(len(pose_json['people'])):
#lj3.PolyLineOneColor(face(pose), c=color, PL = 0, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
#lj3.rPolyLineOneColor(face(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(browL(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(browR(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(eyeR(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
@ -594,12 +600,107 @@ def Dancers():
PL[PL] = fwork.LinesPL(PL)
'''
# Curve 4 IdiotIA
import json
CurrentPose = 1
def prepareIdiotIA():
# anim format (name, xpos,ypos, resize, currentframe, totalframe, count, speed)
# total frame is fetched from directory file count
anims[0] = [['detroit1', 300,300, 100,0,0,0,1]]
anims[1] = [['detroit1', 400,200, 200,0,0,0,1]]
anims[2] = [['detroit1', 500,200, 300,0,0,0,1]]
'''
# read anims number of frames from disk.
for anim in range(len(anims0)):
anims0[anim][5]= lengthPOSE(anims0[anim][0])
for anim in range(len(anims1)):
anims1[anim][5]= lengthPOSE(anims1[anim][0])
for anim in range(len(anims2)):
anims2[anim][5]= lengthPOSE(anims2[anim][0])
'''
#replace code below
'''
for laseranims in range(3):
if debug > 0:
print "anims:",anims[laseranims],
for anim in range(len(anims[laseranims])):
anims[laseranims][anim][5]= lengthPOSE(anims[laseranims][anim][0])
if debug > 1:
print anims[laseranims][anim][5]
'''
#by this one
#thanks to https://stackoverflow.com/questions/19184335/is-there-a-need-for-rangelena
for laseranims in anims:
if debug > 1:
print("anims:",laseranims)
for anim in laseranims:
anim[5]=lengthPOSE(anim[0])
if debug > 1:
print(anim[5])
# display the face animation describe in PoseDir
def Faces():
for laseranims in range(3):
for anim in anims[laseranims]:
PL = laseranims
#print PL, anim
dots = []
#print anim, anim[5]
# repeat anim[7] time the same frame
anim[6] +=1
if anim[6] == anim[7]:
anim[6] = 0
# increase current frame and compare to total frame
anim[4] += 1
if anim[4] == anim[5]:
anim[4] = 0
posename = 'poses/' + anim[0] + '/' + anim[0] +'-'+str("%05d"%anim[4])+'.json'
posefile = open(posename , 'r')
posedatas = posefile.read()
pose_json = json.loads(posedatas)
# Face
for people in range(len(pose_json['people'])):
#lj3.rPolyLineOneColor(face(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(browL(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(browR(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(eyeR(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(eyeL(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(nose(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(mouth(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.DrawPL(PL)
time.sleep(0.02)
def OSCljclient(value):
# Will receive message address, and message data flattened in s, x, y
print("I got /bank0/ljclient with value", value)
print("Bank0 got /bank0/ljclient with value", value)
ljclient = value
lj3.LjClient(ljclient)
def OSCpl(value):
print("Bank0 got /bank0/pl with value", value)
lj3.WebStatus("Bank0 to pl "+ str(value))
lj3.LjPl(value)
# Dancers, Starfield, Pose, Face
def OSCrun(value):
@ -619,10 +720,6 @@ def WebStatus(message):
lj3.SendLJ("/status",message)
#doit = Starfield
doit = Pose
#doit = Faces
#doit = Dancers
print('Loading Bank0...')
@ -636,15 +733,16 @@ osc_udp_server("127.0.0.1", OSCinPort, "InPort")
osc_method("/bank0/run*", OSCrun)
osc_method("/bank0/ping*", lj3.OSCping)
osc_method("/bank0/ljclient", OSCljclient)
osc_method("/bank0/ljpl", OSCpl)
osc_method("/quit", OSCquit)
'''
import pygame
pygame.init()
Nbpads = pygame.joystick.get_count()
print ("Joypads : ", str(Nbpads))
'''
if Nbpads != 2:
print ('')
@ -652,7 +750,6 @@ if Nbpads != 2:
print ("THIS VERSION NEEDS 2 PADS. PLEASE CONNECT THEM.")
print ('')
sys.exit()
'''
if Nbpads > 1:
@ -678,16 +775,22 @@ if Nbpads > 0:
#print ("Buttons Pad 1 :" , str(numButtons))
'''
anims =[[],[],[],[]]
color = lj3.rgb2int(255,255,255)
prepareSTARFIELD()
preparePOSE()
prepareDANCERS()
#prepareSTARFIELD()
#preparePOSE()
#prepareDANCERS()
prepareFACES()
#doit = Starfield
#doit = Pose
doit = Faces
#doit = Dancers
WebStatus("Bank0 ready.")
print("Bank0 ready")

439
plugins/VJing/idiotia.py Normal file
View File

@ -0,0 +1,439 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
LJ v0.8.1
IdiotIA for THSF 10
Include IdiotIA and Starfields
LICENCE : CC
Sam Neurohack, Loloster,
'''
import math
import numpy as np
import pdb
from datetime import datetime
from random import randrange
import redis
import lj3
import sys,time
import os
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
#from osc4py3 import oscmethod as osm
from osc4py3.oscmethod import *
import argparse
screen_size = [700,700]
xy_center = [screen_size[0]/2,screen_size[1]/2]
message = "LO"
OSCinPort = 8011
redisIP = '127.0.0.1'
ljclient = 0
print ("")
print ("Arguments parsing if needed...")
argsparser = argparse.ArgumentParser(description="Pose bank for LJ")
argsparser.add_argument("-r","--redisIP",help="IP of the Redis server used by LJ (127.0.0.1 by default) ",type=str)
argsparser.add_argument("-c","--client",help="LJ client number (0 by default)",type=int)
argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",type=int)
args = argsparser.parse_args()
if args.verbose:
debug = args.verbose
else:
debug = 0
if args.client:
ljclient = args.client
else:
ljclient = 0
# Redis Computer IP
if args.redisIP != None:
redisIP = args.redisIP
else:
redisIP = '127.0.0.1'
lj3.Config(redisIP,ljclient)
def hex2rgb(hexcode):
return tuple(map(ord,hexcode[1:].decode('hex')))
def rgb2hex(rgb):
return int('0x%02x%02x%02x' % tuple(rgb),0)
# IdiotIA
import json
CurrentPose = 1
# Get frame number for pose path describe in PoseDir
def lengthPOSE(pose_dir):
#if debug > 0:
# print("Check directory",'poses/' + pose_dir)
if os.path.exists('poses/' + pose_dir):
numfiles = sum(1 for f in os.listdir('poses/' + pose_dir) if os.path.isfile(os.path.join('poses/' + pose_dir + '/', f)) and f[0] != '.')
return numfiles
else:
if debug > 0:
print("but it doesn't even exist!")
return 0
# get absolute face position points
def getFACE(pose_json,pose_points, people):
dots = []
for dot in pose_points:
if len(pose_json['people'][people]['face_keypoints_2d']) != 0:
#print "people 0"
if pose_json['people'][people]['face_keypoints_2d'][dot * 3] != -1 and pose_json['people'][people]['face_keypoints_2d'][(dot * 3)+1] != -1:
dots.append((pose_json['people'][people]['face_keypoints_2d'][dot * 3], pose_json['people'][people]['face_keypoints_2d'][(dot * 3)+1]))
return dots
# Face keypoints
def face(pose_json, people):
pose_points = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
return getFACE(pose_json,pose_points, people)
def browL(pose_json, people):
pose_points = [26,25,24,23,22]
return getFACE(pose_json,pose_points, people)
def browR(pose_json, people):
pose_points = [21,20,19,18,17]
return getFACE(pose_json,pose_points, people)
def eyeR(pose_json, people):
pose_points = [36,37,38,39,40,41,36]
return getFACE(pose_json,pose_points, people)
def eyeL(pose_json, people):
pose_points = [42,43,44,45,46,47,42]
return getFACE(pose_json,pose_points, people)
def nose(pose_json, people):
pose_points = [27,28,29,30]
return getFACE(pose_json,pose_points, people)
def mouth(pose_json, people):
pose_points = [48,59,58,57,56,55,54,53,52,51,50,49,48,60,67,66,65,64,63,62,61,60]
return getFACE(pose_json,pose_points, people)
def prepareIdiotIA():
WebStatus("Init IdiotIA...")
# anim format (name, xpos, ypos, resize, currentframe, totalframe, count, speed)
# 0 1 2 3 4 5 6 7
# total frames is fetched from directory by lengthPOSE()
anims[0] = [['detroit1', xy_center[0], xy_center[1], 300,0,0,0,5]]
anims[1] = [['detroit1', xy_center[0], xy_center[1] + 50, 400,0,0,0,15]]
anims[2] = [['detroit1', xy_center[0], xy_center[1] + 50, 500,0,0,0,25]]
anims[3] = [['detroit1', xy_center[0], xy_center[1], 500,0,0,0,25]]
for laseranims in anims:
for anim in laseranims:
anim[5] = lengthPOSE(anim[0])
if debug > 0:
print("anim :", 'poses/' + anim[0], "length :", anim[5], "frames")
# display the face animation describe in PoseDir
def IdiotIA():
for laseranims in range(3):
for anim in anims[laseranims]:
PL = laseranims
#print PL, anim
dots = []
# increase current frame [4] of speed [7] frames
anim[4] += 1
# compare to total frame [5]
if anim[4] >= anim[5]:
anim[4] = 0
posename = 'poses/' + anim[0] + '/' + anim[0] +'-'+str("%05d"%anim[4])+'.json'
posefile = open(posename , 'r')
posedatas = posefile.read()
pose_json = json.loads(posedatas)
# Face
for people in range(len(pose_json['people'])):
#lj3.rPolyLineOneColor(face(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(browL(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(browR(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(eyeR(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(eyeL(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(nose(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(mouth(pose_json, people), c=color, PL = laseranims, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.DrawPL(PL)
time.sleep(0.02)
# many starfields
def prepareSTARFIELD():
global star, stars0, stars1, stars2, starfieldcount, starspeed, displayedstars, displayedstars, num_stars, max_depth
WebStatus("Init starfields...")
stars0=[]
stars1=[]
stars2=[]
#stars3=[]
num_stars = 50
max_depth = 20
stars = []
starfieldcount = 0
displayedstars = 5
starspeed = 0.05
for i in range(num_stars):
# A star is represented as a list with this format: [X,Y,Z]
star = [randrange(-25,25), randrange(-25,25), randrange(1, max_depth)]
stars0.append(star)
star = [randrange(-25,25), randrange(-25,25), randrange(1, max_depth)]
stars1.append(star)
star = [randrange(-25,25), randrange(-25,25), randrange(1, max_depth)]
stars2.append(star)
def Starfield(hori=0,verti=0):
global star, stars0, stars1, stars2, starfieldcount, starspeed, displayedstars, displayedstars, num_stars, max_depth
starfieldcount += 1
#print starfieldcount
starpoints = []
#print displayedstars, 'stars displayed'
# Increase number of
if displayedstars < num_stars and starfieldcount % 15 == 0:
displayedstars += 1
if displayedstars == num_stars and starfieldcount % 10 == 0:
starspeed += 0.005
#print starspeed
for starnumber in range(0,displayedstars):
# The Z component is decreased on each frame.
stars0[starnumber][2] -= starspeed * 3
stars1[starnumber][2] -= starspeed * 3
stars2[starnumber][2] -= starspeed * 3
# If the star has past the screen (I mean Z<=0) then we
# reposition it far away from the screen (Z=max_depth)
# with random X and Y coordinates.
if stars0[starnumber][2] <= 0:
stars0[starnumber][0] = randrange(-25,25)
stars0[starnumber][1] = randrange(-25,25)
stars0[starnumber][2] = max_depth
if stars1[starnumber][2] <= 0:
stars1[starnumber][0] = randrange(-25,25)
stars1[starnumber][1] = randrange(-25,25)
stars1[starnumber][2] = max_depth
if stars2[starnumber][2] <= 0:
stars2[starnumber][0] = randrange(-25,25)
stars2[starnumber][1] = randrange(-25,25)
stars2[starnumber][2] = max_depth
# Convert the 3D coordinates to 2D using perspective projection.
k0 = 128.0 / stars0[starnumber][2]
k1 = 128.0 / stars1[starnumber][2]
k2 = 128.0 / stars2[starnumber][2]
# Move Starfield origin.
# if stars xpos/ypos is same sign (i.e left stars xpos is <0) than (joystick or code) acceleration (hori and verti moves the star field origin)
if np.sign(stars0[starnumber][0]) == np.sign(hori):
x0 = int(stars0[starnumber][0] * k0 + xy_center[0] + (hori*600))
else:
x0 = int(stars0[starnumber][0] * k0 + xy_center[0] + (hori*500))
if np.sign(stars0[starnumber][1]) == np.sign(verti):
y0 = int(stars0[starnumber][1] * k0 + xy_center[1] + (verti*600))
else:
y0 = int(stars0[starnumber][1] * k0 + xy_center[1] + (verti*500))
if np.sign(stars1[starnumber][0]) == np.sign(hori):
x1 = int(stars1[starnumber][0] * k1 + xy_center[0] + (hori*600))
else:
x1 = int(stars1[starnumber][0] * k1 + xy_center[0] + (hori*300))
if np.sign(stars1[starnumber][1]) == np.sign(verti):
y1 = int(stars1[starnumber][1] * k1 + xy_center[1] + (verti*600))
else:
y1 = int(stars1[starnumber][1] * k1 + xy_center[1] + (verti*300))
if np.sign(stars2[starnumber][0]) == np.sign(hori):
x2 = int(stars2[starnumber][0] * k2 + xy_center[0] + (hori*600))
else:
x2 = int(stars2[starnumber][0] * k2 + xy_center[0] + (hori*300))
if np.sign(stars2[starnumber][1]) == np.sign(verti):
y2 = int(stars2[starnumber][1] * k2 + xy_center[1] + (verti*600))
else:
y2 = int(stars2[starnumber][1] * k2 + xy_center[1] + (verti*300))
# Add star to pointlist PL 0
if 0 <= x0 < screen_size[0] - 2 and 0 <= y0 < screen_size[1] - 2:
lj3.PolyLineOneColor([(x0,y0),((x0+1),(y0+1))], c = white, PL = 0, closed = False)
# Add star to pointlist PL 1
if 0 <= x1 < screen_size[0] - 2 and 0 <= y1 < screen_size[1] - 2:
lj3.PolyLineOneColor([(x1,y1),((x1+1),(y1+1))], c = white, PL = 1, closed = False)
# Add star to pointlist PL 2
if 0 <= x2 < screen_size[0] - 2 and 0 <= y2 < screen_size[1] - 2:
lj3.PolyLineOneColor([(x2,y2),((x2+1),(y2+1))], c= white, PL = 2, closed = False)
'''
if starfieldcount < 200:
if 0 <= x3 < screen_size[0] - 2 and 0 <= y3 < screen_size[1] - 2:
fwork.PolyLineOneColor([(x3,y3),((x3+2),(y3+2))], c=colorify.rgb2hex([255,255,255]), PL = 3, closed = False)
'''
lj3.Text(message, white, PL = 3, xpos = 300, ypos = 300, resize = 1, rotx =0, roty =0 , rotz=0)
lj3.DrawPL(0)
lj3.DrawPL(1)
lj3.DrawPL(2)
lj3.DrawPL(3)
def OSCidiotia(address, value):
print("Pose bank idiotia got", address, "with value", value)
def OSCfield(address, value):
print("Pose bank field got", address, "with value", value)
def OSCljclient(value):
print("Pose bank got /pose/ljclient with value", value)
ljclient = value
lj3.LjClient(ljclient)
def OSCpl(value):
print("Pose bank got /pose/pl with value", value)
lj3.WebStatus("Pose bank to pl "+ str(value))
lj3.LjPl(value)
# Starfield, idiotia
def OSCrun(value):
# Will receive message address, and message data flattened in s, x, y
print("Pose bank got /run with value", value)
doit = value
# /quit
def OSCquit():
WebStatus("Pose bank stopping")
print("Stopping OSC...")
lj3.OSCstop()
sys.exit()
def WebStatus(message):
lj3.SendLJ("/status",message)
print('Loading Pose bank...')
WebStatus("Loading Pose bank...")
# OSC Server callbacks
print("Starting OSC at 127.0.0.1 port",OSCinPort,"...")
osc_startup()
osc_udp_server("127.0.0.1", OSCinPort, "InPort")
osc_method("/pose/run*", OSCrun)
osc_method("/pose/ping*", lj3.OSCping)
osc_method("/pose/ljclient", OSCljclient)
osc_method("/pose/ljpl", OSCpl)
osc_method("/quit", OSCquit)
osc_method("/pose/idiotia*", OSCidiotia, argscheme=OSCARG_ADDRESS + OSCARG_DATA)
osc_method("/pose/field*", OSCfield, argscheme=OSCARG_ADDRESS + OSCARG_DATA)
anims =[[],[],[],[]]
color = lj3.rgb2int(255,255,255)
prepareIdiotIA()
#prepareSTARFIELD()
#doit = Starfield
doit = IdiotIA
white = lj3.rgb2int(255,255,255)
red = lj3.rgb2int(255,0,0)
blue = lj3.rgb2int(0,0,255)
green = lj3.rgb2int(0,255,0)
WebStatus("Pose bank running.")
print("Pose bank running")
def Run():
try:
while 1:
#Starfield(hori=0,verti=0)
doit()
except KeyboardInterrupt:
pass
# Gently stop on CTRL C
finally:
WebStatus("Pose bank Exit")
print("Stopping OSC...")
lj3.OSCstop()
print ("Pose bank Stopped.")
Run()

View File

@ -1,7 +1,9 @@
# coding=UTF-8
'''
LJ v0.8.1 in python3
lj3 v0.8.1
Some LJ functions useful for python clients (was framy.py)
OSC functions commented, waiting working on OSC in python3
@ -11,24 +13,28 @@ PolyLineOneColor
rPolyLineOneColor
Text(word, color, PL, xpos, ypos, resize, rotx, roty, rotz) : Display a word
Send(adress,message) : remote control. See commands.py
WebStatus(message) : display message on webui
SendLJ(adress,message) : LJ remote control. See commands.py
WebStatus(message) : display message on webui
DrawPL(point list number) : once you stacked all wanted elements, like 2 polylines, send them to lasers.
rgb2int(r,g,b)
LjClient(client): Change Client number in redis keys
LjPl(pl): Change pl number in redis keys = laser target.
OSCstart(): Start the OSC system.
OSCframe():
OSCstop(): Properly close the OSC system
OSCping(value): Answer to LJ pings
OSCstart(): Start the OSC system.
OSCframe(): Handle incoming OSC message. Calling the right callback
OSCstop(): Properly close the OSC system
OSCping(value): Answer to LJ pings by sending /pong value
OSCquit(name): Exit calling script using name in terminal
setup_controls(joystick)
XboxController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
Ps3Controller : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger, getUp, getDown, getLeft, getRight, getFire1, getFire2(self):
XboxController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
Ps3Controller : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger, getUp, getDown, getLeft, getRight, getFire1, getFire2(self):
MySaitekController : getLeftHori,getLeftVert, getRightHori,getRightVert, getLeftTrigger,getRightTrigger
MyThrustController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
CSLController : getLeftHori,getLeftVert,getRightHori, getRightVert,getLeftTrigger,getRightTrigger,getFire1,getFire2
my USB Joystick : getUp,getDown,getLeft,getRight,etLeftTrigger, getRightTrigger,getFire1, getFire2
CSLController : getLeftHori,getLeftVert,getRightHori, getRightVert,getLeftTrigger,getRightTrigger,getFire1,getFire2
my USB Joystick : getUp,getDown,getLeft,getRight,etLeftTrigger, getRightTrigger,getFire1, getFire2
LICENCE : CC
@ -42,6 +48,8 @@ import redis
# Import needed modules from osc4py3
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
#from osc4py3 import oscmethod as osm
from osc4py3.oscmethod import *
redisIP = '127.0.0.1'
@ -69,6 +77,7 @@ def OSCframe():
def OSCstop():
osc_terminate()
def SendLJ(oscaddress,oscargs=''):
try:
@ -80,13 +89,24 @@ def SendLJ(oscaddress,oscargs=''):
print ('Connection to LJ refused : died ?')
pass
def WebStatus(message):
SendLJ("/status", message)
# Answer to LJ pings
def OSCping(value):
# Will receive message address, and message data flattened in s, x, y
print("I got /ping with value", value)
print("Got /ping with value", value)
SendLJ("/pong",value)
# /quit
def OSCquit(name):
WebStatus(name + " quit.")
print("Stopping OSC...")
OSCstop()
sys.exit()
'''
def handlerfunction(s, x, y):
@ -216,7 +236,11 @@ def LjClient(client):
global ClientNumber
ClientNumber = client
def LjPl(pl):
global PL
PL = pl
def LineTo(xy, c, PL):
@ -320,7 +344,6 @@ def ResetPL(self, PL):
pl[PL] = []
def DigitsDots(number,color):
dots =[]
for dot in ASCII_GRAPHICS[number]:
@ -329,6 +352,7 @@ def DigitsDots(number,color):
#self.point_list.append((xy + (c,)))
return dots
def CharDots(char,color):
dots =[]
@ -336,6 +360,7 @@ def CharDots(char,color):
dots.append((dot[0],dot[1],color))
return dots
def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
dots =[]

View File

@ -112,7 +112,7 @@ LOGO = [
LOGO_OFFSET_X = 460
LOGO_OFFSET_Y = 250
def LogoDraw():
def LogoDraw(plnumber):
'''
Dessine le logo
'''
@ -122,8 +122,7 @@ def LogoDraw():
for xy in pl_color[0]:
xy_list.append((LOGO_OFFSET_X + xy[0], LOGO_OFFSET_Y + xy[1]))
#print xy_list
lj.PolyLineOneColor(xy_list, c,0, False)
lj.PolyLineOneColor(xy_list, c, plnumber, False)
@ -190,23 +189,23 @@ def FlipsMoveJoy(left_key,right_key,up_key,down_key,lvertax):
FlipsLy = screen_size[1] - PADDLE_height
return FlipsLy, FlipsRy
def FlipsDraw():
def FlipsDraw(plnumber):
lj.PolyLineOneColor([(FlipsLx,FlipsLy),(FlipsLx,FlipsLy + PADDLE_height),(FlipsLx + PADDLE_width , FlipsLy + PADDLE_height),(FlipsLx + PADDLE_width,FlipsLy)], white,0,True)
lj.PolyLineOneColor([(FlipsRx,FlipsRy),(FlipsRx,FlipsRy + PADDLE_height),(FlipsRx + PADDLE_width , FlipsRy + PADDLE_height),(FlipsRx + PADDLE_width,FlipsRy)], white,0,True)
lj.PolyLineOneColor([(FlipsLx,FlipsLy),(FlipsLx,FlipsLy + PADDLE_height),(FlipsLx + PADDLE_width , FlipsLy + PADDLE_height),(FlipsLx + PADDLE_width,FlipsLy)], white, plnumber, True)
lj.PolyLineOneColor([(FlipsRx,FlipsRy),(FlipsRx,FlipsRy + PADDLE_height),(FlipsRx + PADDLE_width , FlipsRy + PADDLE_height),(FlipsRx + PADDLE_width,FlipsRy)], white, plnumber, True)
def FiletDraw():
lj.PolyLineOneColor([(screen_size[0]/2,screen_size[1]),(screen_size[0]/2,0)], white, 0,True)
def FiletDraw(plnumber):
lj.PolyLineOneColor([(screen_size[0]/2,screen_size[1]),(screen_size[0]/2,0)], white, plnumber,True)
def Score1Draw(score):
def Score1Draw(score, plnumber):
#print "score1",score
lj.Text(str(score),white, 0, 350, 50, 1, 0, 0, 0)
lj.Text(str(score),white, plnumber, 350, 50, 1, 0, 0, 0)
def Score2Draw(score):
def Score2Draw(score, plnumber):
#print "score2",score
lj.Text(str(score),white, 0, 500, 50, 1, 0, 0, 0)
lj.Text(str(score),white, plnumber, 500, 50, 1, 0, 0, 0)
@ -235,7 +234,7 @@ def BallMove(xcoord,ycoord):
elif BallY >= screen_size[1]:
BallY = screen_size[1]
def BallDraw():
def BallDraw(plnumber):
global BallX,BallY
xmin = 0
@ -255,5 +254,5 @@ def BallDraw():
#print "ball position",xmin,xmax,ymin,ymax
lj.PolyLineOneColor([(xmin,ymin),(xmin,ymax),(xmax,ymax),(xmax,ymin)], white,0,True)
lj.PolyLineOneColor([(xmin,ymin),(xmin,ymax),(xmax,ymax),(xmax,ymin)], white, plnumber, True)

View File

@ -1,15 +1,21 @@
# coding=UTF-8
'''
LJ v0.8.0
Some LJ functions useful for python clients (was framy.py)
LJ v0.8.1
Some LJ functions useful for python 2.7 clients (was framy.py)
Functions and documentation here is low priority as python 2 support will stop soon.
Better code your plugin with python 3 and lj3.py.
Config
PolyLineOneColor
rPolyLineOneColor
Text
sendlj : remote control
SendLJ : remote control
LjClient :
LjPl :
DrawPL
WebStatus
LICENCE : CC
Sam Neurohack
@ -29,21 +35,14 @@ point_list = []
pl = [[],[],[],[]]
'''
LJIP = "127.0.0.1"
osclientlj = OSCClient()
oscmsg = OSCMessage()
osclientlj.connect((redisIP, 8002))
'''
def sendlj(oscaddress,oscargs=''):
def SendLJ(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
#print ("sending to bhorosc : ",oscmsg)
print ("sending OSC message : ",oscmsg)
try:
osclientlj.sendto(oscmsg, (redisIP, 8002))
oscmsg.clearData()
@ -52,7 +51,8 @@ def sendlj(oscaddress,oscargs=''):
pass
#time.sleep(0.001
def WebStatus(message):
SendLJ("/status", message)
ASCII_GRAPHICS = [
@ -158,6 +158,17 @@ def Config(redisIP,client):
ClientNumber = client
#print "client configured",ClientNumber
def LjClient(client):
global ClientNumber
ClientNumber = client
def LjPl(pl):
global PL
PL = pl
def LineTo(xy, c, PL):
@ -248,6 +259,7 @@ def LinesPL(PL):
print "Stupido !! your code is to old : use DrawPL() instead of LinesPL()"
DrawPL(PL)
def DrawPL(PL):
#print '/pl/0/'+str(PL), str(pl[PL])
if r.set('/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])) == True:

View File

@ -13,6 +13,7 @@ import math
import itertools
import sys
import os
import types
'''
is_py2 = sys.version[0] == '2'
@ -30,6 +31,9 @@ import entities
from controller import setup_controls
import argparse
from OSC import OSCServer, OSCClient, OSCMessage
OSCIP = "127.0.0.1"
OSCPort = 8020
score = None
@ -87,6 +91,9 @@ red = rgb2int(255,0,0)
blue = rgb2int(0,0,255)
green = rgb2int(0,255,0)
#
# Arguments handling
#
print ("")
print ("Arguments parsing if needed...")
@ -129,11 +136,17 @@ def StartPlaying(first_time = False):
app_path = os.path.dirname(os.path.realpath(__file__))
#
# Pads via pygame
#
print "Pygame init..."
pygame.init()
#sounds.InitSounds()
clock = pygame.time.Clock()
Nbpads = pygame.joystick.get_count()
print ("Joypads : ", str(Nbpads))
@ -184,6 +197,66 @@ y = ball_origin[1]
keystates = pygame.key.get_pressed()
#
# OSC
#
oscserver = OSCServer( (OSCIP, OSCPort) )
oscserver.timeout = 0
OSCRunning = True
def OSCljclient(path, tags, args, source):
print("LJ Pong got /ljpong/ljclient with value", args[0])
lj.WebStatus("LJPong to virtual "+ str(args[0]))
ljclient = args[0]
lj.LjClient(ljclient)
def OSCpl(path, tags, args, source):
print("LJ Pong got /ljpong/pl with value", args[0])
lj.WebStatus("LJPong to pl "+ str(args[0]))
plnumber = args[0]
# /ping
def OSCping(path, tags, args, source):
print("LJ Pong got /ping")
lj.SendLJ("/pong","ljpong")
lj.SendLJ("/ljpong/start",1)
def OSC_frame():
# clear timed_out flag
oscserver.timed_out = False
# handle all pending requests then return
while not oscserver.timed_out:
oscserver.handle_request()
def handle_timeout(self):
self.timed_out = True
print ""
print "Launching OSC server..."
print "at", OSCIP, "port",str(OSCPort)
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
# OSC callbacks
oscserver.addMsgHandler( "/ljpong/ljclient", OSCljclient )
oscserver.addMsgHandler("/ljpong/pl", OSCpl)
oscserver.addMsgHandler("/ping", OSCping)
print "Running..."
#
# Game main loop
#
while fs != GAME_FS_QUIT:
@ -192,6 +265,8 @@ while fs != GAME_FS_QUIT:
if event.type == pygame.QUIT:
fs = GAME_FS_QUIT
OSC_frame()
keystates_prev = keystates[:]
keystates = pygame.key.get_pressed()[:]
@ -346,21 +421,19 @@ while fs != GAME_FS_QUIT:
if fs == GAME_FS_PLAY or fs == GAME_FS_GAMEOVER or fs == GAME_FS_LAUNCH:
entities.Score1Draw(lscore)
entities.Score2Draw(rscore)
entities.FlipsDraw()
entities.BallDraw()
entities.FiletDraw()
lj.DrawPL(0)
entities.Score1Draw(lscore, plnumber)
entities.Score2Draw(rscore, plnumber)
entities.FlipsDraw(plnumber)
entities.BallDraw(plnumber)
entities.FiletDraw(plnumber)
lj.DrawPL(plnumber)
if fs == GAME_FS_MENU:
entities.LogoDraw()
lj.DrawPL(0)
entities.LogoDraw(plnumber)
lj.DrawPL(plnumber)
# TODO : rendre indépendante la fréquence de rafraîchissement de l'écran par
# rapport à celle de l'animation du jeu
clock.tick(100)
pygame.quit()

View File

@ -110,11 +110,18 @@ def rgb2int(r,g,b):
def OSCljclient(value):
# Will receive message address, and message data flattened in s, x, y
print("I got /glyph/ljclient with value", value)
print("Glyph got /glyph/ljclient with value", value)
lj3.WebStatus("Glyph to virtual "+ str(value))
ljclient = value
lj3.LjClient(ljclient)
def OSCpl(value):
print("Glyph got /glyph/pl with value", value)
lj3.WebStatus("Glyph to pl "+ str(value))
lj3.LjPl(value)
def Proj(x,y,z,angleX,angleY,angleZ):

View File

@ -94,10 +94,12 @@ def OSCword3(value):
def OSCljclient(value):
# Will receive message address, and message data flattened in s, x, y
print("Words got /words/ljclient with value", value)
lj3.WebStatus("Words to virtual "+ str(value))
ljclient = value
lj3.LjClient(ljclient)
# /ping
def OSCping():
@ -108,7 +110,7 @@ def OSCping():
# /quit
def OSCquit():
lj3.OSCquit("Words")
lj3.OSCquit("words")
def Run():
@ -122,7 +124,7 @@ def Run():
osc_method("/words/text/2*", OSCword2)
osc_method("/words/text/3*", OSCword3)
osc_method("/ping*", OSCping)
osc_method("/words/ljclient", OSCljclient)
osc_method("/words/ljclient*", OSCljclient)
osc_method("/quit", OSCquit)
color = lj3.rgb2int(255,255,255)

View File

@ -17,6 +17,9 @@ SendLJ(adress,message) : LJ remote control. See commands.py
WebStatus(message) : display message on webui
DrawPL(point list number) : once you stacked all wanted elements, like 2 polylines, send them to lasers.
rgb2int(r,g,b)
LjClient(client): Change Client number in redis keys
LjPl(pl): Change pl number in redis keys = laser target.
OSCstart(): Start the OSC system.
OSCframe(): Handle incoming OSC message. Calling the right callback
@ -233,7 +236,11 @@ def LjClient(client):
global ClientNumber
ClientNumber = client
def LjPl(pl):
global PL
PL = pl
def LineTo(xy, c, PL):

View File

@ -67,7 +67,7 @@ def SendLJ(oscaddress,oscargs=''):
# Answer to LJ pings
def OSCping(value):
# Will receive message address, and message data flattened in s, x, y
print("I got /ping with value", value)
SendLJ("/pong",value)
@ -190,6 +190,9 @@ def Config(redisIP,client):
ClientNumber = client
osc_udp_client(redisIP, 8002, "LJ 8002")
# If you want to use rgb for color :
def rgb2int(r,g,b):
return int('0x%02x%02x%02x' % (r,g,b),0)
def LineTo(xy, c, PL):
@ -308,13 +311,13 @@ def CharDots(char,color):
dots.append((dot[0],dot[1],color))
return dots
def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
def Text(message, c, PL, xpos, ypos, resize, rotx, roty, rotz):
dots =[]
l = len(message)
i= 0
#print message
#print (message)
for ch in message:
@ -333,10 +336,10 @@ def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
for xy in char_pl_list:
char_draw.append((xy[0] + x_offset,xy[1],c))
i +=1
i += 1
#print ch,char_pl_list,char_draw
rPolyLineOneColor(char_draw, c, PL , False, xpos, ypos, resize, rotx, roty, rotz)
#print ("laser",PL,"message",message)
# print ("laser",PL,"message",message)
#dots.append(char_draw)

View File

@ -17,7 +17,7 @@ Todo:
- use debug mode and check altaz calculated values against online sites.
- Validate aa2radec() with online calculator. Rewrite it to remove need for Astropy.
- Findout how to use OSC in python 3.
-
- North sky is hardcoded.
- Code WebUI page.
- UpdateStars() in each laser sky. Get magnitude. See UpdateSolar for example.
- All Draw operations should also check visibility in the given laser altitude range.
@ -33,10 +33,12 @@ import lj3
import numpy as np
import math,time
print("Importing astropy...")
from astropy.coordinates import SkyCoord, EarthLocation, AltAz
from astropy import units as u
from astropy.time import Time
print("Importing skyfield...")
from skyfield.api import Star, load, Topos,Angle
from skyfield.data import hipparcos
@ -45,10 +47,6 @@ from osc4py3 import oscbuildparse
#from osc4py3 import oscmethod as osm
from osc4py3.oscmethod import *
import json
'''
@ -65,14 +63,12 @@ else:
import argparse
print ("")
print ("Arguments parsing if needed...")
argsparser = argparse.ArgumentParser(description="Planetarium for LJ")
argsparser.add_argument("-r","--redisIP",help="IP of the Redis server used by LJ (127.0.0.1 by default) ",type=str)
argsparser.add_argument("-c","--client",help="LJ client number (0 by default)",type=int)
argsparser.add_argument("-L","--Lasers",help="Number of lasers connected (1 by default).",type=int)
argsparser.add_argument("-L","--Lasers",help="Number of lasers connected (4 by default).",type=int)
argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",type=int)
argsparser.add_argument("-i","--input",help="inputs OSC Port (8005 by default)",type=int)
#argsparser.add_argument("-n","--name",help="City Name of the observer",type=str)
@ -89,7 +85,7 @@ else:
if args.Lasers:
lasernumber = args.Lasers
else:
lasernumber = 1
lasernumber = 4
if args.verbose:
debug = args.verbose
@ -178,10 +174,17 @@ def Proj(x,y,z,angleX,angleY,angleZ):
def aa2radec(azimuth, altitude, t):
#AstrObserver = EarthLocation(lat=lati * u.deg, lon=longi *u.deg, height= elevation*u.m,)
ObjectCoord = SkyCoord(alt = altitude * u.deg, az = azimuth *u.deg, obstime = t, frame = 'altaz', location = AstrObserver)
#print("Oserver",AstrObserver )
print("time",t)
ObjectCoord = SkyCoord(alt = altitude * u.deg, az = azimuth * u.deg, obstime = t, frame = 'altaz', location = AstrObserver)
#print("icrs",ObjectCoord.icrs)
print("Altitude", altitude)
print("Altitude", altitude * u.deg)
print("Azimuth", azimuth)
print("Azimuth", azimuth * u.deg)
#print("ICRS Right Ascension", ObjectCoord.icrs.ra)
#print("ICRS Declination", ObjectCoord.icrs.dec)
#print()
return ObjectCoord.icrs.ra.degree, ObjectCoord.icrs.dec.degree
@ -227,16 +230,20 @@ def RadecSkies(LaserSkies, AstroSkyTime):
print()
print("Converting", lasernumber, "LaserSkies limits in Right Ascension & Declination (radec) coordinates ")
for laser in range(lasernumber):
if debug > 0:
print ("")
print("Laser",laser)
# Left top point
LaserSkies[laser][4],LaserSkies[laser][6] = aa2radec(azimuth = LaserSkies[laser][0], altitude =LaserSkies[laser][2], t =AstroSkyTime)
if debug > 0:
print(LaserSkies[laser][4],LaserSkies[laser][6])
# Right Bottom point
LaserSkies[laser][5],LaserSkies[laser][7] = aa2radec(azimuth = LaserSkies[laser][1], altitude =LaserSkies[laser][3], t =AstroSkyTime)
if debug > 0:
print(LaserSkies[laser][5],LaserSkies[laser][7])
print("Top left Altaz :",LaserSkies[laser][2],LaserSkies[laser][0])
print("Top left radec :",LaserSkies[laser][4],LaserSkies[laser][6])
print("Bottom right Altaz :",LaserSkies[laser][3],LaserSkies[laser][1])
print("Bottom right radec :",LaserSkies[laser][5],LaserSkies[laser][7])
if debug > 0:
print(LaserSkies)
print ("Done.")
@ -248,7 +255,10 @@ def azimuth2scrX(leftAzi,rightAzi,s):
b1, b2 = 0, width
#if debug > 0:
# print(leftAzi, rightAzi, s, b1 + ((s - a1) * (b2 - b1) / (a2 - a1)))
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
if s != 0:
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
else:
return width/2
@ -297,7 +307,7 @@ def LoadSolar():
def UpdateSolar():
global SolarObjects
# Compute Alt Az coordinates for all solar objects for obsehttps://www.startpage.com/do/searchrver.
# Compute Alt Az coordinates for all solar objects for Observer.
for number,object in enumerate(SolarObjects):
#print(object[0],number)
@ -305,13 +315,11 @@ def UpdateSolar():
if debug > 0:
PrintSolar()
def PrintSolar():
for number,object in enumerate(SolarObjects):
print (SolarObjects[number][0],"is at (alt,az)",SolarObjects[number][1],SolarObjects[number][2])
# Draw the SolarShapeObject for any Solar object is in the laser Sky
def DrawSolar(laser):
@ -363,12 +371,11 @@ def StarSelect():
for index in range(len(Starnames)-1):
StarsObjects.append([Starnames[index+1],0,0])
def UpdateStars(ts):
global StarsObjects
hipparcos_epoch = ts.tt(1991.25)
# Compute Alt Az coordinates for all solar objects for obsehttps://www.startpage.com/do/searchrver.
# Compute Alt Az coordinates for all stars objects for Observer.
for number,object in enumerate(StarsObjects):
#print(object[0],number)
@ -405,7 +412,7 @@ def DrawStars(laser):
#
# Anything system. Say you want
# Template for Anything you want system.
#
AnythingObjectShape = [(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)]
@ -433,13 +440,11 @@ def UpdateAnything():
if debug > 0:
PrintAnything()
def PrintAnything():
for number,object in enumerate(AnythingObjects):
print (AnythingObjects[number][0],"is at (alt,az)",AnythingObjects[number][1],AnythingObjects[number][2])
# Draw the AnythingShapeObject for any Anything object is in the laser Sky
def DrawAnything(laser):
@ -453,12 +458,11 @@ def DrawAnything(laser):
#
# On Earth Gps positions
# from https://github.com/lutangar/cities.json
#
def LoadCities():
global world
@ -493,8 +497,7 @@ def DrawOrientation(laser):
# North direction is in given laser sky azimuth range?
if LaserSkies[laser][1] < LaserSkies[laser][0]:
#print ("N az",azimuth2scrX(LaserSkies[laser][0],LaserSkies[laser][1],0))
lj3.Text("NORTH",white,laser,azimuth2scrX(LaserSkies[laser][0],LaserSkies[laser][1],359), 770, resize = 0.5, rotx =0, roty =0 , rotz=0)
lj3.Text("NORTH",white,laser,azimuth2scrX(LaserSkies[laser][0],LaserSkies[laser][1],0), 770, resize = 0.5, rotx =0, roty =0 , rotz=0)
# East direction is in given laser sky azimuth range ?
if LaserSkies[laser][0] <= 90 < LaserSkies[laser][1]:
@ -546,7 +549,9 @@ def InitObserver(SkyCity, SkyCountryCode, time,ts):
# to later select their visible objects in radec catalogs like hipparcos.
# LaserSky definition for one laser (in decimal degrees) : [RightAzi, LeftAzi, TopAlt, BotAlt, LeftRa, RightRa, TopDec, BottomDec]
# With 4 lasers with each one a quarter of the 360 ° real sky, there is 4 LaserSky :
LaserSkies = [[45,135.0,90.0,0.0,0.0,0.0,0.0,0.0],[135,225,90,0,0,0,0,0],[225,315,90,0,0,0,0,0],[305,0,90,0,0,0,0,0]]
print()
print("LaserSkies Radec conversion")
LaserSkies = [[45,135.0,90.0,0.0,0.0,0.0,0.0,0.0],[135,225,90,0,0,0,0,0],[225,315,90.0,0,0,0,0,0],[315,45,90.0,0,0,0,0,0]]
RadecSkies(LaserSkies, AstroSkyTime)
@ -612,7 +617,7 @@ try:
osc_method("/ping*", lj3.OSCping)
osc_method("/quit", OSCquit)
WebStatus("Load Cities.")
WebStatus("Loading Cities...")
ts = load.timescale()
LoadCities()
@ -620,17 +625,17 @@ try:
SkyCountryCode = 'FR'
WebStatus(SkyCity)
WebStatus("Solar System..")
WebStatus("Loading Solar System...")
LoadSolar()
WebStatus("Observer..")
WebStatus("Finding observer position..")
InitObserver(SkyCity, SkyCountryCode, Time.now(),ts)
WebStatus("Load Stars..")
WebStatus("Loading Stars...")
LoadHipparcos(ts)
StarSelect()
WebStatus("Updating...")
WebStatus("Computing observer skies")
print("Updating solar system (de421) objects position for observer at", Skylat, Skylong, "time", SkyfieldTime.utc_iso())
UpdateSolar()

View File

@ -74,14 +74,22 @@ def rgb2int(r,g,b):
def WebStatus(message):
lj3.SendLJ("/status",message)
def OSCljclient(value):
# Will receive message address, and message data flattened in s, x, y
print("I got /cycl/ljclient with value", value)
print("Cycl got /cycl/ljclient with value", value)
lj3.WebStatus("Cycl to virtual "+ str(value))
ljclient = value
lj3.LjClient(ljclient)
def OSCpl(value):
print("Cycl got /cycl/pl with value", value)
lj3.WebStatus("Cycl to pl "+ str(value))
lj3.LjPl(value)
# /ping
def OSCping():
@ -91,15 +99,15 @@ def OSCping():
# /quit
def OSCquit():
lj3.OSCquit("Cycl")
lj3.OSCquit("cycl")
osc_startup()
osc_udp_server("127.0.0.1", OSCinPort, "InPort")
osc_method("/ping*", OSCping)
osc_method("/quit", OSCquit)
osc_method("/cycl/ljclient", OSCljclient)
osc_method("/cycl/ljclient*", OSCljclient)
osc_method("/cycl/pl*", OSCpl)
WebStatus("Textcycl Ready")
lj3.SendLJ("/cycl/start 1")

View File

@ -80,6 +80,8 @@
x.style.display = "none";
var x = document.getElementById("vjUI");
x.style.display = "none";
var x = document.getElementById("poseUI");
x.style.display = "none";
var x = document.getElementById("wordsUI");
x.style.display = "none";
var x = document.getElementById("pluginsUI");
@ -119,6 +121,15 @@
_WS.send("/bank0/ping");
}
function showposeUI() {
nosimuUI();
var x = document.getElementById("poseUI");
x.style.display = "grid";
_WS.send("/pose/ping");
}
function showwordsUI() {
nosimuUI();
var x = document.getElementById("wordsUI");
@ -154,9 +165,12 @@
if (clicked_id === "lissa/lissaUI") {
showlissaUI();
}
if (clicked_id === "vj/vjUI") {
if (clicked_id === "bank0/vjUI") {
showvjUI();
}
if (clicked_id === "pose/poseUI") {
showposeUI();
}
if (clicked_id === "words/wordsUI") {
showwordsUI();
}
@ -238,6 +252,7 @@
//console.log("plpoint");
break;
default:
//console.log(e);
document.getElementById(res[0].slice(1)).value = res[1];
_WS.showin(e.data);
}

View File

@ -69,6 +69,22 @@
transition: all .3s ease;
background-color: #151515;
}
.posebuttons {
display: none;
height: 400px;
width: 400px;
grid-template-columns: 66px 66px 66px 66px 66px 66px;
grid-template-rows: 30px 67px 67px 67px 30px;
background-color: #000;
justify-items: center;
align-items: center;
border-color: #445;
border-style: groove;
border-width: 1px;
grid-gap: 1px;
transition: all .3s ease;
background-color: #151515;
}
.mglive {
display: none;
height: 400px;

View File

@ -1,10 +1,10 @@
<!DOCTYPE html>
<!--
LJ webapp 'mg' stand for main grid elements
-->
<html>
<head>
<meta charset="utf-8">
@ -26,8 +26,6 @@
<link rel="stylesheet" href="LJgrid.css" />
<!-- Javascript for this webapp is a the end of this html page and in LJ.js -->
<script src="LJ.js"></script>
</head>
<body style="background-color:#222;">
@ -55,9 +53,7 @@
<div><webaudio-switch id="on" height="52" width="41" value="0" src="knobs/bigbluetoggle.png" type="toggle"></webaudio-switch></div>
</div>
<!-- Lasers state grid -->
<!-- Lasers states grid -->
<div class="lsttgrid">
<div></div>
@ -65,29 +61,32 @@
<div class="lasertextxs">S</div>
<div class="lasertextxs">C</div>
<!-- Laser 0 lstt & lack -->
<div class="lasertextxs">0</div>
<div></div>
<div><webaudio-knob id="lstt/0" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<div><webaudio-knob id="lack/0" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<!-- Laser 1 lstt & lack -->
<div class="lasertextxs">1</div>
<div></div>
<div><webaudio-knob id="lstt/1" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<div><webaudio-knob id="lack/1" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<!-- Laser 2 lstt & lack -->
<div class="lasertextxs">2</div>
<div></div>
<div><webaudio-knob id="lstt/2" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<div><webaudio-knob id="lack/2" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<!-- Laser 3 lstt & lack -->
<div class="lasertextxs">3</div>
<div></div>
<div><webaudio-knob id="lstt/3" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<div><webaudio-knob id="lack/3" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
</div>
<!-- blackout button -->
<!-- blackout button -->
<div class="blackout">
<div class="lasertextxs">Emergy Black</div>
<div><webaudio-switch id="emergency" height="64" width="64" value="0" src="knobs/blackout.png" type="toggle"></webaudio-switch></div>
@ -142,20 +141,18 @@
<div id="mgstatus" class="mgstatus">
<div>
<!-- Horizontal menu buttons -->
<webaudio-switch id="align" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/align.png"></webaudio-switch>
<webaudio-switch id="simu" value="1" height="27" width="75" tooltip="Switch-B" src="knobs/simu.png"></webaudio-switch>
<webaudio-switch id="live" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/live.png"></webaudio-switch>
<webaudio-switch id="run" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/run.png"></webaudio-switch>
<!--
<button class="button" id="showrun" onclick="showRun()">Run</button>
<button class="button" id="shownozoid" onclick="showNozoid()">Nozoid</button>
-->
</div>
<div><button class="info" id="showstatus">OFFLINE</button></div>
<div>
<div>
<div>
<!-- Client actually drawn Selection -->
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="noteon 0">0</option>
@ -164,6 +161,7 @@
<option value="noteon 3">3</option>
</select>
<!-- Point List drawn in simulator -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
<option value="noteon 24">0</option>
@ -171,29 +169,35 @@
<option value="noteon 26">2</option>
<option value="noteon 27">3</option>
</select>
<!--
<span class="lasertext">Laser</span>
<select onclick="buttonClicked(this.value)">
<option value="noteon 24" selected >0</option>
<option value="noteon 25">1</option>
<option value="noteon 26">2</option>
<option value="noteon 27">3</option>
</select>
-->
<select onclick="buttonClicked(this.value)" value="lj/pluginsUI">
<option value="lj/pluginsUI">Plugins</option>
<option value="planet/planetUI">Planetarium</option>
<option value="nozoid/nozoidUI">Nozoid</option>
<option value="bank0/vjUI">VJing</option>
<option value="words/wordsUI">Words</option>
<option value="ai/aiUI">AI</option>
<option value="lissa/lissaUI">Lissa</option>
</select>
</div>
</div>
<div>
<div>
<!-- Plugins selection menu -->
<button class="info" id="showstatus">OFFLINE</button>
<select onclick="buttonClicked(this.value)" value="lj/pluginsUI">
<option value="lj/pluginsUI">Plugins</option>
<option value="planet/planetUI">Planetarium</option>
<option value="nozoid/nozoidUI">Nozoid</option>
<option value="bank0/vjUI">VJing</option>
<option value="pose/poseUI">Pose</option>
<option value="words/wordsUI">Words</option>
<option value="ai/aiUI">AI</option>
<option value="lissa/lissaUI">Lissa</option>
</select>
<!--
<span class="lasertext">Laser</span>
<select onclick="buttonClicked(this.value)">
<option value="noteon 24" selected >0</option>
<option value="noteon 25">1</option>
<option value="noteon 26">2</option>
<option value="noteon 27">3</option>
</select>
-->
</div>
</div>
</div>
@ -203,6 +207,7 @@
<div id="mgalign" class="mgalign">
<!-- Laser 0 -->
<div class="laserbox">
<!-- IP laser 0 -->
@ -221,38 +226,46 @@
<webaudio-switch id="swap/X/0" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/0" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<!-- Lasergrid 0 -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid0.png);">
<div><webaudio-param id="kpps/0" link="kpps/0" ></webaudio-param></div>
<!-- kPPS & Points-->
<div><webaudio-param id="kpps/0" link="kpps/0" ></webaudio-param></div>
<div><webaudio-param id="points/0" link="points/0"></webaudio-param></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="loffset/X/0" diameter="60" min="-320" max="320" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/0" diameter="60" min="-320" max="320" value="0"></webaudio-knob></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="loffset/X/0" value="0"></webaudio-param></div>
<div><webaudio-param link="loffset/Y/0" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Scale X & Scale Y -->
<div><webaudio-knob id="scale/X/0" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/0" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale Y</div>
<div><webaudio-param link="scale/X/0" value="0"></webaudio-param></div>
<div><webaudio-param link="scale/Y/0" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div><webaudio-knob id="angle/0" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle & Intensity -->
<div><webaudio-knob id="angle/0" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div><webaudio-knob id="intens/0" diameter="60" min="0" max="127" value="127"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Intens.</div>
</div>
</div>
<!-- Laser 1 -->
<div class="laserbox">
<!-- IP laser 1 -->
@ -275,30 +288,39 @@
<webaudio-switch id="swap/Y/1" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<!-- Lasergrid 1 -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid1.png);">
<div><webaudio-param id="kpps/1" link="kpps/1"></webaudio-param></div>
<div><webaudio-param id="points/1" link="points/1"></webaudio-param></div>
<!-- kPPS & Points-->
<div><webaudio-param id="kpps/1" link="kpps/1"></webaudio-param></div>
<div><webaudio-param id="points/1" link="points/1"></webaudio-param></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="loffset/X/1" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/1" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="loffset/X/1" value="0"></webaudio-param></div>
<div><webaudio-param link="loffset/Y/1" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Scale X & Scale Y -->
<div><webaudio-knob id="scale/X/1" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/1" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale Y</div>
<div><webaudio-param link="scale/X/1" value="0"></webaudio-param></div>
<div><webaudio-param link="scale/Y/1" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle & Intensity -->
<div><webaudio-knob id="angle/1" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div><webaudio-knob id="intens/1" diameter="60" min="0" max="127"value="127"></webaudio-knob></div>
<div class="lasertext">Angle</div>
@ -306,6 +328,7 @@
</div>
</div>
<!-- Laser 2 -->
<div class="laserbox">
<!-- IP laser 2 -->
@ -330,31 +353,36 @@
<!-- Laser 2 grid -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid2.png)">
<div><webaudio-param id="kpps/2" link="kpps/2"></webaudio-param></div>
<!-- kPPS & Points-->
<div><webaudio-param id="kpps/2" link="kpps/2"></webaudio-param></div>
<div><webaudio-param id="points/2" link="points/2"></webaudio-param></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="loffset/X/2" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/2" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="loffset/X/2" value="0"></webaudio-param></div>
<div><webaudio-param link="loffset/Y/2" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Scale X & Scale Y -->
<div><webaudio-knob id="scale/X/2" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/2" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale Y</div>
<div><webaudio-param link="scale/X/2" value="0"></webaudio-param></div>
<div><webaudio-param link="scale/Y/2" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle & Intensity -->
<div><webaudio-knob id="angle/2" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div><webaudio-knob id="intens/2" diameter="60" min="0" max="127"value="127"></webaudio-knob></div>
<div class="lasertext">Angle</div>
@ -362,6 +390,7 @@
</div>
</div>
<!-- Laser 3 -->
<div class="laserbox">
<!-- IP laser 3 -->
@ -386,31 +415,36 @@
<!-- Laser 3 grid -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid3.png)">
<!-- kPPS & Points-->
<div><webaudio-param id="kpps/3" link="kpps/3" ></webaudio-param></div>
<div><webaudio-param id="points/3" link="points/3"></webaudio-param></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="loffset/X/3" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/3" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="loffset/X/3" value="0"></webaudio-param></div>
<div><webaudio-param link="loffset/Y/3" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Scale X & Scale Y -->
<div><webaudio-knob id="scale/X/3" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/3" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale Y</div>
<div><webaudio-param link="scale/X/3" value="0"></webaudio-param></div>
<div><webaudio-param link="scale/Y/3" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle & Intensity -->
<div><webaudio-knob id="angle/2" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div><webaudio-knob id="intens/3" diameter="60" min="0" max="127" value="127"></webaudio-knob></div>
<div class="lasertext">Angle</div>
@ -421,7 +455,6 @@
<canvas id="aligncanvas" width="336" height="400" style="border-color: #445;border-style:groove;border-width:1px;"></canvas>
</div>
</div>
@ -436,30 +469,34 @@
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">With AI
</div>
<div class="withaigrid">
<!-- Velocity X Expression -->
<div><webaudio-knob id="ai/velocity" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="ai/expressivity" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="ai/velocity" value="64"></webaudio-param></div>
<div><webaudio-param link="ai/expressivity" value="64"></webaudio-param></div>
<div class="lasertext">Velocity</div>
<div class="lasertext">Express.</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Sensibility & Beauty -->
<div><webaudio-knob id="ai/sensibility" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="ai/beauty" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="ai/sensibility" value="64"></webaudio-param></div>
<div><webaudio-param link="ai/beauty" value="64"></webaudio-param></div>
<div class="lasertext">Sens.</div>
<div class="lasertext">Beauty</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- CC 1 & CC 2 -->
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="1"></webaudio-param></div>
<div><webaudio-param link="cc/2" value="1"></webaudio-param></div>
<div class="lasertext">CC 1</div>
<div class="lasertext">CC 2</div>
<div class="lasertext">CC 2</div>
</div>
</div>
@ -470,22 +507,27 @@
</div>
<div class="lissagrid">
<!-- Select X & Select Y -->
<div><webaudio-knob id="cc/5" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-knob id="cc/6" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-param link="cc/5" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/6" value="0"></webaudio-param></div>
<div class="lasertext">Select X</div>
<div class="lasertext">Select Y</div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="lasertext">Select Y</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- FOV & Dist -->
<div><webaudio-knob id="cc/21" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/22" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/21" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/22" value="0"></webaudio-param></div>
<div class="lasertext">FOV</div>
<div class="lasertext">Dist</div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="lasertext">FOV</div>
<div class="lasertext">Dist</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="0"></webaudio-param></div>
@ -521,43 +563,49 @@
-->
<div id = "mgsimu" class="mgsimu">
<!-- left part : simulator -->
<!-- Simu left part : canvas -->
<div>
<canvas id="canvas" width="500" height="400" style="border-color: #445;border-style:groove;border-width:1px;"></canvas>
</div>
<!-- right part : interdace -->
<div>
<!-- Right part interfaces -->
<!-- sub right part : planetarium -->
<div>
<!-- simu right part : Planetarium -->
<div id ="planetUI" style = "display: none;justify-items: center;">
<!-- Stop and start switch -->
<div>
<div><webaudio-switch id="planet/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/planet.png"></webaudio-switch>
</div>
<!-- Virtual client destination -->
<div>
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)">
<option value="planet/ljclient 0" selected >0</option>
<option value="planet/ljclient 1">1</option>
<option value="planet/ljclient 2">2</option>
<option value="planet/ljclient 3">3</option>
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)">
<option value="planet/ljclient 0" selected >0</option>
<option value="planet/ljclient 1">1</option>
<option value="planet/ljclient 2">2</option>
<option value="planet/ljclient 3">3</option>
</select>
</div>
</div>
</div>
<form onsubmit="onSubmit(); return false;">
<!-- Observer position -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Country (FR)</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/country">
<span class="lasertext">City</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/city">
</form>
<!-- Observer time -->
<form>
<span class="lasertext">Date/Time (2012-7-12 23:00:00) </span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/time">
</form>
<!-- Laser 0 Sky -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 0 : Alt</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/alt/0">
@ -566,6 +614,8 @@
<span class="lasertext">Angle</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/angle/0">
</form>
<!-- Laser 1 Sky -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 1 : Alt</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/alt/1">
@ -574,6 +624,8 @@
<span class="lasertext">Angle</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/angle/1">
</form>
<!-- Laser 2 Sky -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 2 : Alt</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/alt/2">
@ -582,6 +634,8 @@
<span class="lasertext">Angle</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/angle/2">
</form>
<!-- Laser 3 Sky -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 3 : Alt</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/alt/3">
@ -592,42 +646,48 @@
</form>
</div>
<!-- sub right part : lissaUI -->
<!-- simu right part : lissaUI -->
<div id ="lissaUI" style = "display: none;justify-items: center;">
<!-- Lissa interface -->
<div class="lissabox">
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">LISSA
</div>
<div class="lissagrid">
<!-- Lissa interface -->
<div class="lissabox">
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">LISSA
</div>
<div class="lissagrid">
<div><webaudio-knob id="cc/5" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-knob id="cc/6" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-param link="cc/5" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/6" value="0"></webaudio-param></div>
<div class="lasertext">Select X</div>
<div class="lasertext">Select Y</div>
<div class="spacer"></div>
<div class="spacer"></div>
<div><webaudio-knob id="cc/21" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/22" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/21" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/22" value="0"></webaudio-param></div>
<div class="lasertext">FOV</div>
<div class="lasertext">Dist</div>
<div class="spacer"></div>
<div class="spacer"></div>
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/2" value="0"></webaudio-param></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
</div>
<!-- Select X & Select Y -->
<div><webaudio-knob id="cc/5" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-knob id="cc/6" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-param link="cc/5" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/6" value="0"></webaudio-param></div>
<div class="lasertext">Select X</div>
<div class="lasertext">Select Y</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- FOV & Dist -->
<div><webaudio-knob id="cc/21" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/22" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/21" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/22" value="0"></webaudio-param></div>
<div class="lasertext">FOV</div>
<div class="lasertext">Dist</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/2" value="0"></webaudio-param></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
</div>
</div>
</div>
<!-- sub right part : aiUI -->
<!-- simu right part : aiUI -->
<div id ="aiUI" style = "display: none;justify-items: center;">
<!-- with AI Interface -->
@ -635,24 +695,28 @@
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">With AI
</div>
<div class="withaigrid">
<!-- Velocity & Expression -->
<div><webaudio-knob id="ai/velocity" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="ai/expressivity" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="ai/velocity" value="64"></webaudio-param></div>
<div><webaudio-param link="ai/expressivity" value="64"></webaudio-param></div>
<div class="lasertext">Velocity</div>
<div class="lasertext">Express.</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Sensibility & Beauty -->
<div><webaudio-knob id="ai/sensibility" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="ai/beauty" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="ai/sensibility" value="64"></webaudio-param></div>
<div><webaudio-param link="ai/beauty" value="64"></webaudio-param></div>
<div class="lasertext">Sens.</div>
<div class="lasertext">Beauty</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- CC 1 & CC 2 -->
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="1"></webaudio-param></div>
@ -664,7 +728,7 @@
</div>
<!-- sub right part : pluginsUI -->
<!-- simu right part : pluginsUI -->
<div id ="pluginsUI" style = "display: grid;justify-items: center;">
<!-- Plugins choice Interface -->
@ -674,51 +738,177 @@
</div>
<div>
<webaudio-switch id="glyph/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/glyph.png"></webaudio-switch>
<webaudio-switch id="cycl/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/cycl.png"></webaudio-switch>
</div>
<div>
<!-- Glyph destination LJ client Selection -->
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="glyph/ljclient 0">0</option>
<option value="glyph/ljclient 1">1</option>
<option value="glyph/ljclient 2">2</option>
<option value="glyph/ljclient 3">3</option>
</select>
<!-- Cycl destination LJ client Selection -->
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="cycl/ljclient 0">0</option>
<option value="cycl/ljclient 1">1</option>
<option value="cycl/ljclient 2">2</option>
<option value="cycl/ljclient 3">3</option>
</select>
</div>
<div>
<!-- Glyph Point List destination -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
<option value="glyph/pl 0">0</option>
<option value="glyph/pl 1">1</option>
<option value="glyph/pl 2">2</option>
<option value="glyph/pl 3">3</option>
</select>
<!-- Cycl Point List destination -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
<option value="cycl/pl 0">0</option>
<option value="cycl/pl 1">1</option>
<option value="cycl/pl 2">2</option>
<option value="cycl/pl 3">3</option>
</select>
</div>
<!-- LJPong & LJwars -->
<div>
<webaudio-switch id="ljpong/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/ljpong.png"></webaudio-switch>
<webaudio-switch id="ljwars/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/ljwars.png"></webaudio-switch>
</div>
<div>
<!-- LJ Pong destination LJ client Selection -->
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="ljpong/ljclient 0">0</option>
<option value="ljpong/ljclient 1">1</option>
<option value="ljpong/ljclient 2">2</option>
<option value="ljpong/ljclient 3">3</option>
</select>
<!-- LJ Wars destination LJ client Selection -->
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="ljwars/ljclient 0">0</option>
<option value="ljwars/ljclient 1">1</option>
<option value="ljwars/ljclient 2">2</option>
<option value="ljwars/ljclient 3">3</option>
</select>
</div>
<div>
<!-- LJ Pong Point List destination -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
<option value="ljpong/pl 0">0</option>
<option value="ljpong/pl 1">1</option>
<option value="ljpong/pl 2">2</option>
<option value="ljpong/pl 3">3</option>
</select>
</div>
</div>
<!-- simu right part : bank0 vjUI -->
<div id ="vjUI" class="cnvbuttons">
<!-- sub right part : vjUI bank0 -->
<!-- Bank Selection first line -->
<div><webaudio-switch id="bank0/run" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="1" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="2" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="3" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="4" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="5" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div id ="vjUI" class="cnvbuttons">
<!-- Bank Selection second line -->
<div><webaudio-switch id="noteon" value="23" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="24" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="25" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="26" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="27" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="28" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank 0" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank 1" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch>></div>
<div><webaudio-switch id="bank 2" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank 3" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank 4" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank 5" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch>></div>
<div><webaudio-switch id="noteon 26" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 27" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 24" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 25" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch>></div>
<div><webaudio-switch id="noteon 26" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 27" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 26" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 27" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 24" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 25" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch>></div>
<div><webaudio-switch id="noteon 26" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon 27" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<!-- Bank Selection third line -->
<div><webaudio-switch id="noteon" value="26" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="27" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="28" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="29" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="30" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="31" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
</div>
<!-- sub right part : wordsUI -->
<!-- simu right part : poseUI -->
<div id ="poseUI" class="posebuttons">
<!-- IdiotIA laser destination -->
<div><span class="lasertext">IdiotIA</span></div>
<div><webaudio-switch id="pose/idiotia/0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
<!-- IdiotIA animation selection first line -->
<div><webaudio-switch id="pose/idiotia/anim0" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim1" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim2" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim3" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim4" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim5" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- IdiotIA animation selection second line -->
<div><webaudio-switch id="pose/idiotia/anim6" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim7" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim8" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim9" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim10" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim11" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- IdiotIA animation selection third line -->
<div><webaudio-switch id="pose/idiotia/anim12" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim13" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim14" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim15" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim16" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/anim17" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- Starfield laser destination -->
<div><span class="lasertext">Fields</span></div>
<div><webaudio-switch id="pose/field/0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field/1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field/2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field/3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
</div>
<!-- simu right part : wordsUI -->
<div id ="wordsUI" style = "display: none;justify-items: center;">
<div>
<webaudio-switch id="words/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/words.png"></webaudio-switch>
<!-- Words virtual client destination -->
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)">
<option value="words/ljclient 0" selected >0</option>
@ -727,9 +917,12 @@
<option value="words/ljclient 3">3</option>
</select>
</div>
<!-- Words 0 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/0" value=" ">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/0 red" selected >Red</option>
<option value="words/color/0 green">Green</option>
<option value="words/color/0 blue">Blue</option>
@ -740,9 +933,12 @@
</select>
<span class="lasertext">Laser 0</span>
</form>
<!-- Words 1 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/1" value=" ">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/1 red" selected >Red</option>
<option value="words/color/1 green">Green</option>
<option value="words/color/1 blue">Blue</option>
@ -753,9 +949,12 @@
</select>
<span class="lasertext">Laser 1</span>
</form>
<!-- Words 2 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/2" value=" ">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/2/color red" selected >Red</option>
<option value="words/color/2 green">Green</option>
<option value="words/color/2 blue">Blue</option>
@ -766,9 +965,12 @@
</select>
<span class="lasertext">Laser 2</span>
</form>
<!-- Words 3 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/3" value=" ">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/3 red" selected >Red</option>
<option value="words/color/3 green">Green</option>
<option value="words/color/3 blue">Blue</option>
@ -785,7 +987,7 @@
<!-- sub right part : NozoidUI -->
<!-- simu right part : NozoidUI -->
<div id ="nozoidUI" style = "display: none;justify-items: center;">
<!-- Stop and start switch -->
@ -832,7 +1034,7 @@
</select>
</div>
<!-- X curve Line IN and X Curve choices -->
<!-- X and X Curve choices -->
<div>
<span class="lasertext" >X</span>
<select onclick="buttonClicked(this.value)">
@ -874,7 +1076,7 @@
</select>
</div>
<!-- Y curve Line IN and Y Curve choices -->
<!-- Y and Y Curve choices -->
<div>
<span class="lasertext" >Y</span>
<select onclick="buttonClicked(this.value)">
@ -955,7 +1157,7 @@
<div id="mgrun" class="mgrun">
<!-- Laser Client selection grid -->
<!-- Run Laser Client selection grid -->
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>

BIN
webui/knobs/0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
webui/knobs/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
webui/knobs/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
webui/knobs/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
webui/knobs/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
webui/knobs/cycl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
webui/knobs/glyph.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
webui/knobs/iconvj1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
webui/knobs/idiotia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
webui/knobs/ljpong.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
webui/knobs/ljwars.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
webui/knobs/pong.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB