1019 lines
33 KiB
Python
1019 lines
33 KiB
Python
#!/usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
# -*- mode: Python -*-
|
|
|
|
'''
|
|
|
|
lj23layers v0.7.6 for LJ v0.8+
|
|
|
|
LJ functions (API) for python plugins/clients
|
|
|
|
"layers" version :
|
|
- "PL" has been replaced by "layer"
|
|
- "Client"
|
|
|
|
Each program using this API to manage complexity, should declare itself by calling Config, but it's not mandatory
|
|
|
|
Config(redisIP, client number, name)
|
|
|
|
|
|
Basic Draw :
|
|
|
|
- PolyLineOneColor, rPolyLineOneColor, LineTo, Line
|
|
- PolyLineRGB, rPolyLineRGB, LineRGBTo, LineRGB
|
|
- rgb2int(r,g,b)
|
|
- Drawlayer (point list number) : once you stacked all wanted elements, like 2 polylines, send them to lasers.
|
|
- DrawDests(): Draw all requested destinations for each layer .
|
|
|
|
High level draw :
|
|
|
|
- Text(word, zpos, integercolor, layer , xpos, ypos, resize, rotx, roty, rotz) : Display a word
|
|
- TextRGB(word, zpos, red, green, blue, ...)
|
|
- Embeded font1
|
|
|
|
|
|
Laser objects (name and convenient group of parameters for one or several point lists)
|
|
|
|
- RelativeObject
|
|
- FixedObject
|
|
|
|
"Destinations" : Tell for given Layer a scene/Laser ("destination").
|
|
Each Layer can have different destination (i.e to display same stuff on different laser)
|
|
|
|
Redis :
|
|
- fromKey(keyname) Ask redis for a given key
|
|
- toKey(keyname,keyvalue) Write to redis key
|
|
|
|
OSC and plugins functions :
|
|
|
|
SendLJ(adress,message) LJ remote control. See commands.py
|
|
SendResol(address,message) Send OSC message to Resolume.
|
|
WebStatus(message) display message on webui
|
|
SendIntensity(laser, intensity)
|
|
Sendkpps(laser, kpps)
|
|
|
|
Ljscene(client) Change scene number in redis keys
|
|
Ljlayer(layer) Change layer number in redis keys = laser target.
|
|
ClosePlugin(name) Send UI closing info of given plugin
|
|
|
|
OSCstart() Start the OSC system.
|
|
OSCframe() Handle incoming OSC message. Calling the right callback
|
|
OSCstop() Properly close the OSC system
|
|
OSCping() /ping Answer to LJ pings by sending /pong name
|
|
OSCquit() /quit Exit calling script using name in terminal
|
|
OSCadddest(layer, scene, laser) Add a destination
|
|
OSCdeldest(layer , scene, laser) Delete a destination
|
|
OSCobj() /name/obj objectname attribute value for automation
|
|
OSCvar() /name/var variablename value for automation
|
|
OSCdebug()
|
|
|
|
** Joystick management is removed. Get it back in todolist **
|
|
|
|
setup_controls(joystick)
|
|
|
|
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
|
|
|
|
|
|
|
|
Class management manuals:
|
|
|
|
https://stackoverflow.com/questions/739882/iterating-over-object-instances-of-a-given-class-in-python
|
|
https://stackoverflow.com/questions/8628123/counting-instances-of-a-class
|
|
http://effbot.org/pyfaq/how-do-i-get-a-list-of-all-instances-of-a-given-class.htm
|
|
|
|
|
|
LICENCE : CC
|
|
Sam Neurohack
|
|
|
|
'''
|
|
|
|
import math
|
|
import redis
|
|
import sys
|
|
import weakref
|
|
import struct
|
|
import numpy as np
|
|
import gstt
|
|
from multiprocessing import Process, Queue, TimeoutError
|
|
|
|
is_py2 = sys.version[0] == '2'
|
|
if is_py2:
|
|
from OSC import OSCServer, OSCClient, OSCMessage
|
|
#print ("Importing lj23 and OSC from libs...")
|
|
else:
|
|
from OSC3 import OSCServer, OSCClient, OSCMessage
|
|
#print ("Importing lj23 and OSC3 from libs...")
|
|
|
|
|
|
#redisIP = '127.0.0.1'
|
|
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
|
|
|
ClientNumber = 0
|
|
name = "noname"
|
|
oscrun = True
|
|
point_list = []
|
|
layers = [[],[],[],[],[],[],[],[],[],[]]
|
|
|
|
fft3Groups = [-1,-1,-1,-1]
|
|
|
|
Dests = dict()
|
|
|
|
oscIPresol = "127.0.0.1"
|
|
oscPORTresol = 7000
|
|
|
|
# 3D to 2D projection parameters
|
|
fov = 256
|
|
viewer_distance = 100
|
|
|
|
|
|
'''
|
|
|
|
Laser "objects"
|
|
|
|
|
|
set a name and convenient group of parameters for one or several point lists
|
|
|
|
RelativeObject is for point lists around 0,0 with builtin move/rotation.
|
|
|
|
How to init with object color, xpos,... :
|
|
osciObj = lj.RelativeObject('osciObj', True, 255, [], white, red, green,blue,0 , False, centerX , centerY , 1 , Xrot , Yrot , Zrot)
|
|
How to use in drawing functions : you're free to use 0, some or all of any laserobject attributes
|
|
- draw one or several pointlists with 'A' laserobject color and 'B' laserobject xpos ypos ?
|
|
- Change color of 'main' object and all other objects using it will change also
|
|
how to change attribute :
|
|
osciObj.resize = 2 or /pluginame/change 'OsciObj' 'resize' 2
|
|
|
|
'''
|
|
|
|
class RelativeObject:
|
|
|
|
kind = 'relative'
|
|
counter = 0
|
|
|
|
def __init__(self, name, active, intensity, xy, color, red, green, blue, layer , closed, xpos , ypos , resize , rotx , roty , rotz):
|
|
self.name = name
|
|
self.active = active # True/False
|
|
self.intensity = intensity
|
|
self.xy = [] # Dots list
|
|
self.color = color # RGB color in int
|
|
self.red = red
|
|
self.green = green
|
|
self.blue = blue
|
|
self.layer = layer
|
|
self.closed = closed
|
|
self.xpos = xpos
|
|
self.ypos = ypos
|
|
self.resize = resize
|
|
self.rotx = rotx
|
|
self.roty = roty
|
|
self.rotz = rotz
|
|
|
|
RelativeObject.counter += 1
|
|
#type(self).counter += 1
|
|
|
|
def __del__(self):
|
|
RelativeObject.counter -= 1
|
|
|
|
|
|
# Fixed Laser object : point list in 'pygame' space (top left = 0,0 / bottom right)
|
|
class FixedObject:
|
|
|
|
kind = 'fixed'
|
|
counter = 0
|
|
|
|
def __init__(self, name, intensity, active, xy, color, red, green, blue, layer , closed):
|
|
self.name = name
|
|
self.active = active # True/False
|
|
self.intensity = intensity
|
|
self.xy = []
|
|
self.color = color
|
|
self.red = red
|
|
self.green = green
|
|
self.blue = blue
|
|
self.layer = layer
|
|
self.closed = closed
|
|
|
|
FixedObject.counter += 1
|
|
|
|
def __del__(self):
|
|
FixedObject.counter -= 1
|
|
|
|
'''
|
|
|
|
class IterDest(type):
|
|
def __new__ (cls, name, bases, dct):
|
|
dct['_instances'] = []
|
|
return super().__new__(cls, name, bases, dct)
|
|
|
|
def __call__(cls, *args, **kwargs):
|
|
instance = super().__call__(*args, **kwargs)
|
|
cls._instances.append(instance)
|
|
return instance
|
|
|
|
def __iter__(cls):
|
|
return iter(cls._instances)
|
|
|
|
class DestObject():
|
|
|
|
# class Destinations(metaclass=IterDest):
|
|
__metaclass__ = IterDest
|
|
counter = 0
|
|
def __init__(self, name, number, active, layer , scene, laser):
|
|
self.name = name
|
|
self.number = number
|
|
self.active = active
|
|
self.layer = layer
|
|
self.scene = scene
|
|
self.laser = laser
|
|
|
|
DestObject.counter += 1
|
|
|
|
def __del__(self):
|
|
DestObject.counter -= 1
|
|
'''
|
|
class DestObject():
|
|
|
|
# class Destinations(metaclass=IterDest):
|
|
_instances = set()
|
|
counter = 0
|
|
|
|
def __init__(self, name, number, active, layer , scene, laser):
|
|
self.name = name
|
|
self.number = number
|
|
self.active = active
|
|
self.layer = layer
|
|
self.scene = scene
|
|
self.laser = laser
|
|
self._instances.add(weakref.ref(self))
|
|
DestObject.counter += 1
|
|
|
|
@classmethod
|
|
def getinstances(cls):
|
|
dead = set()
|
|
for ref in cls._instances:
|
|
obj = ref()
|
|
if obj is not None:
|
|
yield obj
|
|
else:
|
|
dead.add(ref)
|
|
cls._instances -= dead
|
|
|
|
|
|
def __del__(self):
|
|
DestObject.counter -= 1
|
|
|
|
|
|
|
|
def Config(redIP,client,myname):
|
|
global ClientNumber, name, redisIP, r
|
|
|
|
redisIP = redIP
|
|
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
|
|
|
# ClientNumber 255 are not drawing anything like artnet
|
|
ClientNumber = client
|
|
#print ("client configured",ClientNumber)
|
|
name = myname
|
|
print ("lj23layers : Plugin declare its name :",name)
|
|
#print layer
|
|
return r
|
|
|
|
|
|
def LjClient(client):
|
|
global ClientNumber
|
|
|
|
ClientNumber = client
|
|
|
|
|
|
|
|
def Ljlayer(somelayer):
|
|
global layer
|
|
|
|
layer = somelayer
|
|
|
|
|
|
def fromRedis(n):
|
|
|
|
encoded = r.get(n)
|
|
#print("")
|
|
#print('fromredis key',n,":",encoded)
|
|
h, w = struct.unpack('>II',encoded[:8])
|
|
#print("fromredis array size",n,":",h,w)
|
|
a = np.frombuffer(encoded, dtype=np.int16, offset=8).reshape(h,w)
|
|
#print("fromredis array",n,":",a)
|
|
return a
|
|
|
|
# Store Numpy array 'a' in Redis key 'n'
|
|
# Write also in redis key 'a' numpy array, its 2 dimensions size : h time w values
|
|
def toRedis(n,a):
|
|
|
|
#print("array.shape", a.shape, len(a.shape) )
|
|
if len(a.shape) == 1:
|
|
h = a.shape[0]
|
|
w = 1
|
|
else:
|
|
h,w = a.shape
|
|
#print("toredis", n,"h",h,"w",w,"a",a)
|
|
shape = struct.pack('>II',h,w)
|
|
|
|
#shape = struct.pack('>II',len(a),1)
|
|
#print("toredis",n,a)
|
|
encoded = shape + a.tobytes()
|
|
|
|
# Store encoded data in Redis
|
|
return r.set(n,encoded)
|
|
|
|
# Ask redis for a given key
|
|
def fromKey(keyname):
|
|
|
|
return r.get(keyname)
|
|
|
|
#
|
|
# Write to redis key
|
|
def toKey(keyname,keyvalue):
|
|
|
|
# Store encoded data in Redis
|
|
return r.set(keyname,keyvalue)
|
|
|
|
|
|
#
|
|
# OSC functions
|
|
#
|
|
|
|
# OSC clients
|
|
|
|
def SendLJ(oscaddress,oscargs=''):
|
|
|
|
oscmsg = OSCMessage()
|
|
oscmsg.setAddress(oscaddress)
|
|
oscmsg.append(oscargs)
|
|
|
|
osclientlj = OSCClient()
|
|
osclientlj.connect((redisIP, 8002))
|
|
#print("lj23layers for", name, "sending OSC message :", oscmsg, "to", redisIP, ":8002")
|
|
|
|
if gstt.debug >0:
|
|
print("lj23layers for", name, "sending OSC message :", oscmsg, "to", redisIP, ":8002")
|
|
|
|
try:
|
|
osclientlj.sendto(oscmsg, (redisIP, 8002))
|
|
oscmsg.clearData()
|
|
|
|
except:
|
|
print ('Connection to LJ refused : died ?')
|
|
pass
|
|
#time.sleep(0.001
|
|
|
|
|
|
|
|
# Resolume OSC Arena client.
|
|
# sendresol(oscaddress, [arg1, arg2,...])
|
|
# example : sendresol("/noteon",note)
|
|
|
|
def SendResol(oscaddress,oscargs):
|
|
|
|
oscmsg = OSCMessage()
|
|
oscmsg.setAddress(oscaddress)
|
|
oscmsg.append(oscargs)
|
|
|
|
osclientresol = OSCClient()
|
|
osclientresol.connect((oscIPresol, oscPORTresol))
|
|
|
|
print("lj23layers sending OSC message : ", oscmsg, "to Resolume", oscIPresol, ":", oscPORTresol)
|
|
try:
|
|
osclientresol.sendto(oscmsg, (oscIPresol, oscPORTresol))
|
|
oscmsg.clearData()
|
|
except:
|
|
print ('Connection to Resolume refused : died ?')
|
|
pass
|
|
|
|
|
|
def SendIntensity(laser, intensity):
|
|
r.set('/intensity/' + str(laser), str(intensity))
|
|
r.set('/order/'+str(laser), 6)
|
|
SendLJ("/kpps/" + str(layer)+ " " + str(int(args[1])))
|
|
|
|
|
|
def Sendkpps(laser, kpps):
|
|
r.set('/kpps/' + str(laser), str(kpps))
|
|
r.set('/order/'+str(laser), 7)
|
|
|
|
|
|
def WebStatus(message):
|
|
SendLJ("/status", message)
|
|
|
|
|
|
# Closing plugin messages to LJ
|
|
def ClosePlugin():
|
|
WebStatus(name+" Exiting")
|
|
SendLJ("/"+name+"/start",0)
|
|
|
|
|
|
|
|
|
|
# RAW OSC Frame available ?
|
|
def OSCframe():
|
|
# clear timed_out flag
|
|
#print "oscframe"
|
|
oscserver.timed_out = False
|
|
# handle all pending requests then return
|
|
while not oscserver.timed_out:
|
|
oscserver.handle_request()
|
|
|
|
# Answer to LJ pings with /pong value
|
|
def OSCping(path, tags, args, source):
|
|
#def OSCping():
|
|
if gstt.debug >0:
|
|
print(name, "lj23layers got /ping from LJ -> reply /pong", name)
|
|
SendLJ("/pong",name)
|
|
|
|
|
|
# Properly close the system.
|
|
def OSCstop():
|
|
oscserver.close()
|
|
|
|
# change debug level (0-2)
|
|
def OSCdebug(path, tags, args, source):
|
|
print("new debug level", args[0] )
|
|
gstt.debug = int(args[0])
|
|
|
|
# /quit
|
|
def OSCquit(path, tags, args, source):
|
|
global oscrun
|
|
|
|
oscrun = False
|
|
print('lj23layers got /quit for',name)
|
|
#WebStatus(name + " quit.")
|
|
#SendLJ("/"+name+"/start",0)
|
|
#print("Stopping OSC...")
|
|
#OSCstop()
|
|
#sys.exit()
|
|
|
|
|
|
# default handler
|
|
def OSChandler(path, tags, args, source):
|
|
|
|
oscaddress = ''.join(path.split("/"))
|
|
print("lj23layers Default OSC Handler for",name,": msg from Client :" + str(source[0]),)
|
|
print("OSC address", path)
|
|
if len(args) > 0:
|
|
print("with args", args)
|
|
|
|
#oscIPout = str(source[0])
|
|
#osclient.connect((oscIPout, oscPORTout))
|
|
|
|
|
|
# for any laser object : /pluginame/obj objectname attribute value
|
|
# like : /pluginname/obj 'fft' 'xpos' 100
|
|
# attributes for all lj Objects: name, xy_list, c, layer
|
|
# + for RelativeObjects : closed, xpos , ypos , resize , rotx , roty , rotz
|
|
def OSCobj(path, tags, args, source):
|
|
|
|
obj = eval(args[0]+"."+ args[1])
|
|
obj = args[2]
|
|
|
|
|
|
def OSCvar(path, tags, args, source):
|
|
|
|
obj = eval(args[0])
|
|
obj = args[1]
|
|
|
|
|
|
def addOSCdefaults(server):
|
|
global oscserver
|
|
|
|
oscserver = server
|
|
oscserver.addMsgHandler( "default", OSChandler )
|
|
oscserver.addMsgHandler( "/ping", OSCping)
|
|
oscserver.addMsgHandler( "/quit", OSCquit)
|
|
oscserver.addMsgHandler( "/debug", OSCdebug)
|
|
oscserver.addMsgHandler( "/"+ name + "/adddest", OSCadddest)
|
|
oscserver.addMsgHandler( "/"+ name + "/deldest", OSCdeldest)
|
|
oscserver.addMsgHandler( "/"+ name + "/dest", OSCdest)
|
|
oscserver.addMsgHandler( "/"+ name + "/obj", OSCobj)
|
|
oscserver.addMsgHandler( "/"+ name + "/var", OSCvar)
|
|
|
|
|
|
|
|
#
|
|
# Color functions
|
|
#
|
|
|
|
# input hexcode = '0xff00ff'
|
|
def hex2rgb(hexcode):
|
|
|
|
hexcode = hexcode[2:]
|
|
return tuple(int(hexcode[i:i+2], 16) for i in (0, 2, 4))
|
|
#return tuple(map(ord,hexcode[1:].decode('hex')))
|
|
|
|
# input rgb=(255,0,255) output '0xff00ff'
|
|
#def rgb2hex(rgb):
|
|
# return '0x%02x%02x%02x' % tuple(rgb)
|
|
|
|
def rgb2hex(r, g, b):
|
|
return hex((r << 16) + (g << 8) + b)
|
|
|
|
|
|
#def rgb2int(rgb):
|
|
# return int('0x%02x%02x%02x' % tuple(rgb),0)
|
|
|
|
def rgb2int(r,g,b):
|
|
return int('0x%02x%02x%02x' % (r,g,b),0)
|
|
|
|
def int2rgb(intcode):
|
|
#hexcode = '0x{0:06X}'.format(intcode)
|
|
hexcode = '{0:06X}'.format(intcode)
|
|
return tuple(int(hexcode[i:i+2], 16) for i in (0, 2, 4))
|
|
|
|
|
|
|
|
#
|
|
# Drawing basic functions
|
|
#
|
|
|
|
# Lines
|
|
def Line(xy1, xy2, c, layer ):
|
|
LineTo(xy1, 0, layer )
|
|
LineTo(xy2, c , layer )
|
|
|
|
def rLine(xy1, xy2, c, layer , xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
|
rLineTo(xy1, 0, layer )
|
|
rLineTo(xy2, c , layer )
|
|
|
|
def LineRGB(xy1, xy2, red,green,blue, layer ):
|
|
|
|
LineTo(xy1, 0, layer )
|
|
LineTo(xy2, int('0x%02x%02x%02x' % (red,green,blue),0) , layer )
|
|
|
|
|
|
# Lineto
|
|
def LineTo(xy, c, layer ):
|
|
|
|
layers[layer].append((xy + (c,)))
|
|
|
|
def LineRGBTo(xy, red, green, blue, layer ):
|
|
|
|
LineTo(xy, int('0x%02x%02x%02x' % (red,green,blue),0), layer )
|
|
|
|
def rLineTo(xy, c, layer , xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
|
|
|
layers[layer ].append((Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz) + (c,)))
|
|
|
|
|
|
# Polylines
|
|
def PolyLineOneColor(xy_list, c, layer , closed ):
|
|
#print "--"
|
|
#print "c",c
|
|
#print "xy_list",xy_list
|
|
#print "--"
|
|
xy0 = None
|
|
for xy in xy_list:
|
|
if xy0 is None:
|
|
xy0 = xy
|
|
#print "xy0:",xy0
|
|
LineTo(xy0,0, layer )
|
|
LineTo(xy0,c, layer )
|
|
else:
|
|
#print "xy:",xy
|
|
LineTo(xy,c, layer )
|
|
if closed:
|
|
LineTo(xy0,c, layer )
|
|
|
|
def PolyLineRGB(xy_list, red, green, blue, layer , closed ):
|
|
|
|
PolyLineOneColor(xy_list, int('0x%02x%02x%02x' % (red,green,blue),0), layer , closed )
|
|
|
|
|
|
# rPolylines
|
|
# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos
|
|
#def rPolyLineOneColor(self, xy_list, c, layer , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
|
def rPolyLineOneColor(xy_list, c, layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
|
xy0 = None
|
|
for xy in xy_list:
|
|
if xy0 is None:
|
|
xy0 = xy
|
|
#if xy == (338.8, -20, 16777215) or xy == (338.8, -20, 255):
|
|
# print(xy, xy0, xpos, ypos, resize, rotx, roty, rotz, Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz))
|
|
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz), 0, layer )
|
|
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz), c, layer )
|
|
else:
|
|
LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz), c, layer )
|
|
if closed:
|
|
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz), c, layer )
|
|
|
|
def rPolyLineRGB(xy_list, red, green, blue, layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
|
|
|
rPolyLineOneColor(xy_list, int('0x%02x%02x%02x' % (red,green,blue),0), layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0)
|
|
|
|
|
|
|
|
# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates
|
|
def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
|
|
|
x = xy[0] * resize
|
|
y = xy[1] * resize
|
|
z = xy[2] * resize
|
|
|
|
rad = math.radians(rotx)
|
|
cosaX = math.cos(rad)
|
|
sinaX = math.sin(rad)
|
|
|
|
y2 = y
|
|
y = y2 * cosaX - z * sinaX
|
|
z = y2 * sinaX + z * cosaX
|
|
|
|
rad = math.radians(roty)
|
|
cosaY = math.cos(rad)
|
|
sinaY = math.sin(rad)
|
|
|
|
z2 = z
|
|
z = z2 * cosaY - x * sinaY
|
|
x = z2 * sinaY + x * cosaY
|
|
|
|
rad = math.radians(rotz)
|
|
cosZ = math.cos(rad)
|
|
sinZ = math.sin(rad)
|
|
|
|
x2 = x
|
|
x = x2 * cosZ - y * sinZ
|
|
y = x2 * sinZ + y * cosZ
|
|
|
|
#print("transf",xy, (x + xpos,y+ ypos))
|
|
factor = resize / (10*(viewer_distance + z))
|
|
#print("resize", resize, "z", z, "factor", factor)
|
|
#print("perspec", xy, (x * factor) + xpos, (- y * factor)+ ypos)
|
|
#print()
|
|
return ((x * factor) + xpos, (y * factor)+ ypos)
|
|
#return (x + xpos, y + ypos)
|
|
|
|
#to understand why it get negative Y
|
|
""" Transforms this 3D point to 2D using a perspective projection. """
|
|
factor = fov / (viewer_distance + z)
|
|
print("z", z, "factor", factor)
|
|
#x = (x * factor)
|
|
#y = (- y * factor)
|
|
print("perspec", xy, (x * factor) + xpos, (- y * factor)+ ypos)
|
|
print()
|
|
return (x + xpos, y + ypos)
|
|
#return (x, y)
|
|
|
|
|
|
def Lineslayer(layer):
|
|
print("Stupido !! your code is to old : use Drawlayer() instead of LinesPL()")
|
|
Drawlayer(layer )
|
|
|
|
|
|
def Draw(layer):
|
|
#print '/pl/0/'+str(layer), str(layers[layer])
|
|
if r.set('/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])) == True:
|
|
#print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])
|
|
layers[layer] = []
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def Resetlayer(self, layer):
|
|
layers[layer] = []
|
|
|
|
|
|
#
|
|
# "Destinations" management for layers
|
|
#
|
|
|
|
|
|
# Add a destination for a given layer
|
|
def Addest(layer, scene, laser):
|
|
|
|
print (name,'adding',layer,scene,laser,'?')
|
|
if Findest(layer, scene, laser) == -1:
|
|
newdest = DestsObjects.counter + 1
|
|
Dest0 = lj.DestObject(str(newdest), newdest, True, layer , scene, laser)
|
|
print("New destination added with number", newdest)
|
|
else:
|
|
print("Destination already existed")
|
|
|
|
|
|
# OSC add a destination for a given layer
|
|
# /pluginame/dest layer, scene, laser
|
|
def OSCadddest(path, tags, args, source):
|
|
|
|
Addests(int(args[0]),int(args[1]),int(args[2]))
|
|
|
|
|
|
# Find layer destination with its parameters in destinations dictionnary
|
|
def Findest(layer, scene, laser):
|
|
|
|
print(name, 'searching layer,scene,laser',layer,scene,laser)
|
|
for item in DestObjects.getinstances():
|
|
#print(item)
|
|
if item.layer == layer and item.scene == scene and item.laser == laser:
|
|
#Dests.append(item[0])
|
|
print('found number',item.number)
|
|
return item.number
|
|
else:
|
|
print('no destination found')
|
|
return -1
|
|
'''
|
|
#Dests = list()
|
|
allDests = Dests.items()
|
|
for item in allDests:
|
|
print(item)
|
|
if item[1] == layer and item[2] == scene and item[3] == laser:
|
|
#Dests.append(item[0])
|
|
return Dests[item[0]]
|
|
else:
|
|
return -1
|
|
'''
|
|
|
|
# Find and remove a layer destination with its parameters in destinations dictionnary
|
|
def Deldest(layer, scene, laser):
|
|
|
|
Destnumber = Findest(layer, scene, laser)
|
|
print(name,'deleting Destination layer, scene, laser', layer,scene, laser)
|
|
|
|
if Destnumber != -1:
|
|
print('found DestObject', Destnumber)
|
|
delattr(DestObjects, str(Destnumber))
|
|
print("Destination", Destnumber,"was removed")
|
|
else:
|
|
print("Destination was not found")
|
|
|
|
|
|
# OSC Delete a destination for a given layer
|
|
# /pluginame/deldests layer, scene, laser
|
|
def OSCdeldest(path, tags, args, source):
|
|
|
|
Deldests(args[0], args[1], args[2])
|
|
|
|
|
|
# pluginame/dest layer, scene, laser
|
|
def OSCdest(path, tags, args, source):
|
|
|
|
# For single layer plugin : add a new destination
|
|
Addest(0, args[0], args[1])
|
|
|
|
# For single layer plugin : remove a destination
|
|
|
|
# For multiple layers plugin : add or remove
|
|
|
|
|
|
# Replace Drawlayer if Destinations paradigm is implemented in plugin code
|
|
def DrawDests():
|
|
|
|
# Objects style
|
|
|
|
#print("DrawDest")
|
|
|
|
for destination in DestObject.getinstances():
|
|
|
|
#print(Dests[str(destination)])
|
|
#print('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), ":", str(layers[Dests[str(destination)]["PL"]]))
|
|
#print(len(layers[destination.layer]))
|
|
if destination.active == True:
|
|
if r.set('/pl/'+str(destination.scene)+'/'+str(destination.laser), str(layers[destination.layer])) == True:
|
|
#print ('layer', destination.layer, '/pl/'+str(destination.scene)+'/'+str(destination.laser), str(layers[destination.layer]))
|
|
pass
|
|
else:
|
|
print('Redis key modification failed')
|
|
|
|
# Maybe one layer can be sent to multiple destination so they are all reset *after* all sending.
|
|
for layerss in range(4):
|
|
|
|
layers[layerss] = []
|
|
|
|
'''
|
|
# Dictionnary style
|
|
|
|
#print(Dests)
|
|
for destination in range(len(Dests)):
|
|
#print(Dests[str(destination)])
|
|
#print('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), ":", str(layers[Dests[str(destination)]["layer"]]))
|
|
if r.set('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), str(layers[Dests[str(destination)]["layer"]])) == True:
|
|
#print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])
|
|
pass
|
|
else:
|
|
print('Redis key modification failed')
|
|
|
|
# Maybe one layer can be sent to multiple destination so they are all reset *after* all sending.
|
|
for destination in range(len(Dests)):
|
|
|
|
layers[Dests[str(destination)]["layer"]] = []
|
|
'''
|
|
'''
|
|
scenes = 4
|
|
|
|
def DrawDestslayer(layer):
|
|
|
|
for scene in range(scenes):
|
|
|
|
if Dests[laser]["scene"] != -1:
|
|
if r.set('/pl/'+str(Dests[laser]["scene"])+'/'+str(Dests[laser]["laser"]), str(layers[Dests[laser]["laser"]])) == True:
|
|
if r.set('/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])) == True:
|
|
#print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])
|
|
layers[Dests[laser]["laser"]] = []
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
'''
|
|
|
|
#
|
|
# High level drawing functions
|
|
#
|
|
|
|
|
|
# Font1
|
|
|
|
|
|
ASCII_GRAPHICS = [
|
|
|
|
#implementé
|
|
|
|
[(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], # 0
|
|
[(-20,30), (0,-30), (-20,30)], # 1
|
|
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # 2
|
|
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # 3
|
|
[(30,10), (-30,10), (0,-30), (0,30)], # 4
|
|
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # 5
|
|
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # 6
|
|
[(-30,-30), (30,-30), (-30,30)], # 7
|
|
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], # 8
|
|
[(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], # 9
|
|
|
|
# A implementer
|
|
[(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #:
|
|
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # ;
|
|
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # <
|
|
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # =
|
|
[(30,10), (-30,10), (0,-30), (0,30)], # >
|
|
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # ?
|
|
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # @
|
|
|
|
# Implementé 65-90
|
|
|
|
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A
|
|
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A
|
|
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], # B
|
|
[(30,30), (-30,30), (-30,-30), (30,-30)], # C
|
|
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], # D
|
|
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # E
|
|
[(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # F
|
|
[(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], # G
|
|
[(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], # H
|
|
[(0,30), (0,-30)], # I
|
|
[(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], # J
|
|
[(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], # K
|
|
[(30,30), (-30,30), (-30,-30)], # L
|
|
[(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], # M
|
|
[(-30,30), (-30,-30), (30,30), (30,-30)], # N
|
|
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], # O
|
|
[(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], # P
|
|
[(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], # Q
|
|
[(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], # R
|
|
[(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], # S
|
|
[(0,30), (0,-30), (-30,-30), (30,-30)], # T
|
|
[(-30,-30), (-30,30), (30,30), (30,-30)], # U
|
|
[(-30,-30), (0,30), (30,-30)], # V
|
|
[(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], # W
|
|
[(-30,30), (30,-30), (-30,-30), (30,30)], # X
|
|
[(0,30), (0,0), (30,-30), (0,0), (-30,-30)], # Y
|
|
[(30,30), (-30,30), (30,-30), (-30,-30)], # Z
|
|
|
|
# A implementer
|
|
|
|
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # [
|
|
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # \
|
|
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # ]
|
|
[(30,10), (-30,10), (0,-30), (0,30)], # ^
|
|
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # _
|
|
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # `
|
|
|
|
# Implementé 97-122
|
|
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], # b
|
|
[(20,20), (-20,20), (-20,-20), (20,-20)], # c
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # d
|
|
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # e
|
|
[(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # f
|
|
[(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], # g
|
|
[(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], # h
|
|
[(0,20), (0,-20)], # i
|
|
[(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], # j
|
|
[(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], # k
|
|
[(20,20), (-20,20), (-20,-20)], # l
|
|
[(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], # m
|
|
[(-20,20), (-20,-20), (20,20), (20,-20)], # n
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o
|
|
[(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], # p
|
|
[(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], # q
|
|
[(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], # r
|
|
[(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], # s
|
|
[(0,20), (0,-20), (-20,-20), (20,-20)], # t
|
|
[(-20,-20), (-20,20), (20,20), (20,-20)], # u
|
|
[(-20,-20), (0,20), (20,-20)], # v
|
|
[(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], # w
|
|
[(-20,20), (20,-20)], [(-20,-20), (20,20)], # x
|
|
[(0,20), (0,0), (20,-20), (0,0), (-20,-20)], # y
|
|
[(20,20), (-20,20), (20,-20), (-20,-20)], # z
|
|
|
|
# A implementer
|
|
[(-2,15), (2,15)], # Point a la place de {
|
|
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # |
|
|
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # }
|
|
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #
|
|
[(30,10), (-30,10), (0,-30), (0,30)], # DEL
|
|
|
|
# Accents 128-151 a implementer
|
|
[(30,30), (-30,30), (-30,-30), (30,-30)], # C
|
|
[(-20,-20), (-20,20), (20,20), (20,-20)], # û
|
|
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # é
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # â
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # ä
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a
|
|
[(20,20), (-20,20), (-20,-20), (20,-20)], # c
|
|
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # é
|
|
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # é
|
|
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # é
|
|
[(0,20), (0,-20)], # i
|
|
[(0,20), (0,-20)], # i
|
|
[(0,20), (0,-20)], # i
|
|
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A
|
|
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A
|
|
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # E
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o
|
|
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o
|
|
[(-20,-20), (-20,20), (20,20), (20,-20)], # u
|
|
[(-20,-20), (-20,20), (20,20), (20,-20)] # u
|
|
|
|
]
|
|
|
|
|
|
def DigitsDots(number,color):
|
|
dots =[]
|
|
for dot in ASCII_GRAPHICS[number]:
|
|
#print dot
|
|
dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color))
|
|
#self.point_list.append((xy + (c,)))
|
|
return dots
|
|
|
|
def CharDots(char,color):
|
|
|
|
dots =[]
|
|
for dot in ASCII_GRAPHICS[ord(char)-46]:
|
|
dots.append((dot[0],dot[1],color))
|
|
return dots
|
|
|
|
def Text(message, zpos, c, layer, xpos, ypos, resize, rotx, roty, rotz):
|
|
|
|
dots =[]
|
|
|
|
l = len(message)
|
|
i= 0
|
|
#print()
|
|
# print (message)
|
|
|
|
for ch in message:
|
|
|
|
#print ""
|
|
# texte centre en x automatiquement selon le nombre de lettres l
|
|
x_offset = 26 * (- (0.9*l) + 3*i)
|
|
# Digits
|
|
if ord(ch)<58:
|
|
char_layer_list = ASCII_GRAPHICS[ord(ch) - 48]
|
|
|
|
# Uppercase
|
|
elif 64 < ord(ch) < 91 :
|
|
char_layer_list = ASCII_GRAPHICS[ord(ch) - 46]
|
|
|
|
# Lowercase
|
|
elif 96 < ord(ch) < 123 :
|
|
char_layer_list = ASCII_GRAPHICS[ord(ch) - 45]
|
|
|
|
char_draw = []
|
|
#dots.append((char_layer_list[0][0] + x_offset,char_layer_list[0][1],0))
|
|
|
|
for xy in char_layer_list:
|
|
char_draw.append((xy[0] + x_offset,xy[1], zpos))
|
|
i +=1
|
|
rPolyLineOneColor(char_draw, c, layer , False, xpos, ypos, resize, rotx, roty, rotz)
|
|
#dots.append(char_draw)
|
|
|
|
def TextRGB(message, zpos, c, layer, xpos, ypos, resize, rotx, roty, rotz):
|
|
|
|
Text(message, zpos, int('0x%02x%02x%02x' % (red,green,blue),0), layer, xpos, ypos, resize, rotx, roty, rotz)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|