1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
from xml.etree.ElementTree import ElementTree
from pixelcore.Screen import *
from pixelcore.PixelStrip import *
import pdb, sys, time, Util
from pygame.locals import *
#Python class to instantiate and drive a Screen through different patterns,
#and effects.
class LightInstallation:
def __init__(self, configFileName):
self.inputs = {} #dict of inputs and their bound behaviors, keyed by InputId
self.behaviors = {}
self.behaviorOutputs = {} #key: [list of output destinations]
self.behaviorInputs = {}
self.componentDict = {}
self.inputBehaviorRegistry = {} #inputid -> behaviors listening to that
#input
#give Util a pointer to our componentRegistry so that everyone can use
#it
Util.setComponentDict(self.componentDict)
self.screen = Screen()
config = Util.loadConfigFile(configFileName)
#read configs from xml
rendererConfig = config.find('RendererConfiguration')
pixelConfig = config.find('PixelConfiguration')
inputConfig = config.find('InputConfiguration')
behaviorConfig = config.find('BehaviorConfiguration')
#inits
self.initializeScreen(pixelConfig)
self.initializeRenderers(rendererConfig)
self.initializeInputs(inputConfig)
self.initializeBehaviors(behaviorConfig)
#registration in dict
self.registerComponents(self.renderers)
self.registerComponents(self.inputs)
self.registerComponents(self.behaviors)
#Done initializing. Lets start this thing!
self.mainLoop()
def initializeScreen(self, layoutConfig):
pixelAssemblers = self.initializeComponent(layoutConfig)
[self.addPixelStrip(l) for l in pixelAssemblers]
def addPixelStrip(self, layoutEngine):
pixelStrip = PixelStrip(layoutEngine)
self.screen.addStrip(pixelStrip)
def initializeInputs(self, inputConfig):
inputs = self.initializeComponent(inputConfig)
self.inputs = inputs
for inputClass in inputs:
inputClass.start()
self.inputBehaviorRegistry[inputClass['Id']] = []
#empty list is list of bound behaviors
def initializeRenderers(self, rendererConfig):
self.renderers = self.initializeComponent(rendererConfig)
def registerComponents(self, components):
for component in components:
try:
cid = component['Id']
except:
raise Exception('Components must have Ids!')
self.componentDict[cid] = component
def initializeComponent(self, config):
components = []
if config != None:
for configItem in config.getchildren():
[module,className] = configItem.find('Class').text.split('.')
exec('from ' + module+'.'+className + ' import *')
args = Util.generateArgDict(configItem.find('Args'))
args['parentScope'] = self #TODO: we shouldn't give away scope
#like this, find another way.
components.append(eval(className+'(args)')) #TODO: doesn't error
#right
return components
def alive(self):
return True
def mainLoop(self):
#self.screen.allOn()
while 1:
time.sleep(.1)
responses = self.evaluateBehaviors() #inputs are all queued when they
#happen, so we only need to run the behaviors
[self.screen.respond(response) for response in responses if
response != []]
self.screen.timeStep()
[r.render(self.screen) for r in self.renderers]
#evaluates all the behaviors (including inter-dependencies) and returns a
#list of responses to go to the screen.
def evaluateBehaviors(self):
responses = {}
responses['Screen'] = [] #responses to the screen
for behavior in self.behaviors:
responses[behavior['Id']] = behavior.timeStep()
if behavior['RenderToScreen'] == True: #TODO: this uses extra space,
#we can use less in the future if needbe.
responses['Screen'] += responses[behavior['Id']]
return responses['Screen']
def initializeBehaviors(self, behaviorConfig):
self.behaviors = self.initializeComponent(behaviorConfig)
for behavior in self.behaviors:
self.addBehavior(behavior)
#TODO: we probably don't need this anymore :(
def topologicalBehaviorSort(self):
return Util.topologicalSort(self.behaviorDependencies)
#Does work needed to add a behavior: currently -- maps behavior inputs into
#the input behavior registry.
def addBehavior(self, behavior):
for inputId in behavior.argDict['Inputs']:
if inputId in self.inputBehaviorRegistry: #it could be a behavior
self.inputBehaviorRegistry[inputId].append(behavior['Id'])
def processResponse(self,inputDict, responseDict):
#pdb.set_trace()
inputId = inputDict['Id']
boundBehaviorIds = self.inputBehaviorRegistry[inputId]
[self.componentDict[b].addInput(responseDict) for b in boundBehaviorIds]
def main(argv):
print argv
if len(argv) == 1:
l = LightInstallation('LightInstallationConfig.xml')
else:
l = LightInstallation(argv[1])
if __name__ == "__main__":
main(sys.argv)
|