From 8d014f88994c5c5d616aca790bf80b7abb2c5198 Mon Sep 17 00:00:00 2001 From: mdan Date: Thu, 27 Jan 2011 17:57:47 -0500 Subject: Mirrors fix from main branch. --- renderers/PygameRenderer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderers/PygameRenderer.py b/renderers/PygameRenderer.py index 9582a03..220f861 100644 --- a/renderers/PygameRenderer.py +++ b/renderers/PygameRenderer.py @@ -9,11 +9,11 @@ class PygameRenderer(Renderer): self.screen = pygame.display.set_mode((1300,500)) self.background = pygame.Surface(self.screen.get_size()) self.background = self.background.convert() - self.background.fill(Color('Black')) + self.background.fill(Color(0,0,0)) self.stopwatch = timeops.Stopwatch() self.stopwatch.start() def render(self, lightSystem, currentTime=timeops.time()): - self.background.fill(Color('Black')) + self.background.fill(Color(0,0,0)) #print 'drawing color:',light.color for light in lightSystem: pygame.draw.circle(self.background, light.state(currentTime), light.location, \ -- cgit v1.2.3 From 44659801073c059aeac5a992dc241648263c74b6 Mon Sep 17 00:00:00 2001 From: mdan Date: Thu, 27 Jan 2011 17:58:47 -0500 Subject: Modifies OSC configuration and behavior. --- behaviors/TouchOSC.py | 3 ++- config/6thFloorOSC.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/behaviors/TouchOSC.py b/behaviors/TouchOSC.py index 1c41b5e..354b845 100644 --- a/behaviors/TouchOSC.py +++ b/behaviors/TouchOSC.py @@ -12,7 +12,8 @@ class TouchOSC(Behavior): self.xy = (-1,-1) def processResponse(self, sensorInputs, recursiveInputs): ret = [] - for data in sensorInputs: + if sensorInputs: + data = sensorInputs[-1]#for data in sensorInputs: if data['Path'] == '/1/fader1': try: self.h = data['Value'][0]*360.0 diff --git a/config/6thFloorOSC.xml b/config/6thFloorOSC.xml index 792fd0c..d3f0e6f 100644 --- a/config/6thFloorOSC.xml +++ b/config/6thFloorOSC.xml @@ -42,7 +42,7 @@ osc 12345 - 10 + 20 -- cgit v1.2.3 From 6341992254c837b1d814b3eaa24b2ab3e729c8e2 Mon Sep 17 00:00:00 2001 From: eugue Date: Thu, 27 Jan 2011 20:27:12 -0500 Subject: Added HTMLInput, SmootWind behavior, and a config file for testing. --- behaviors/SmootWind.py | 32 +++++++ behaviors/XYMove.py | 2 +- config/HTMLTest.xml | 58 +++++++++++++ config/SmootWindTest.xml | 166 +++++++++++++++++++++++++++++++++++++ inputs/HTMLInput.py | 29 +++++++ pixelmappers/WindGaussianMapper.py | 18 ++++ util/Geo.py | 6 ++ 7 files changed, 310 insertions(+), 1 deletion(-) create mode 100755 behaviors/SmootWind.py create mode 100755 config/HTMLTest.xml create mode 100755 config/SmootWindTest.xml create mode 100755 inputs/HTMLInput.py create mode 100755 pixelmappers/WindGaussianMapper.py diff --git a/behaviors/SmootWind.py b/behaviors/SmootWind.py new file mode 100755 index 0000000..bf05ab2 --- /dev/null +++ b/behaviors/SmootWind.py @@ -0,0 +1,32 @@ +from operationscore.Behavior import * +import util.ComponentRegistry as compReg + +class SmootWind(Behavior): + def behaviorInit(self): + self.mapper = None + self.xFor = None + + def processResponse(self, sensorInputs, recursiveInputs): + if self.mapper == None: + try: + self.mapper = compReg.getComponent('windgaussmap') + except KeyError: + pass + if self.xFor == None: + try: + self.xFor = compReg.getComponent('xfor') + except KeyError: + pass + + for sensory in sensorInputs: + #print sensory + # input[0] is windspeed, [1] is dir + windSpeed = sensory[0] + windDir = sensory[1] + + #print self.mapper.argDict + self.mapper.argDict['Width'] = float(windSpeed) ** 3 + self.xFor.argDict['ParamOp'] = float(windSpeed) ** 2 + #print 'Width: ' + str(self.mapper.argDict['Width']) + #print 'xFor: ' + str(self.xFor.argDict['ParamOp']) + return (sensorInputs, recursiveInputs) diff --git a/behaviors/XYMove.py b/behaviors/XYMove.py index 0ba3baf..44a93bb 100644 --- a/behaviors/XYMove.py +++ b/behaviors/XYMove.py @@ -13,7 +13,7 @@ class XYMove(Behavior): for loc in sensor: oploc = dict(loc) self.insertStepIfMissing(oploc) - print oploc['YStep'] + #print oploc['YStep'] oploc['Location'] = Geo.addLocations((oploc['XStep'], oploc['YStep']), oploc['Location']) ret.append(oploc) return (ret, []) diff --git a/config/HTMLTest.xml b/config/HTMLTest.xml new file mode 100755 index 0000000..159cec4 --- /dev/null +++ b/config/HTMLTest.xml @@ -0,0 +1,58 @@ + + + + simplemap + + + + layouts/BasicSixStrip.xml + + + + pixelmappers.SimpleMapper + + simplemap + 20 + + + + pixelmappers.GaussianMapper + + gaussmap + 30 + 0.1 + 10 + 1 + + + + + + renderers/Pygame.xml + + + + + inputs.HTMLInput + + weatherinput + 'http://sailing.mit.edu/weather/' + + 'rtWindSpeed = (\d+).*\s.*\s.*rtWindDir = (\d+)' + + + + + + + behaviors.EchoBehavior + + + weatherinput + + echo + False + + + + diff --git a/config/SmootWindTest.xml b/config/SmootWindTest.xml new file mode 100755 index 0000000..a494720 --- /dev/null +++ b/config/SmootWindTest.xml @@ -0,0 +1,166 @@ + + + + + simplemap + + + + layouts/60StripLayout.xml + + + + + pixelmappers.SimpleMapper + + simplemap + 20 + + + + pixelmappers.GaussianMapper + + gaussmap + 10 + 0.1 + 10 + 5 + + + + pixelmappers.WindGaussianMapper + + windgaussmap + 150 + 0.005 + 30 + 10 + + + + + + + renderers/Pygame.xml + + + + + inputs.PygameInput + + pygame + 1 + + + + inputs.HTMLInput + + weatherinput + 'http://sailing.mit.edu/weather/' + + 'rtWindSpeed = (\d+).*\s.*\s.*rtWindDir = (\d+)' + + + + + inputs.RandomLocs + + randomLoc + + + + + + behaviors/RandomColor.xml + + + behaviors/RandomColor.xml + + + (100,200,255) + (50,200,255) + (0,200,255) + (0,150,255) + + + + + behaviors/PixelDecay.xml + + + behaviors.XYMove + + xymove + 0 + 0 + + + + behaviors.BehaviorChain + + movebounce + + xymove + yfor + xfor + + + + + behaviors.ModifyParam + + yfor + YStep + Sensor + 10*(2*math.sin({x}/float(100))+math.sin({x}/float(50))) + + + + + behaviors.ModifyParam + + xfor + XStep + Sensor + + 25 + + + + + behaviors.SmootWind + + smootwind + + weatherinput + + + + + behaviors.ResponseMover + + mover + + + + behaviors.BehaviorChain + + xymover + + pygame + randomLoc + + + staticcolor + mover + decay + + {'mover':'movebounce'} + True + windgaussmap + + + + diff --git a/inputs/HTMLInput.py b/inputs/HTMLInput.py new file mode 100755 index 0000000..9697a32 --- /dev/null +++ b/inputs/HTMLInput.py @@ -0,0 +1,29 @@ +from operationscore.Input import * +import urllib, re + +""" +HTML Input, which takes 2 arguments: +- 'Src': a URL to a web page, and +- 'Regex': a Regex to parse data out of the web page. +The input parses the source code of the web page according to the regex, and processes the parsed regex groups. +""" +class HTMLInput(Input): + def inputInit(self): + self.src = self.argDict['Src'] + self.regex = self.argDict['Regex'] + + def getHTML(self): + self.sock = urllib.urlopen(self.src); + self.html = self.sock.read() + self.sock.close() + + def sensingLoop(self): + self.getHTML() + self.dataList = [] + + pattern = re.compile(self.regex) + matchObj = pattern.search(self.html) + self.dataList = matchObj.groups() + + self.respond(self.dataList) + diff --git a/pixelmappers/WindGaussianMapper.py b/pixelmappers/WindGaussianMapper.py new file mode 100755 index 0000000..c5d77ca --- /dev/null +++ b/pixelmappers/WindGaussianMapper.py @@ -0,0 +1,18 @@ +from operationscore.PixelMapper import * +import util.Geo as Geo +import math +class WindGaussianMapper(PixelMapper): + def mappingFunction(self, eventLocation, screen): + returnPixels = [] #TODO: consider preallocation and trimming + [x,y] = eventLocation + potentialPixels = screen.pixelsInRange(x-self.CutoffDist, x) + for (xloc,pixel) in screen.pixelsInRange(x-self.CutoffDist, x): + pixelDistx = math.fabs(pixel.location[0] - x) + pixelDisty = math.fabs(pixel.location[1] - y) + if pixelDistx < self.CutoffDist: + if pixelDisty < 30: + w = Geo.windtrail(pixelDistx, pixelDisty, self.Height, 0, self.Width) + if w > self.MinWeight: + returnPixels.append((pixel, w)) + + return returnPixels diff --git a/util/Geo.py b/util/Geo.py index 05ea9fe..0dde80b 100644 --- a/util/Geo.py +++ b/util/Geo.py @@ -26,3 +26,9 @@ def randomLoc(boundingBox): #TODO: make less shitty def approxexp(x): """Approximates exp with a 3 term Taylor Series.""" return 1+x+x**2/2+x**3/6 + +def windtrail(x,y,height,center,width): + a=height + b=center + c=width + return a*((math.exp(-((x-b))/(c)))**2)*(math.exp(-((y))/(0.2*c)))**2 -- cgit v1.2.3 From b8bb5e82a2e8802b9adb1258463d4198f974dbd1 Mon Sep 17 00:00:00 2001 From: mdan Date: Fri, 28 Jan 2011 09:19:11 -0500 Subject: added behavior for sixaxis controller over OSC-- untested --- behaviors/ControllerOSC.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 behaviors/ControllerOSC.py diff --git a/behaviors/ControllerOSC.py b/behaviors/ControllerOSC.py new file mode 100644 index 0000000..6e3e814 --- /dev/null +++ b/behaviors/ControllerOSC.py @@ -0,0 +1,62 @@ +from operationscore.Behavior import * +from logger import main_log +#import util.ColorOps as color +import colorsys +from numpy import arrray +import pdb +import util.ComponentRegistry as compReg + +def constrain(v,c): + if v[0] > c[1]: + v[0] = c[1] + elif v[0]<0 + v[0] = 0 + + if v[1] > c[0]: + v[1] = c[0] + elif v[1]<0 + v[1] = 0 + + return v + +class TouchOSC(Behavior): + def behaviorInit(self): + self.xy = array((0,0)) + self.v_xy = array((0,0)) + self.v_decay = .1 + + self.start_hsv = (0,1,1) + self.dest_hsv = (0,1,1) + + def processResponse(self, sensorInputs, recursiveInputs): + ret = [] + if sensorInputs: + data = sensorInputs[-1]#for data in sensorInputs: + if data['Path'] == '/sixaxis/xy': + try: + x = data['Value'][0] + y = data['Value'][1] + if y < 0: + self.start_hsv[1] = 1+y #s + else: + self.start_hsv[2] = y + self.h += x +#self.h = x * 360. + + except: + pdb.set_trace() + elif data['Path'] == '/sixaxis/lrud': + val=data['Value'] + ssize = compReg.getComponent('Screen').getSize()[-2:] #896 x 310 + vx = -val[3] if val[3] else val[2] + vy = -val[0] if val[0] else val[1] + #self.v_xy = (val[1]*ssize[0], (1.0-val[0])*ssize[1]) + self.v_xy = array((vx, vy)) + else: + main_log.error('Sensor Inputs: ' + str(sensorInputs)) + self.xy = self.xy + self.v_xy + constrain(self.xy,ssize) + self.v_xy -= self.v_decay + ret.append({'Color':[i*256 for i in colorsys.hsv_to_rgb(*self.start_hsv)],'Location':tuple(self.xy)}) + + return (ret, []) -- cgit v1.2.3 From 3319a58ecc391f9aac092ade45f9f50dc2af5aa6 Mon Sep 17 00:00:00 2001 From: rcoh Date: Fri, 28 Jan 2011 09:50:38 -0500 Subject: Finishing up for the demo --- behaviors/Accelerate.xml | 2 +- behaviors/DimColor.xml | 2 +- behaviors/Expand.py | 3 ++- behaviors/MITDoors.py | 7 +++++++ behaviors/ResponseMover.py | 8 +------- behaviors/XYMove.py | 1 - config/6thFloor.xml | 2 +- inputs/PygameInput.py | 2 +- pixelcore/Screen.py | 19 +++++++------------ 9 files changed, 21 insertions(+), 25 deletions(-) diff --git a/behaviors/Accelerate.xml b/behaviors/Accelerate.xml index f9de077..c78195b 100644 --- a/behaviors/Accelerate.xml +++ b/behaviors/Accelerate.xml @@ -3,6 +3,6 @@ Sensor StepSize - {val}*1.1 + {val}*1.01 diff --git a/behaviors/DimColor.xml b/behaviors/DimColor.xml index 58b0673..ef98fee 100644 --- a/behaviors/DimColor.xml +++ b/behaviors/DimColor.xml @@ -3,6 +3,6 @@ Sensor Color - [chan*.95 for chan in {val}] + [chan*.98 for chan in {val}] diff --git a/behaviors/Expand.py b/behaviors/Expand.py index 323e71f..f017c16 100644 --- a/behaviors/Expand.py +++ b/behaviors/Expand.py @@ -15,7 +15,8 @@ class Expand(Behavior): data = dict(data) data['Left'] -= data['ExpandRate'] data['Right'] += data['ExpandRate'] - data['Location'] = "{x}>" + str(data['Left']) + ", {x}<" + str(data['Right']) + data['Location'] = "{x}>" + str(data['Left']) + ", {x}<" +\ + str(data['Right'])+", {y}<50" ret.append(data) return (ret, []) diff --git a/behaviors/MITDoors.py b/behaviors/MITDoors.py index d602a55..03bef6d 100644 --- a/behaviors/MITDoors.py +++ b/behaviors/MITDoors.py @@ -1,4 +1,6 @@ from operationscore.Behavior import * +import math +import util.ComponentRegistry as compReg class MITDoors(Behavior): """MITDoors is a case-specific behavior to map keypresses to specific locations. Written for Kuan 1/26/11 by RCOH""" @@ -6,6 +8,11 @@ class MITDoors(Behavior): def behaviorInit(self): self.keymapping = {'q':[2,19], 'w':[22,36], 'e':[37,49], 'r':[52,69], 't':[76,91], 'y':[94,105], 'u':[106,117], 'i':[123,154], 'o':[158,161], 'p':[164,167], '[':[172,184]} + screenWidth = compReg.getComponent('Screen').getSize()[2] #(minx, miny,maxx, maxy) + maxKey = max([max(self.keymapping[v]) for v in self.keymapping]) + mult = screenWidth / float(maxKey) + for k in self.keymapping: + self.keymapping[k] = [int(val*mult) for val in self.keymapping[k]] def processResponse(self, sensorInputs, recursiveInputs): ret = [] for data in sensorInputs: diff --git a/behaviors/ResponseMover.py b/behaviors/ResponseMover.py index 59e353a..3d559df 100644 --- a/behaviors/ResponseMover.py +++ b/behaviors/ResponseMover.py @@ -7,11 +7,5 @@ class ResponseMover(Behavior): modulates the location.""" def processResponse(self, sensorInputs, recursiveInputs): - newResponses = sensorInputs - ret = [] - for recurInput in recursiveInputs: - outDict = dict(recurInput) - ret.append(outDict) - ret += newResponses - return (ret, ret) + return (recursiveInputs, recursiveInputs+sensorInputs) diff --git a/behaviors/XYMove.py b/behaviors/XYMove.py index 0ba3baf..11cee96 100644 --- a/behaviors/XYMove.py +++ b/behaviors/XYMove.py @@ -13,7 +13,6 @@ class XYMove(Behavior): for loc in sensor: oploc = dict(loc) self.insertStepIfMissing(oploc) - print oploc['YStep'] oploc['Location'] = Geo.addLocations((oploc['XStep'], oploc['YStep']), oploc['Location']) ret.append(oploc) return (ret, []) diff --git a/config/6thFloor.xml b/config/6thFloor.xml index 81f0c9f..ef195ec 100644 --- a/config/6thFloor.xml +++ b/config/6thFloor.xml @@ -186,7 +186,7 @@ behaviors.BehaviorChain - inpexpanddim + doors pygamekey diff --git a/inputs/PygameInput.py b/inputs/PygameInput.py index 399a77e..18f463d 100644 --- a/inputs/PygameInput.py +++ b/inputs/PygameInput.py @@ -23,7 +23,7 @@ class PygameInput(Input): if event.key == 27: self.die() if self['Keyboard']: - self.respond({'Key': event.key}) + self.respond({'Key': event.key, 'KeyChar': chr(event.key)}) return else: pygame.event.post(event) diff --git a/pixelcore/Screen.py b/pixelcore/Screen.py index 9a81df7..ada8d4a 100644 --- a/pixelcore/Screen.py +++ b/pixelcore/Screen.py @@ -22,14 +22,14 @@ class Screen: sizeValid = False self.pixelsSorted = False - def addStrip(self, lS): - self.pixelStrips.append(lS) + def addStrip(self, strip): + self.pixelStrips.append(strip) self.sizeValid = False #keep track of whether or not our screen size has self.pixelsSorted = False #been invalidated by adding more pixels def pixelsInRange(self, minX, maxX): - """Returns (pixelIndex, pixel). Does a binary search.""" + """Returns (pixelIndex, pixel). Does a binary search. Sorts first if neccesary.""" if not self.pixelsSorted: self.computeXSortedPixels() minIndex = Search.find_ge(self.xPixelLocs, minX) @@ -48,12 +48,11 @@ class Screen: return itertools.chain(*[strip.__iter__() for strip in \ self.pixelStrips]) #the * operator breaks the list into args - #increment time -- This processes all queued responses. Responses generated - #during this period are added to the queue that will be processed on the next - #time step. #SUBVERTING DESIGN FOR EFFICIENCY 1/24/11, RCOH -- It would be cleaner to store the time on the responses #themselves, however, it is faster to just pass it in. def timeStep(self, currentTime=None): + """Increments time -- This processes all queued responses, adding that to a queue that will + be processed on the next time step.""" if currentTime == None: currentTime = timeops.time() tempQueue = list(self.responseQueue) @@ -66,6 +65,7 @@ class Screen: self.responseQueue.append(responseInfo) def getSize(self): + """Returns the size of the screen in the form: (minx, miny, maxx, maxy)""" if self.sizeValid: return self.size (minX, minY, maxX, maxY) = (sys.maxint,sys.maxint,-sys.maxint,-sys.maxint) @@ -79,24 +79,19 @@ class Screen: maxY = max(y, maxY) self.size = (0,0, maxX, maxY) self.sizeValid = True - print self.size - return (0, 0, maxX+100, maxY+100) #TODO: cleaner + return (0, 0, maxX, maxY) #private def processResponse(self, responseInfo, currentTime=None): #we need to make a new dict for #each to prevent interference - #[strip.respond(dict(responseInfo)) for strip in self.pixelStrips] if currentTime == None: currentTime = timeops.time() - print 'cachetime fail' if type(responseInfo) != type(dict()): pass if 'Mapper' in responseInfo: mapper = compReg.getComponent(responseInfo['Mapper']) else: mapper = compReg.getComponent(Strings.DEFAULT_MAPPER) - #if type(mapper) != type(PixelMapper): - # raise Exception('No default mapper specified.') pixelWeightList = mapper.mapEvent(responseInfo['Location'], self) main_log.debug('Screen processing response. ' + str(len(pixelWeightList)) + ' events\ generated') -- cgit v1.2.3 From ef1abfa913498e02a4ece3be4be45d2f03e47d05 Mon Sep 17 00:00:00 2001 From: rcoh Date: Fri, 28 Jan 2011 15:19:21 -0500 Subject: Lots of stuff INCOMPLETE --- LightInstallation.py | 2 +- behaviors/ExpandingColorZones.py | 7 ++++--- behaviors/MITDoors.py | 1 + behaviors/RiseFall.py | 6 ++++++ behaviors/SmootWind.py | 24 +++++++++++++++++------- config/6thFloorOSC.xml | 30 +++++++++++++++++++++++++++++- config/Jennifer.xml | 1 + config/Kuan.xml | 9 +++++++++ config/SmootWindTest.xml | 12 ++++++++++-- inputs/OSCInput.py | 4 ++-- inputs/PygameInput.py | 5 ++++- pixelcore/Pixel.py | 4 +++- renderers/IndoorRenderer.py | 7 ++++++- util/NetworkOps.py | 6 ++++++ util/PacketComposition.py | 15 ++++++++++++--- 15 files changed, 111 insertions(+), 22 deletions(-) diff --git a/LightInstallation.py b/LightInstallation.py index 24ad8b1..c1f01e8 100755 --- a/LightInstallation.py +++ b/LightInstallation.py @@ -139,7 +139,7 @@ class LightInstallation(object): def mainLoop(self): lastLoopTime = clock.time() - refreshInterval = 30 + refreshInterval = 30 while not self.dieNow: #dieNow is set if one of its constituents sends a die request. loopStart = clock.time() responses = self.evaluateBehaviors() diff --git a/behaviors/ExpandingColorZones.py b/behaviors/ExpandingColorZones.py index 345851e..75be761 100644 --- a/behaviors/ExpandingColorZones.py +++ b/behaviors/ExpandingColorZones.py @@ -2,13 +2,14 @@ from operationscore.Behavior import * from logger import main_log class ExpandingColorZones(Behavior): def behaviorInit(self): - self.mapping = {'r':[(132,0),(255,0,0)], 'g':[(400,0), (0,255,0)], - 'b':[(668,0), + self.mapping = {'s001':[(132,0),(255,0,0)], 's002':[(400,0), (0,255,0)], + 's003':[(668,0), (0,0,255)]} - self.mappingkey = 'KeyChar' + self.mappingkey = 'data' def processResponse(self, sensorInputs, recursiveInputs): ret = [] for data in sensorInputs: + print data data = dict(data) if self.mappingkey in data: try: diff --git a/behaviors/MITDoors.py b/behaviors/MITDoors.py index 03bef6d..cee47f0 100644 --- a/behaviors/MITDoors.py +++ b/behaviors/MITDoors.py @@ -23,5 +23,6 @@ class MITDoors(Behavior): data['Left'], data['Right'] = bounds data['Bottom'] = self['Bottom'] data['Location'] = (sum(bounds) / 2., self['Bottom']) + data['Oscillate'] = False ret.append(data) return (ret, []) diff --git a/behaviors/RiseFall.py b/behaviors/RiseFall.py index 109cd10..eea2283 100644 --- a/behaviors/RiseFall.py +++ b/behaviors/RiseFall.py @@ -29,7 +29,13 @@ class RiseFall(Behavior): data['Right'] = data['Location'][0]+data['Width']/2. currentTime = timeOps.time() deltaTime = currentTime-data['StartTime'] + #if data['Oscillate'] == True: data['Height'] = data['MaxHeight']*math.sin(deltaTime/data['Period']*(math.pi*2)) + #else: + # data['Height'] = data['MaxHeight'] + #if (currentTime-data['StartTime']) > data['Period']: + # del data['StartTime'] + data['Location'] = "{x}>"+str(data['Left']) + ", " +\ "{x}<"+str(data['Right'])+", {y}<" + str(data['Bottom']) + ",\ {y}>"+str(data['Bottom']-data['Height']) diff --git a/behaviors/SmootWind.py b/behaviors/SmootWind.py index 347e2fc..804183c 100755 --- a/behaviors/SmootWind.py +++ b/behaviors/SmootWind.py @@ -22,12 +22,22 @@ class SmootWind(Behavior): for sensory in sensorInputs: print sensory # input[0] is windspeed, [1] is dir - windSpeed = sensory[0] - windDir = sensory[1] + if 0 in sensory and 1 in sensory: + windSpeed = sensory[0] + windDir = sensory[1] + #print self.mapper.argDict + self.mapper.argDict['Width'] = self.mapper.argDict['Width']+float(windSpeed)*2+20 + self.xFor.argDict['ParamOp'] = self.xFor.argDict['ParamOp']+float(windSpeed)*3+10*random.random(); + #print 'Width: ' + str(self.mapper.argDict['Width']) + #print 'xFor: ' + str(self.xFor.argDict['ParamOp']) + + elif 'Key' in sensory: + if sensory['Key'] == 273: + self.mapper.argDict['Width'] = self.mapper.argDict['Width']+10; + self.xFor.argDict['ParamOp'] = self.xFor.argDict['ParamOp']+5; + + elif sensory['Key'] == 274: + self.mapper.argDict['Width'] = self.mapper.argDict['Width']-10; + self.xFor.argDict['ParamOp'] = self.xFor.argDict['ParamOp']-5; - #print self.mapper.argDict - self.mapper.argDict['Width'] = float(windSpeed)*2+20 - self.xFor.argDict['ParamOp'] = float(windSpeed)*3+10*random.random(); - #print 'Width: ' + str(self.mapper.argDict['Width']) - #print 'xFor: ' + str(self.xFor.argDict['ParamOp']) return (sensorInputs, recursiveInputs) diff --git a/config/6thFloorOSC.xml b/config/6thFloorOSC.xml index 792fd0c..2215688 100644 --- a/config/6thFloorOSC.xml +++ b/config/6thFloorOSC.xml @@ -37,6 +37,14 @@ + + inputs.OSCInput + + osc2 + 1234 + 10 + + inputs.OSCInput @@ -79,6 +87,12 @@ False + + + sixaxis + + behaviors.ControllerOSC + touchosc @@ -262,13 +276,27 @@ + + behaviors.BehaviorChain + + mousechaser2 + + osc2 + + + sixaxis + singleframe + + True + gaussmap + + behaviors.BehaviorChain mousechaser - tcp osc diff --git a/config/Jennifer.xml b/config/Jennifer.xml index e6cfc40..179c462 100644 --- a/config/Jennifer.xml +++ b/config/Jennifer.xml @@ -98,6 +98,7 @@ colorbars pygamekey + udp colorzones diff --git a/config/Kuan.xml b/config/Kuan.xml index c85cb75..7d76ed4 100644 --- a/config/Kuan.xml +++ b/config/Kuan.xml @@ -82,6 +82,15 @@ 2000 + behaviors.MITDoors diff --git a/config/SmootWindTest.xml b/config/SmootWindTest.xml index 6b74450..f6e7a97 100755 --- a/config/SmootWindTest.xml +++ b/config/SmootWindTest.xml @@ -53,6 +53,14 @@ 1 + + inputs.PygameInput + + pygamekey + 10 + True + + inputs.HTMLInput @@ -141,8 +149,8 @@ smootwind - weatherinput - + pygamekey + diff --git a/inputs/OSCInput.py b/inputs/OSCInput.py index f867fb5..ba1e035 100644 --- a/inputs/OSCInput.py +++ b/inputs/OSCInput.py @@ -7,8 +7,8 @@ class OSCInput(Input): def inputInit(self): HOST = '' # Symbolic name meaning all available interfaces PORT = self['Port'] # Arbitrary non-privileged port - self.server = liblo.Server(PORT) - self.server.add_method(None,None, self.fallback) + self.server = liblo.Server(PORT) + self.server.add_method(None,None, self.fallback) # except liblo.ServerError, err: # main_log.error(str(err)) diff --git a/inputs/PygameInput.py b/inputs/PygameInput.py index 18f463d..414adf3 100644 --- a/inputs/PygameInput.py +++ b/inputs/PygameInput.py @@ -23,7 +23,10 @@ class PygameInput(Input): if event.key == 27: self.die() if self['Keyboard']: - self.respond({'Key': event.key, 'KeyChar': chr(event.key)}) + try: + self.respond({'Key': event.key, 'KeyChar': chr(event.key)}) + except: + self.respond({'Key': event.key}) return else: pygame.event.post(event) diff --git a/pixelcore/Pixel.py b/pixelcore/Pixel.py index 6ff2e67..4e7cfce 100644 --- a/pixelcore/Pixel.py +++ b/pixelcore/Pixel.py @@ -1,4 +1,5 @@ import util.ColorOps as color +from logger import main_log import pdb from pixelevents.StepEvent import * import util.TimeOps as timeops @@ -57,7 +58,8 @@ class Pixel: if eventResult != None: scaledEvent = color.multiplyColor(eventResult,scale) if (scaledEvent[0] + scaledEvent[1] + scaledEvent[2]) < 5: - deadEvents.append(eventObj) + pass + #deadEvents.append(eventObj) else: colors.append(scaledEvent) else: diff --git a/renderers/IndoorRenderer.py b/renderers/IndoorRenderer.py index 531a732..710ca43 100644 --- a/renderers/IndoorRenderer.py +++ b/renderers/IndoorRenderer.py @@ -21,7 +21,7 @@ class IndoorRenderer(Renderer): for stripId in stripsInPowerSupply: self.stripLocations[stripId] = (ip, \ stripsInPowerSupply[stripId]) - + self.broadSocket = network.getBroadcastSocket(6038) def render(self, lightSystem, currentTime=timeops.time()): #try: for pixelStrip in lightSystem.pixelStrips: @@ -32,4 +32,9 @@ class IndoorRenderer(Renderer): self.sockets[ip] = network.getConnectedSocket(ip,sock_port) packet = composer.composePixelStripPacket(pixelStrip, port, currentTime) self.sockets[ip].send(packet, 0x00) + + synchPacket = composer.composeSynchPacket() + #pdb.set_trace() + #self.broadSocket.sendto(synchPacket, ('10.0.32.255', 6038)) + diff --git a/util/NetworkOps.py b/util/NetworkOps.py index 8894b78..3ece763 100644 --- a/util/NetworkOps.py +++ b/util/NetworkOps.py @@ -8,3 +8,9 @@ def getConnectedSocket(ip,port): except Exception as inst: main_log.error('Network down. All network based renderers and sensors will not function.', inst) + +def getBroadcastSocket(port): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + return s diff --git a/util/PacketComposition.py b/util/PacketComposition.py index 7b4fe95..75ef917 100644 --- a/util/PacketComposition.py +++ b/util/PacketComposition.py @@ -5,7 +5,7 @@ PORTOUT = 0x0108 UNI = 0 import pdb import util.TimeOps as timeops -argDict = {'flags': 0, 'startcode': 0, 'pad':0} +argDict = {'flags': 0, 'startcode': 0x0fff, 'pad':0} def composePixelStripData(pixelStrip,currentTime=timeops.time()): packet = bytearray() @@ -33,10 +33,10 @@ def memoize(f): def cachePacketHeader(port): packet = bytearray() subDict = dict(argDict) - subDict['len'] = 38500 #I have no idea why this works. + subDict['len'] = 150 #I have no idea why this works. subDict['port'] = port packet.extend(portOutPacket(subDict)) - packet.append(0x0) +# packet.append(0x0) return packet def composePixelStripPacket(pixelStrip,port, currentTime): @@ -61,10 +61,19 @@ def portOut(): def portOutPayload(argDict): payload = bytearray() payload.extend(struct.pack('B', argDict['port'])) + payload.extend(struct.pack('B',0)) payload.extend(struct.pack('H', argDict['flags'])) payload.extend(struct.pack('H', argDict['len'])) payload.extend(struct.pack('H', argDict['startcode'])) return payload +def composeSynchPacket(): + header = bytearray() + header.extend(struct.pack('L', MAGIC)) + header.extend(struct.pack('H', VERSION)) + header.extend(struct.pack('H', 0x0109)) + header.extend(struct.pack('L', 0)) + header.extend(struct.pack('L', 0)) + return header def portOutPacket(payloadArgs): packet = bytearray() -- cgit v1.2.3 From 3cf7f82b2c88181925e01c2736e13d8be7574ab9 Mon Sep 17 00:00:00 2001 From: eugue Date: Fri, 28 Jan 2011 15:19:40 -0500 Subject: get string data instead of int --- behaviors/MobileShakeBehavior.py | 29 +++++++++++++++++++---------- behaviors/MoveBehavior.py | 18 ++++++++++-------- config/MobileTest.xml | 28 ++++++++++++---------------- inputs/TCPInput.py | 2 ++ 4 files changed, 43 insertions(+), 34 deletions(-) diff --git a/behaviors/MobileShakeBehavior.py b/behaviors/MobileShakeBehavior.py index e25e929..b05cb5f 100644 --- a/behaviors/MobileShakeBehavior.py +++ b/behaviors/MobileShakeBehavior.py @@ -1,17 +1,26 @@ from operationscore.Behavior import * +import util.ComponentRegistry as compReg import util.Strings as Strings class MobileShakeBehavior(Behavior): + def behaviorInit(self): + self.mapper = None + def processResponse(self, sensorInputs, recursiveInputs): + if self.mapper == None: + try: + self.mapper = compReg.getComponent('mobilegaussmap') + except KeyError: + pass + #print sensorInputs - ret = [] for sInput in sensorInputs: - outDict = dict(sInput) - if 'type' in sInput and sInput['type'] == 2: - outDict['Location'] = '{x}>' + str(0) + ',{y}>' + str(0) - outDict['Color'] = [sInput['r'], sInput['g'], sInput['b']] - else: # dumb invisible pixel - outDict['Location'] = (-1, -1) - outDict['Color'] = [0, 0, 0] - ret.append(outDict) - return (ret, recursiveInputs) + if 'Shake' in sInput and sInput['Shake'] == 1: + #print 'increase!' + self.mapper.argDict['Width'] += 30 + #self.mapper.argDict['CutoffDist'] += 20 + sInput['Shake'] = 0 + print 'Width:' + str(compReg.getComponent('mobilegaussmap').argDict['Width']) + #print 'CutoffDist: '+ str(compReg.getComponent('mobilegaussmap').argDict['CutoffDist']) + + return (sensorInputs, recursiveInputs) diff --git a/behaviors/MoveBehavior.py b/behaviors/MoveBehavior.py index e504ca9..6f57437 100644 --- a/behaviors/MoveBehavior.py +++ b/behaviors/MoveBehavior.py @@ -13,20 +13,22 @@ class MoveBehavior(Behavior): else: currRecLocs = [{'Location' : (5, 5), 'Color' : [255, 255, 255]}] + #print sensorInputs if sensorInputs: # if input exists, change location ret = [] for currRecLoc in currRecLocs: currDict = dict(currRecLoc) for sensorInput in sensorInputs: - if 'type' in sensorInput and sensorInput['type'] == 1: - currDict['Location'] = (currDict['Location'][0] - sensorInput['x'] * self['XStep'], \ - currDict['Location'][1] + sensorInput['y'] * self['YStep']) - currDict['Color'] = [sensorInput['r'], sensorInput['g'], sensorInput['b']] - #elif sensorInput['type'] == 2: - # currDict['Shake'] = 1 - # currDict['Force'] = sensorInput['force'] + if 'type' in sensorInput and int(sensorInput['type']) == 1: + #currDict['Shake'] = 0 + currDict['Location'] = (currDict['Location'][0] - int(sensorInput['x']) * self['XStep'], \ + currDict['Location'][1] + int(sensorInput['y']) * self['YStep']) + currDict['Color'] = [int(sensorInput['r']), int(sensorInput['g']), int(sensorInput['b'])] + elif int(sensorInput['type']) == 2: + #print sensorInput + currDict['Shake'] = 1 + #currDict['Force'] = sensorInput['force'] ret.append(currDict) - #print ret return (ret, ret) else: # if not, return current recursive location. diff --git a/config/MobileTest.xml b/config/MobileTest.xml index af94c25..63c3b47 100644 --- a/config/MobileTest.xml +++ b/config/MobileTest.xml @@ -26,6 +26,16 @@ 1 + + pixelmappers.GaussianMapper + + mobilegaussmap + 30 + 0.1 + 10 + 1 + + @@ -227,26 +237,12 @@ move + mobileshake decay True - gaussmap + mobilegaussmap - - behaviors.BehaviorChain - - shakeanddecay - - tcp - - - mobileshake - slowdecay - - True - simplemap - - diff --git a/inputs/TCPInput.py b/inputs/TCPInput.py index 17ea7e6..2d8ab4d 100644 --- a/inputs/TCPInput.py +++ b/inputs/TCPInput.py @@ -38,6 +38,8 @@ class TCPInput(Input): for datagroup in data.split('\n'): if datagroup != None and datagroup != '': dataDict = json.loads(datagroup) + #if dataDict['type'] != 1: + #print dataDict self.respond(dataDict) except Exception as exp: print str(exp) -- cgit v1.2.3 From fac2f8373cd0e63a34a39cb77c0c7276d1d88b65 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 28 Jan 2011 15:25:21 -0500 Subject: Fixed Problems with controller --- behaviors/ControllerOSC.py | 61 ++++++++++++++++++++++++++++------------------ oscserver.py | 36 --------------------------- testosc.py | 36 --------------------------- 3 files changed, 37 insertions(+), 96 deletions(-) delete mode 100755 oscserver.py delete mode 100755 testosc.py diff --git a/behaviors/ControllerOSC.py b/behaviors/ControllerOSC.py index 6e3e814..0dd1b12 100644 --- a/behaviors/ControllerOSC.py +++ b/behaviors/ControllerOSC.py @@ -2,61 +2,74 @@ from operationscore.Behavior import * from logger import main_log #import util.ColorOps as color import colorsys -from numpy import arrray +from numpy import array import pdb import util.ComponentRegistry as compReg -def constrain(v,c): - if v[0] > c[1]: - v[0] = c[1] - elif v[0]<0 +speedfactor = 15 +vel_decay = .01 + +def constrainLocation(v,c): + if v[0] > c[0]: + v[0] = c[0] + elif v[0]<0: v[0] = 0 - if v[1] > c[0]: - v[1] = c[0] - elif v[1]<0 + if v[1] > c[1]: + v[1] = c[1] + elif v[1]<0: v[1] = 0 return v -class TouchOSC(Behavior): +class ControllerOSC(Behavior): def behaviorInit(self): self.xy = array((0,0)) self.v_xy = array((0,0)) - self.v_decay = .1 + self.v_decay = vel_decay - self.start_hsv = (0,1,1) - self.dest_hsv = (0,1,1) + self.start_hsv = [0,1,1] + self.dest_hsv = [0,1,1] + self.ssize = compReg.getComponent('Screen').getSize()[-2:] #896 x 310 def processResponse(self, sensorInputs, recursiveInputs): ret = [] if sensorInputs: data = sensorInputs[-1]#for data in sensorInputs: if data['Path'] == '/sixaxis/xy': - try: + #try: x = data['Value'][0] y = data['Value'][1] if y < 0: - self.start_hsv[1] = 1+y #s + self.start_hsv[1] = 1.0+y #s else: - self.start_hsv[2] = y - self.h += x + self.start_hsv[2] = 1.0-y + self.start_hsv[0] = (x+1) * 180.0 +# if self.start_hsv[0] >= 360: +# self.start_hsv[0] = 0 +# if self.start_hsv[0] <=0: +# self.start_hsv[0] = 360 #self.h = x * 360. - except: - pdb.set_trace() + #except(e): + # pdb.set_trace() elif data['Path'] == '/sixaxis/lrud': val=data['Value'] - ssize = compReg.getComponent('Screen').getSize()[-2:] #896 x 310 - vx = -val[3] if val[3] else val[2] - vy = -val[0] if val[0] else val[1] + vy = val[3] if val[3] else -val[2] + vx = -val[0] if val[0] else val[1] + #pdb.set_trace() #self.v_xy = (val[1]*ssize[0], (1.0-val[0])*ssize[1]) - self.v_xy = array((vx, vy)) + self.v_xy = array((vx, vy)) * speedfactor else: main_log.error('Sensor Inputs: ' + str(sensorInputs)) self.xy = self.xy + self.v_xy - constrain(self.xy,ssize) + constrainLocation(self.xy,self.ssize) self.v_xy -= self.v_decay - ret.append({'Color':[i*256 for i in colorsys.hsv_to_rgb(*self.start_hsv)],'Location':tuple(self.xy)}) + if self.v_xy[0] < 0: + self.v_xy[0] = 0 + if self.v_xy[1] < 0: + self.v_xy[1] = 0 + ret.append({'Color':[i*256 for i in + colorsys.hsv_to_rgb(*self.start_hsv)],'Location':(int(self.xy[0]), int(self.xy[1]))}) return (ret, []) diff --git a/oscserver.py b/oscserver.py deleted file mode 100755 index 6763f41..0000000 --- a/oscserver.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python - -import liblo, sys - -# create server, listening on port 1234 -try: - server = liblo.Server(1234) -except liblo.ServerError, err: - print str(err) - sys.exit() - -def foo_bar_callback(path, args): - i, f = args - print "received message '%s' with arguments '%d' and '%f'" % (path, i, f) - -def foo_baz_callback(path, args, types, src, data): - print "received message '%s'" % path - print "blob contains %d bytes, user data was '%s'" % (len(args[0]), data) - -def fallback(path, args, types, src): - print "got unknown message '%s' from '%s'" % (path, src.get_url()) - for a, t in zip(args, types): - print "argument of type '%s': %s" % (t, a) - -# register method taking an int and a float -server.add_method("/foo/bar", 'if', foo_bar_callback) - -# register method taking a blob, and passing user data to the callback -server.add_method("/foo/baz", 'b', foo_baz_callback, "blah") - -# register a fallback for unhandled messages -server.add_method(None, None, fallback) - -# loop and dispatch messages every 100ms -while True: - server.recv(100) diff --git a/testosc.py b/testosc.py deleted file mode 100755 index cea03f4..0000000 --- a/testosc.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python - -import liblo, sys - -# create server, listening on port 1234 -try: - server = liblo.Server(12345) -except liblo.ServerError, err: - print str(err) - sys.exit() - -def foo_bar_callback(path, args): - i, f = args - print "received message '%s' with arguments '%d' and '%f'" % (path, i, f) - -def foo_baz_callback(path, args, types, src, data): - print "received message '%s'" % path - print "blob contains %d bytes, user data was '%s'" % (len(args[0]), data) - -def fallback(path, args, types, src): - print "got unknown message '%s' from '%s'" % (path, src.get_url()) - for a, t in zip(args, types): - print "argument of type '%s': %s" % (t, a) - -# register method taking an int and a float -server.add_method("/foo/bar", 'if', foo_bar_callback) - -# register method taking a blob, and passing user data to the callback -server.add_method("/foo/baz", 'b', foo_baz_callback, "blah") - -# register a fallback for unhandled messages -server.add_method(None, None, fallback) - -# loop and dispatch messages every 100ms -while True: - server.recv(100) -- cgit v1.2.3 From 51b0d5f0cd4524a977e0bf48ca6f643d85d05d00 Mon Sep 17 00:00:00 2001 From: eugue Date: Fri, 28 Jan 2011 16:10:58 -0500 Subject: reverted the effort to take string inputs. --- behaviors/MoveBehavior.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/behaviors/MoveBehavior.py b/behaviors/MoveBehavior.py index 6f57437..6e7fc6a 100644 --- a/behaviors/MoveBehavior.py +++ b/behaviors/MoveBehavior.py @@ -13,22 +13,21 @@ class MoveBehavior(Behavior): else: currRecLocs = [{'Location' : (5, 5), 'Color' : [255, 255, 255]}] - #print sensorInputs if sensorInputs: # if input exists, change location ret = [] for currRecLoc in currRecLocs: currDict = dict(currRecLoc) for sensorInput in sensorInputs: - if 'type' in sensorInput and int(sensorInput['type']) == 1: - #currDict['Shake'] = 0 - currDict['Location'] = (currDict['Location'][0] - int(sensorInput['x']) * self['XStep'], \ - currDict['Location'][1] + int(sensorInput['y']) * self['YStep']) - currDict['Color'] = [int(sensorInput['r']), int(sensorInput['g']), int(sensorInput['b'])] - elif int(sensorInput['type']) == 2: - #print sensorInput + if 'type' in sensorInput and sensorInput['type'] == 1: + currDict['Shake'] = 0 + currDict['Location'] = (currDict['Location'][0] - sensorInput['x'] * self['XStep'], \ + currDict['Location'][1] + sensorInput['y'] * self['YStep']) + currDict['Color'] = [sensorInput['r'], sensorInput['g'], sensorInput['b']] + elif sensorInput['type'] == 2: currDict['Shake'] = 1 #currDict['Force'] = sensorInput['force'] ret.append(currDict) + #print ret return (ret, ret) else: # if not, return current recursive location. -- cgit v1.2.3 From f95eff2616f8e7c952a31756f079aef87f28a1d4 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 28 Jan 2011 16:15:26 -0500 Subject: readded testosc in tests directory --- tests/testosc.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100755 tests/testosc.py diff --git a/tests/testosc.py b/tests/testosc.py new file mode 100755 index 0000000..6763f41 --- /dev/null +++ b/tests/testosc.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +import liblo, sys + +# create server, listening on port 1234 +try: + server = liblo.Server(1234) +except liblo.ServerError, err: + print str(err) + sys.exit() + +def foo_bar_callback(path, args): + i, f = args + print "received message '%s' with arguments '%d' and '%f'" % (path, i, f) + +def foo_baz_callback(path, args, types, src, data): + print "received message '%s'" % path + print "blob contains %d bytes, user data was '%s'" % (len(args[0]), data) + +def fallback(path, args, types, src): + print "got unknown message '%s' from '%s'" % (path, src.get_url()) + for a, t in zip(args, types): + print "argument of type '%s': %s" % (t, a) + +# register method taking an int and a float +server.add_method("/foo/bar", 'if', foo_bar_callback) + +# register method taking a blob, and passing user data to the callback +server.add_method("/foo/baz", 'b', foo_baz_callback, "blah") + +# register a fallback for unhandled messages +server.add_method(None, None, fallback) + +# loop and dispatch messages every 100ms +while True: + server.recv(100) -- cgit v1.2.3 From bd1119e82ff9f4bd8835ed6d3934f156a6da8b23 Mon Sep 17 00:00:00 2001 From: rcoh Date: Fri, 28 Jan 2011 16:24:21 -0500 Subject: Fixed TCPInput bug. --- config/6thFloorOSC.xml | 67 +++++++++++++++++++++++++++++++++++++++++--------- inputs/TCPInput.py | 14 ++++++++++- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/config/6thFloorOSC.xml b/config/6thFloorOSC.xml index 2215688..aa7a07d 100644 --- a/config/6thFloorOSC.xml +++ b/config/6thFloorOSC.xml @@ -60,14 +60,14 @@ 10 - + inputs/MouseFollower.xml @@ -79,15 +79,60 @@ - - behaviors.EchoBehavior - - echo - 0 - False - - - + + behaviors.EchoBehavior + + echo + 0 + False + + + + behaviors.BehaviorChain + + moveanddecay + + tcp + + + move + decay + + True + gaussmap + + + + behaviors.MoveBehavior + + move + 3 + 3 + + + + behaviors.MobileShakeBehavior + + mobileshake + 3 + + + + behaviors.BehaviorChain + + shakeanddecay + + tcp + + + mobileshake + slowdecay + + True + simplemap + + + sixaxis diff --git a/inputs/TCPInput.py b/inputs/TCPInput.py index 17ea7e6..51a6677 100644 --- a/inputs/TCPInput.py +++ b/inputs/TCPInput.py @@ -4,6 +4,7 @@ from operationscore.Input import * import socket, json, time import logging as main_log import string +from select import select class TCPInput(Input): """TCPInput is a input to receive input on a TCP port. In its current incarnation, it parses @@ -20,9 +21,20 @@ class TCPInput(Input): self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind((self.HOST, self.PORT)) self.sock.listen(1) - (self.conn, self.address) = self.sock.accept() + + isreadable=select([self.sock],[],[], 0)[0] + self.conn = None + if isreadable: + (self.conn, self.address) = self.sock.accept() def sensingLoop(self): + if self.conn == None: + isreadable=select([self.sock],[],[], 0)[0] + if isreadable: + (self.conn, self.address) = self.sock.accept() + else: + return + data = self.conn.recv(self.BUFFER_SIZE) main_log.debug('Incoming data', data) -- cgit v1.2.3 From b67a37ad06fa4c97dcdb32cecc71c7f492b12840 Mon Sep 17 00:00:00 2001 From: rcoh Date: Fri, 28 Jan 2011 16:29:36 -0500 Subject: Picking up some files that were lost. --- behaviors/ControllerOSC.py | 67 +++++++++++++++++++++++++++++++++++++++++++ behaviors/Sink.py | 42 +++++++++++++++++++++++++++ behaviors/SynchTest.py | 12 ++++++++ config/SynchTest.xml | 39 +++++++++++++++++++++++++ pixelevents/SynchTestEvent.py | 15 ++++++++++ 5 files changed, 175 insertions(+) create mode 100644 behaviors/ControllerOSC.py create mode 100644 behaviors/Sink.py create mode 100644 behaviors/SynchTest.py create mode 100644 config/SynchTest.xml create mode 100644 pixelevents/SynchTestEvent.py diff --git a/behaviors/ControllerOSC.py b/behaviors/ControllerOSC.py new file mode 100644 index 0000000..ce2cf26 --- /dev/null +++ b/behaviors/ControllerOSC.py @@ -0,0 +1,67 @@ +from operationscore.Behavior import * +from logger import main_log +#import util.ColorOps as color +import colorsys +from numpy import array +import pdb +import util.ComponentRegistry as compReg + +speedfactor = 15 +vel_decay = .00 + +def constrainLocation(v,c): + if v[0] > c[0]: + v[0] = c[0] + elif v[0]<0: + v[0] = 0 + + if v[1] > c[1]: + v[1] = c[1] + elif v[1]<0: + v[1] = 0 + + return v + +class ControllerOSC(Behavior): + def behaviorInit(self): + self.xy = array((0,0)) + self.v_xy = array((0,0)) + self.v_decay = vel_decay + + self.start_hsv = [0,1,1] + self.dest_hsv = [0,1,1] + self.ssize = compReg.getComponent('Screen').getSize()[-2:] #896 x 310 + + def processResponse(self, sensorInputs, recursiveInputs): + ret = [] + if sensorInputs: + data = sensorInputs[-1]#for data in sensorInputs: + if data['Path'] == '/sixaxis/xy': + #try: + x = data['Value'][0] + y = data['Value'][1] + main_log.error(str(x)) + if y < 0: + self.start_hsv[1] = 1.0+y #s + else: + self.start_hsv[2] = 1.0-y + self.start_hsv[0] = (x+1) * 180.0 + elif data['Path'] == '/sixaxis/lrud': + val=data['Value'] + vy = val[3]-val[2] + vx = val[1]-val[0] + #pdb.set_trace() + #self.v_xy = (val[1]*ssize[0], (1.0-val[0])*ssize[1]) + self.v_xy = array((vx, vy)) * speedfactor + else: + main_log.error('Sensor Inputs: ' + str(sensorInputs)) + self.xy = self.xy + self.v_xy + constrainLocation(self.xy,self.ssize) + self.v_xy -= self.v_decay + if self.v_xy[0] < 0: + self.v_xy[0] = 0 + if self.v_xy[1] < 0: + self.v_xy[1] = 0 + ret.append({'Color':[i*255 for i in colorsys.hsv_to_rgb(*self.start_hsv)],'Location':(int(self.xy[0]), int(self.xy[1]))}) + + return (ret, []) diff --git a/behaviors/Sink.py b/behaviors/Sink.py new file mode 100644 index 0000000..52d0be2 --- /dev/null +++ b/behaviors/Sink.py @@ -0,0 +1,42 @@ + +from operationscore.Behavior import * +import math +import util.TimeOps as timeOps +#Required Args: +#Period (ms), MaxHeight, Width +class Sink(Behavior): + """RiseFall is a behavior that creates a rising and falling column of light. Specify: + -- the maximum height that it rises to. + -- the width of the column OR and + -- the period of oscillation in ms + + Designed to be used as part of a recursive hook. + """ + + def processResponse(self, sensorInputs, recurInputs): + ret = [] + for data in sensorInputs: + #first time with behavior: + data = dict(data) + if not 'StartTime' in data: + data['StartTime'] = timeOps.time() + data['Period'] = self['Period'] + data['MaxHeight'] = self['MaxHeight'] #Consider just using += + if not 'Bottom' in data: + data['Bottom'] = data['Location'][1] + if 'Width' in self: #TODO: improve + data['Width'] = self['Width'] + data['Left'] = data['Location'][0]-data['Width']/2. + data['Right'] = data['Location'][0]+data['Width']/2. + currentTime = timeOps.time() + deltaTime = currentTime-data['StartTime'] + data['Height'] = data['MaxHeight']*math.cos(deltaTime/data['Period']*(math.pi*2)) + + data['Location'] = "{x}>"+str(data['Left']) + ", " +\ + "{x}<"+str(data['Right'])+", {y}<" + str(data['Bottom']) + ",\ + {y}>"+str(data['Bottom']-data['Height']) + + ret.append(data) + return (ret, []) + + diff --git a/behaviors/SynchTest.py b/behaviors/SynchTest.py new file mode 100644 index 0000000..e7b8acc --- /dev/null +++ b/behaviors/SynchTest.py @@ -0,0 +1,12 @@ +from operationscore.Behavior import * +from pixelevents.SynchTestEvent import * +import pdb +class SynchTest(Behavior): + def behaviorInit(self): + self.rendered = False + def processResponse(self, sensorInputs, recurs): + if not self.rendered: + self.rendered = True + print 'here1' + return ([{'Location':'True', 'PixelEvent':SynchTestEvent({'Color':(255,0,0)})}], []) + return ([], []) diff --git a/config/SynchTest.xml b/config/SynchTest.xml new file mode 100644 index 0000000..fcb8293 --- /dev/null +++ b/config/SynchTest.xml @@ -0,0 +1,39 @@ + + + + + simplemap + + + + layouts/60StripLayout.xml + + + + pixelmappers.SimpleMapper + + simplemap + 20 + + + + + + renderers/60StripSeq.xml + + + renderers/Pygame.xml + + + + + + + behaviors.SynchTest + + synch + True + + + + diff --git a/pixelevents/SynchTestEvent.py b/pixelevents/SynchTestEvent.py new file mode 100644 index 0000000..3e7ed0c --- /dev/null +++ b/pixelevents/SynchTestEvent.py @@ -0,0 +1,15 @@ +from operationscore.PixelEvent import * +class SynchTestEvent(PixelEvent): + """SynchTestEvent is an event to test the synchronization of the power supplies""" + def initEvent(self): + self.eventstate = 0 + self.cachedDelay = 0 + def state(self, timeDelay): + if timeDelay != self.cachedDelay: + self.eventstate += 1 + self.cachedDelay = timeDelay + color = [0]*3 + color[self.eventstate % 3] = 150 + if self.eventstate > 500: + self.eventstate = 0 + return color -- cgit v1.2.3 From d43f5ef8a771fbfd3a3f38f0eb018d3f84589bf7 Mon Sep 17 00:00:00 2001 From: rcoh Date: Fri, 28 Jan 2011 17:09:46 -0500 Subject: Finishing touches to OSC stuff. --- behaviors/AddPixelEvent.py | 2 -- behaviors/ControllerOSC.py | 13 ++++--------- behaviors/TouchOSC.py | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/behaviors/AddPixelEvent.py b/behaviors/AddPixelEvent.py index 821f432..da3f7c2 100644 --- a/behaviors/AddPixelEvent.py +++ b/behaviors/AddPixelEvent.py @@ -21,8 +21,6 @@ class AddPixelEvent(Behavior): ret = [] for sensory in sensors: outDict = {} - if not 'Location' in sensory: - pdb.set_trace() outDict[Strings.LOCATION] = sensory[Strings.LOCATION] settingsDict = dict(self.argDict) settingsDict['Color'] = sensory['Color'] diff --git a/behaviors/ControllerOSC.py b/behaviors/ControllerOSC.py index ce2cf26..05d2e7d 100644 --- a/behaviors/ControllerOSC.py +++ b/behaviors/ControllerOSC.py @@ -7,7 +7,7 @@ import pdb import util.ComponentRegistry as compReg speedfactor = 15 -vel_decay = .00 +vel_decay = .9 def constrainLocation(v,c): if v[0] > c[0]: @@ -40,12 +40,11 @@ class ControllerOSC(Behavior): #try: x = data['Value'][0] y = data['Value'][1] - main_log.error(str(x)) if y < 0: self.start_hsv[1] = 1.0+y #s else: self.start_hsv[2] = 1.0-y - self.start_hsv[0] = (x+1) * 180.0 + self.start_hsv[0] = (x+1)/2. elif data['Path'] == '/sixaxis/lrud': val=data['Value'] vy = val[3]-val[2] @@ -57,11 +56,7 @@ class ControllerOSC(Behavior): main_log.error('Sensor Inputs: ' + str(sensorInputs)) self.xy = self.xy + self.v_xy constrainLocation(self.xy,self.ssize) - self.v_xy -= self.v_decay - if self.v_xy[0] < 0: - self.v_xy[0] = 0 - if self.v_xy[1] < 0: - self.v_xy[1] = 0 - ret.append({'Color':[i*255 for i in colorsys.hsv_to_rgb(*self.start_hsv)],'Location':(int(self.xy[0]), int(self.xy[1]))}) + self.v_xy *= self.v_decay + ret.append({'Color':[i*255. for i in colorsys.hsv_to_rgb(*self.start_hsv)],'Location':(int(self.xy[0]), int(self.xy[1]))}) return (ret, []) diff --git a/behaviors/TouchOSC.py b/behaviors/TouchOSC.py index 1c41b5e..e7893e3 100644 --- a/behaviors/TouchOSC.py +++ b/behaviors/TouchOSC.py @@ -15,7 +15,7 @@ class TouchOSC(Behavior): for data in sensorInputs: if data['Path'] == '/1/fader1': try: - self.h = data['Value'][0]*360.0 + self.h = data['Value'][0] except: pdb.set_trace() elif data['Path'] == '/1/fader2': -- cgit v1.2.3 From 61d3da8be78c093384b7f87c854c09c255f6384e Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 28 Jan 2011 17:26:53 -0500 Subject: Finished merge of fridaydemo, restored fixed ControllerOSC.py --- behaviors/ControllerOSC.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 behaviors/ControllerOSC.py diff --git a/behaviors/ControllerOSC.py b/behaviors/ControllerOSC.py new file mode 100644 index 0000000..05d2e7d --- /dev/null +++ b/behaviors/ControllerOSC.py @@ -0,0 +1,62 @@ +from operationscore.Behavior import * +from logger import main_log +#import util.ColorOps as color +import colorsys +from numpy import array +import pdb +import util.ComponentRegistry as compReg + +speedfactor = 15 +vel_decay = .9 + +def constrainLocation(v,c): + if v[0] > c[0]: + v[0] = c[0] + elif v[0]<0: + v[0] = 0 + + if v[1] > c[1]: + v[1] = c[1] + elif v[1]<0: + v[1] = 0 + + return v + +class ControllerOSC(Behavior): + def behaviorInit(self): + self.xy = array((0,0)) + self.v_xy = array((0,0)) + self.v_decay = vel_decay + + self.start_hsv = [0,1,1] + self.dest_hsv = [0,1,1] + self.ssize = compReg.getComponent('Screen').getSize()[-2:] #896 x 310 + + def processResponse(self, sensorInputs, recursiveInputs): + ret = [] + if sensorInputs: + data = sensorInputs[-1]#for data in sensorInputs: + if data['Path'] == '/sixaxis/xy': + #try: + x = data['Value'][0] + y = data['Value'][1] + if y < 0: + self.start_hsv[1] = 1.0+y #s + else: + self.start_hsv[2] = 1.0-y + self.start_hsv[0] = (x+1)/2. + elif data['Path'] == '/sixaxis/lrud': + val=data['Value'] + vy = val[3]-val[2] + vx = val[1]-val[0] + #pdb.set_trace() + #self.v_xy = (val[1]*ssize[0], (1.0-val[0])*ssize[1]) + self.v_xy = array((vx, vy)) * speedfactor + else: + main_log.error('Sensor Inputs: ' + str(sensorInputs)) + self.xy = self.xy + self.v_xy + constrainLocation(self.xy,self.ssize) + self.v_xy *= self.v_decay + ret.append({'Color':[i*255. for i in colorsys.hsv_to_rgb(*self.start_hsv)],'Location':(int(self.xy[0]), int(self.xy[1]))}) + + return (ret, []) -- cgit v1.2.3 From da934a838305bab72bd12dcd2b83e689f7c1cc3f Mon Sep 17 00:00:00 2001 From: Jim Salem Date: Fri, 28 Jan 2011 18:28:25 -0500 Subject: New Flasher behavior which fades colors in and out. Several new color functions. Created a "firefly" demo (moving colored bubbles that fade in and out) --- behaviors/EchoBehavior.py | 5 +- behaviors/Flasher.py | 41 +++++ behaviors/RandomSetBrightColorBehavior.py | 14 ++ config/FireflyDemo.xml | 261 ++++++++++++++++++++++++++++++ util/ColorOps.py | 15 ++ 5 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 behaviors/Flasher.py create mode 100644 behaviors/RandomSetBrightColorBehavior.py create mode 100644 config/FireflyDemo.xml diff --git a/behaviors/EchoBehavior.py b/behaviors/EchoBehavior.py index 6ef4fcb..c4af7c0 100644 --- a/behaviors/EchoBehavior.py +++ b/behaviors/EchoBehavior.py @@ -9,6 +9,9 @@ class EchoBehavior(Behavior): for sensory in sensorInputs: outDict = {} outDict[Strings.LOCATION] = sensory[Strings.LOCATION] - outDict['Color'] = (255,0,0) + if self['Color'] != None: + outDict['Color'] = self['Color'] + else: + outDict['Color'] = (255,0,0) ret.append(outDict) return (ret, []) diff --git a/behaviors/Flasher.py b/behaviors/Flasher.py new file mode 100644 index 0000000..4a2dad4 --- /dev/null +++ b/behaviors/Flasher.py @@ -0,0 +1,41 @@ +# Implements a pulsing/flashing behavior. +# Jim Salem: jsalem@gmail.com +# +# Args: +# Factor - The speed of flashing. Must be b/w 0 and 1. Default is .95 +# + +from operationscore.Behavior import * +import util.ColorOps as colorops +import pdb +class Flasher(Behavior): + def processResponse(self, sensorInputs, recursiveInputs): + ret = [] + for response in sensorInputs: + # Get the multiplier + if self['Factor'] != None: + factor = self['Factor'] + else: + factor = 0.95 + # Initialize the first time + if not 'FireflyStartColor' in response: + response['FireflyValue'] = 1.0 + response['FireflyDir'] = 1 + response['FireflyStartColor'] = response['Color']; + else: + # Update the current value + if response['FireflyDir'] == 1: + response['FireflyValue'] = response['FireflyValue'] * factor + if response['FireflyValue'] <= 0.01: + response['FireflyValue'] = 0.01 + response['FireflyDir'] = 0 + else: + response['FireflyValue'] = response['FireflyValue'] / factor + if response['FireflyValue'] >= 1.0: + response['FireflyValue'] = 1.0 + response['FireflyDir'] = 1 + + # Compute the color + response['Color'] = colorops.multiplyColor(response['FireflyStartColor'], response['FireflyValue']) + ret.append(response) + return (ret, []) #no direct ouput diff --git a/behaviors/RandomSetBrightColorBehavior.py b/behaviors/RandomSetBrightColorBehavior.py new file mode 100644 index 0000000..f278858 --- /dev/null +++ b/behaviors/RandomSetBrightColorBehavior.py @@ -0,0 +1,14 @@ +from operationscore.Behavior import * +import util.ColorOps as color +import pdb +import colorsys +import random +class RandomSetBrightColorBehavior(Behavior): + """Sets a random color that is bright.""" + def processResponse(self, sensorInputs, recursiveInputs): + ret = [] + for sensory in sensorInputs: + newDict = dict(sensory) + newDict['Color'] = color.randomBrightColor() + ret.append(newDict) + return (ret, []) diff --git a/config/FireflyDemo.xml b/config/FireflyDemo.xml new file mode 100644 index 0000000..8008168 --- /dev/null +++ b/config/FireflyDemo.xml @@ -0,0 +1,261 @@ + + + + + + + + + + simplemap + + + + layouts/60StripLayout.xml + + + + pixelmappers.SimpleMapper + + simplemap + 20 + + + + pixelmappers.GaussianMapper + + gaussmap + 30 + 0.1 + 10 + 1 + + + + + + + renderers/Pygame.xml + + + + + inputs.PygameInput + + pygameclick + 10 + True + + + + inputs.PygameInput + + pygamekey + 10 + True + + + + inputs.UDPInput + + udp + 3344 + 50 + + + + + inputs/MouseFollower.xml + + + + + + behaviors.RandomSetBrightColorBehavior + + setbrightcolor + + + + + behaviors/RandomColor.xml + + + (255,0,0) + (0,0,255) + + + + + behaviors/PixelDecay.xml + + .5 + + + + behaviors/PixelDecay.xml + + + behaviors/SingleFrame.xml + + + behaviors/PixelDecay.xml + + .01 + + + + behaviors.XYMove + + xymove + 5 + 2 + + + + behaviors.RestrictLocation + + xbounce + {val}*-1 + XStep + {x}<0 or {x}>800 + + + + behaviors.RestrictLocation + + ybounce + {val}*-1 + YStep + {y}<0 or {y}>200 + + + + behaviors.BehaviorChain + + movebounce + + xymove + ybounce + xbounce + + + + + behaviors.Flasher + + flasher + + + + + behaviors.BehaviorChain + + flashermovebounce + + randmovement + ybounce + xbounce + + flasher + + + + + behaviors.Square + + square + 15 + + + + behaviors/LoopAndDie.xml + + 80 + + + + behaviors.RandomWalk + + randmovement + 20 + + + + + behaviors.ModifyParam + + fadecolor + Sensor + Color + [chan*.98 for chan in {val}] + + + + + behaviors.BehaviorChain + + runcolordecay + + pygameclick + + + setbrightcolor + mover + decay + + {'mover':'flashermovebounce'} + True + gaussmap + + + + behaviors.ResponseMover + + mover + + + + behaviors/Accelerate.xml + + + behaviors.EchoBehavior + + echo + 0 + (90,90,90) + False + + + + behaviors.BehaviorChain + + mousechaser + + followmouse + + + echo + square + singleframe + + True + + + + + behaviors/RunningBehavior.xml + + + diff --git a/util/ColorOps.py b/util/ColorOps.py index 037957a..d971ad0 100644 --- a/util/ColorOps.py +++ b/util/ColorOps.py @@ -1,4 +1,5 @@ import random +import colorsys from util.TimeOps import Stopwatch def randomColor(): return [random.randint(0,255) for i in range(3)] @@ -23,3 +24,17 @@ def combineColors(colors): def multiplyColor(color, percent): return safeColor([channel*(percent) for channel in color]) + +def floatToIntColor(rgb): + rgb[0] = int(rgb[0]*256 + .5) + rgb[1] = int(rgb[1]*256 + .5) + rgb[2] = int(rgb[2]*256 + .5) + return safeColor(rgb) + +def randomBrightColor(): + hue = random.random() + sat = random.random()/2.0 + .5 + val = 1.0 + hue, sat, val = colorsys.hsv_to_rgb(hue, sat, val) + ret = [hue, sat, val] + return floatToIntColor(ret) -- cgit v1.2.3 From ccb6ea18285a26b8cc8d99ae7d6540f8ca792398 Mon Sep 17 00:00:00 2001 From: rcoh Date: Sat, 29 Jan 2011 19:28:11 -0500 Subject: couple changes. Merge of friday demo. --- Profile.py | 2 +- util/ColorOps.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Profile.py b/Profile.py index 2f180c9..daabb6b 100644 --- a/Profile.py +++ b/Profile.py @@ -1,4 +1,4 @@ import cProfile from LightInstallation import main -command = """main(['', 'config/6thFloor.xml'])""" +command = """main(['', 'config/Kuan.xml'])""" cProfile.runctx(command, globals(), locals(), filename="smootlight.profile") diff --git a/util/ColorOps.py b/util/ColorOps.py index 037957a..e384605 100644 --- a/util/ColorOps.py +++ b/util/ColorOps.py @@ -11,6 +11,8 @@ def safeColor(c): c[0] = c[0] if c[0] < 255 else 255 c[1] = c[1] if c[1] < 255 else 255 c[2] = c[2] if c[2] < 255 else 255 + + return c def combineColors(colors): -- cgit v1.2.3 From b42cab93f90760eaf3f8aac01c2ab41c1a5b1176 Mon Sep 17 00:00:00 2001 From: rcoh Date: Sat, 29 Jan 2011 19:36:39 -0500 Subject: Fixed a bug that was causing us to drop clicks. --- inputs/PygameInput.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inputs/PygameInput.py b/inputs/PygameInput.py index 414adf3..480630c 100644 --- a/inputs/PygameInput.py +++ b/inputs/PygameInput.py @@ -33,3 +33,5 @@ class PygameInput(Input): if event.type is MOUSEBUTTONDOWN: if self['Clicks']: self.respond({Strings.LOCATION: pygame.mouse.get_pos()}) + else: + pygame.event.post(event) -- cgit v1.2.3 From 277a5143165d2553ce5e97f151cc6b3cea426468 Mon Sep 17 00:00:00 2001 From: rcoh Date: Sat, 29 Jan 2011 21:15:28 -0500 Subject: A couple bits of cleanup to the firefly code --- behaviors/Flasher.py | 12 +++--- config/FireflyDemo.xml | 106 ++----------------------------------------------- 2 files changed, 10 insertions(+), 108 deletions(-) diff --git a/behaviors/Flasher.py b/behaviors/Flasher.py index 4a2dad4..1d79d41 100644 --- a/behaviors/Flasher.py +++ b/behaviors/Flasher.py @@ -1,14 +1,14 @@ -# Implements a pulsing/flashing behavior. -# Jim Salem: jsalem@gmail.com -# -# Args: -# Factor - The speed of flashing. Must be b/w 0 and 1. Default is .95 -# from operationscore.Behavior import * import util.ColorOps as colorops import pdb class Flasher(Behavior): + """Implements a pulsing/flashing behavior. + Jim Salem: jsalem@gmail.com + + Args: + Factor - The speed of flashing. Must be b/w 0 and 1. Default is .95 + """ def processResponse(self, sensorInputs, recursiveInputs): ret = [] for response in sensorInputs: diff --git a/config/FireflyDemo.xml b/config/FireflyDemo.xml index 8008168..856569e 100644 --- a/config/FireflyDemo.xml +++ b/config/FireflyDemo.xml @@ -33,11 +33,9 @@ - renderers/Pygame.xml @@ -67,62 +65,18 @@ 50 - - - inputs/MouseFollower.xml - - behaviors.RandomSetBrightColorBehavior - - setbrightcolor - - - - - behaviors/RandomColor.xml + behaviors.RandomSetBrightColorBehavior - - (255,0,0) - (0,0,255) - - - - - behaviors/PixelDecay.xml - - .5 + setbrightcolor behaviors/PixelDecay.xml - - behaviors/SingleFrame.xml - - - behaviors/PixelDecay.xml - - .01 - - - - behaviors.XYMove - - xymove - 5 - 2 - - behaviors.RestrictLocation @@ -141,24 +95,12 @@ {y}<0 or {y}>200 - - behaviors.BehaviorChain - - movebounce - - xymove - ybounce - xbounce - - - behaviors.Flasher flasher - behaviors.BehaviorChain @@ -167,8 +109,7 @@ randmovement ybounce xbounce - - flasher + flasher @@ -179,12 +120,6 @@ 15 - - behaviors/LoopAndDie.xml - - 80 - - behaviors.RandomWalk @@ -192,17 +127,6 @@ 20 - - - behaviors.ModifyParam - - fadecolor - Sensor - Color - [chan*.98 for chan in {val}] - - - behaviors.BehaviorChain @@ -226,36 +150,14 @@ mover - - behaviors/Accelerate.xml - behaviors.EchoBehavior echo 0 - (90,90,90) + (90,90,90) False - - behaviors.BehaviorChain - - mousechaser - - followmouse - - - echo - square - singleframe - - True - - - - - behaviors/RunningBehavior.xml - -- cgit v1.2.3