target.py 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  1. """
  2. Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration) and Sam Pieters (DEVS)
  3. Model author: Sam Pieters
  4. Model name: Bouncing_Balls_DEVS_Version
  5. Model description:
  6. Tkinter frame with bouncing balls in it.
  7. """
  8. from sccd.runtime.DEVS_statecharts_core import *
  9. from sccd.runtime.libs import ui_v2 as ui
  10. import random
  11. import numpy as np
  12. CANVAS_DIMS = (800, 550)
  13. # package "Bouncing_Balls_DEVS_Version"
  14. class MainAppInstance(RuntimeClassBase):
  15. def __init__(self, atomdevs, id, start_port_id):
  16. RuntimeClassBase.__init__(self, atomdevs, id)
  17. self.associations = {}
  18. self.associations["fields"] = Association("Field", 0, -1)
  19. self.semantics.big_step_maximality = StatechartSemantics.TakeMany
  20. self.semantics.internal_event_lifeline = StatechartSemantics.Queue
  21. self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
  22. self.semantics.priority = StatechartSemantics.SourceParent
  23. self.semantics.concurrency = StatechartSemantics.Single
  24. # build Statechart structure
  25. self.build_statechart_structure()
  26. # call user defined constructor
  27. MainAppInstance.user_defined_constructor(self)
  28. port_name = addInputPort("ui", start_port_id, True)
  29. atomdevs.state.port_mappings[port_name] = id
  30. port_name = addInputPort("<narrow_cast>", start_port_id)
  31. atomdevs.state.port_mappings[port_name] = id
  32. def user_defined_constructor(self):
  33. self.nr_of_fields = 0
  34. def user_defined_destructor(self):
  35. pass
  36. # builds Statechart structure
  37. def build_statechart_structure(self):
  38. # state <root>
  39. self.states[""] = State(0, "", self)
  40. # state /running
  41. self.states["/running"] = State(1, "/running", self)
  42. # state /running/root
  43. self.states["/running/root"] = ParallelState(2, "/running/root", self)
  44. # state /running/root/main_behaviour
  45. self.states["/running/root/main_behaviour"] = State(3, "/running/root/main_behaviour", self)
  46. # state /running/root/main_behaviour/initializing
  47. self.states["/running/root/main_behaviour/initializing"] = State(4, "/running/root/main_behaviour/initializing", self)
  48. # state /running/root/main_behaviour/running
  49. self.states["/running/root/main_behaviour/running"] = State(5, "/running/root/main_behaviour/running", self)
  50. # state /running/root/cd_behaviour
  51. self.states["/running/root/cd_behaviour"] = State(6, "/running/root/cd_behaviour", self)
  52. # state /running/root/cd_behaviour/waiting
  53. self.states["/running/root/cd_behaviour/waiting"] = State(7, "/running/root/cd_behaviour/waiting", self)
  54. # state /running/root/cd_behaviour/creating
  55. self.states["/running/root/cd_behaviour/creating"] = State(8, "/running/root/cd_behaviour/creating", self)
  56. # state /running/root/cd_behaviour/check_nr_of_fields
  57. self.states["/running/root/cd_behaviour/check_nr_of_fields"] = State(9, "/running/root/cd_behaviour/check_nr_of_fields", self)
  58. self.states["/running/root/cd_behaviour/check_nr_of_fields"].setEnter(self._running_root_cd_behaviour_check_nr_of_fields_enter)
  59. self.states["/running/root/cd_behaviour/check_nr_of_fields"].setExit(self._running_root_cd_behaviour_check_nr_of_fields_exit)
  60. # state /running/root/cd_behaviour/stopped
  61. self.states["/running/root/cd_behaviour/stopped"] = State(10, "/running/root/cd_behaviour/stopped", self)
  62. # state /running/stopped
  63. self.states["/running/stopped"] = State(11, "/running/stopped", self)
  64. # add children
  65. self.states[""].addChild(self.states["/running"])
  66. self.states["/running"].addChild(self.states["/running/root"])
  67. self.states["/running"].addChild(self.states["/running/stopped"])
  68. self.states["/running/root"].addChild(self.states["/running/root/main_behaviour"])
  69. self.states["/running/root"].addChild(self.states["/running/root/cd_behaviour"])
  70. self.states["/running/root/main_behaviour"].addChild(self.states["/running/root/main_behaviour/initializing"])
  71. self.states["/running/root/main_behaviour"].addChild(self.states["/running/root/main_behaviour/running"])
  72. self.states["/running/root/cd_behaviour"].addChild(self.states["/running/root/cd_behaviour/waiting"])
  73. self.states["/running/root/cd_behaviour"].addChild(self.states["/running/root/cd_behaviour/creating"])
  74. self.states["/running/root/cd_behaviour"].addChild(self.states["/running/root/cd_behaviour/check_nr_of_fields"])
  75. self.states["/running/root/cd_behaviour"].addChild(self.states["/running/root/cd_behaviour/stopped"])
  76. self.states[""].fixTree()
  77. self.states[""].default_state = self.states["/running"]
  78. self.states["/running"].default_state = self.states["/running/root"]
  79. self.states["/running/root/main_behaviour"].default_state = self.states["/running/root/main_behaviour/initializing"]
  80. self.states["/running/root/cd_behaviour"].default_state = self.states["/running/root/cd_behaviour/waiting"]
  81. # transition /running/root/main_behaviour/initializing
  82. _running_root_main_behaviour_initializing_0 = Transition(self, self.states["/running/root/main_behaviour/initializing"], [self.states["/running/root/main_behaviour/running"]])
  83. _running_root_main_behaviour_initializing_0.setAction(self._running_root_main_behaviour_initializing_0_exec)
  84. _running_root_main_behaviour_initializing_0.setTrigger(None)
  85. self.states["/running/root/main_behaviour/initializing"].addTransition(_running_root_main_behaviour_initializing_0)
  86. # transition /running/root/main_behaviour/running
  87. _running_root_main_behaviour_running_0 = Transition(self, self.states["/running/root/main_behaviour/running"], [self.states["/running/root/main_behaviour/running"]])
  88. _running_root_main_behaviour_running_0.setAction(self._running_root_main_behaviour_running_0_exec)
  89. _running_root_main_behaviour_running_0.setTrigger(Event("button_pressed", None))
  90. _running_root_main_behaviour_running_0.setGuard(self._running_root_main_behaviour_running_0_guard)
  91. self.states["/running/root/main_behaviour/running"].addTransition(_running_root_main_behaviour_running_0)
  92. # transition /running/root/cd_behaviour/waiting
  93. _running_root_cd_behaviour_waiting_0 = Transition(self, self.states["/running/root/cd_behaviour/waiting"], [self.states["/running/root/cd_behaviour/creating"]])
  94. _running_root_cd_behaviour_waiting_0.setAction(self._running_root_cd_behaviour_waiting_0_exec)
  95. _running_root_cd_behaviour_waiting_0.setTrigger(Event("create_field", None))
  96. self.states["/running/root/cd_behaviour/waiting"].addTransition(_running_root_cd_behaviour_waiting_0)
  97. _running_root_cd_behaviour_waiting_1 = Transition(self, self.states["/running/root/cd_behaviour/waiting"], [self.states["/running/root/cd_behaviour/check_nr_of_fields"]])
  98. _running_root_cd_behaviour_waiting_1.setAction(self._running_root_cd_behaviour_waiting_1_exec)
  99. _running_root_cd_behaviour_waiting_1.setTrigger(Event("delete_field", None))
  100. self.states["/running/root/cd_behaviour/waiting"].addTransition(_running_root_cd_behaviour_waiting_1)
  101. # transition /running/root/cd_behaviour/creating
  102. _running_root_cd_behaviour_creating_0 = Transition(self, self.states["/running/root/cd_behaviour/creating"], [self.states["/running/root/cd_behaviour/waiting"]])
  103. _running_root_cd_behaviour_creating_0.setAction(self._running_root_cd_behaviour_creating_0_exec)
  104. _running_root_cd_behaviour_creating_0.setTrigger(Event("instance_created", None))
  105. self.states["/running/root/cd_behaviour/creating"].addTransition(_running_root_cd_behaviour_creating_0)
  106. # transition /running/root/cd_behaviour/check_nr_of_fields
  107. _running_root_cd_behaviour_check_nr_of_fields_0 = Transition(self, self.states["/running/root/cd_behaviour/check_nr_of_fields"], [self.states["/running/root/cd_behaviour/stopped"]])
  108. _running_root_cd_behaviour_check_nr_of_fields_0.setAction(self._running_root_cd_behaviour_check_nr_of_fields_0_exec)
  109. _running_root_cd_behaviour_check_nr_of_fields_0.setTrigger(Event("_0after"))
  110. _running_root_cd_behaviour_check_nr_of_fields_0.setGuard(self._running_root_cd_behaviour_check_nr_of_fields_0_guard)
  111. self.states["/running/root/cd_behaviour/check_nr_of_fields"].addTransition(_running_root_cd_behaviour_check_nr_of_fields_0)
  112. _running_root_cd_behaviour_check_nr_of_fields_1 = Transition(self, self.states["/running/root/cd_behaviour/check_nr_of_fields"], [self.states["/running/root/cd_behaviour/waiting"]])
  113. _running_root_cd_behaviour_check_nr_of_fields_1.setTrigger(None)
  114. _running_root_cd_behaviour_check_nr_of_fields_1.setGuard(self._running_root_cd_behaviour_check_nr_of_fields_1_guard)
  115. self.states["/running/root/cd_behaviour/check_nr_of_fields"].addTransition(_running_root_cd_behaviour_check_nr_of_fields_1)
  116. # transition /running/root
  117. _running_root_0 = Transition(self, self.states["/running/root"], [self.states["/running/stopped"]])
  118. _running_root_0.setAction(self._running_root_0_exec)
  119. _running_root_0.setTrigger(Event("stop", None))
  120. self.states["/running/root"].addTransition(_running_root_0)
  121. def _running_root_cd_behaviour_check_nr_of_fields_enter(self):
  122. self.addTimer(0, 0.05)
  123. def _running_root_cd_behaviour_check_nr_of_fields_exit(self):
  124. self.removeTimer(0)
  125. def _running_root_0_exec(self, parameters):
  126. self.big_step.outputEvent(Event("destroy_all", self.getOutPortName("ui"), []))
  127. def _running_root_main_behaviour_initializing_0_exec(self, parameters):
  128. self.raiseInternalEvent(Event("create_field", None, []))
  129. def _running_root_main_behaviour_running_0_exec(self, parameters):
  130. event_name = parameters[0]
  131. self.raiseInternalEvent(Event("create_field", None, []))
  132. def _running_root_main_behaviour_running_0_guard(self, parameters):
  133. event_name = parameters[0]
  134. return event_name == "create_new_field"
  135. def _running_root_cd_behaviour_waiting_0_exec(self, parameters):
  136. self.big_step.outputEventOM(Event("create_instance", None, [self, "fields"]))
  137. def _running_root_cd_behaviour_waiting_1_exec(self, parameters):
  138. association_name = parameters[0]
  139. self.big_step.outputEventOM(Event("delete_instance", None, [self, association_name]))
  140. self.nr_of_fields -= 1
  141. def _running_root_cd_behaviour_creating_0_exec(self, parameters):
  142. association_name = parameters[0]
  143. self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
  144. self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name])]))
  145. self.nr_of_fields += 1
  146. def _running_root_cd_behaviour_check_nr_of_fields_0_exec(self, parameters):
  147. self.raiseInternalEvent(Event("stop", None, []))
  148. def _running_root_cd_behaviour_check_nr_of_fields_0_guard(self, parameters):
  149. return self.nr_of_fields == 0
  150. def _running_root_cd_behaviour_check_nr_of_fields_1_guard(self, parameters):
  151. return self.nr_of_fields != 0
  152. def initializeStatechart(self):
  153. # enter default state
  154. self.default_targets = self.states["/running"].getEffectiveTargetStates()
  155. RuntimeClassBase.initializeStatechart(self)
  156. class MainApp(ClassBase):
  157. def __init__(self, name):
  158. ClassBase.__init__(self, name)
  159. self.input = self.addInPort("input")
  160. self.glob_outputs["ui"] = self.addOutPort("ui")
  161. self.outputs["fields"] = self.addOutPort("fields")
  162. new_instance = self.constructObject(0, 0, [])
  163. self.state.instances[new_instance.instance_id] = new_instance
  164. self.state.next_instance = self.state.next_instance + 1
  165. def constructObject(self, id, start_port_id, parameters):
  166. new_instance = MainAppInstance(self, id, start_port_id)
  167. return new_instance
  168. class FieldInstance(RuntimeClassBase):
  169. def __init__(self, atomdevs, id, start_port_id):
  170. RuntimeClassBase.__init__(self, atomdevs, id)
  171. self.associations = {}
  172. self.associations["balls"] = Association("Ball", 0, -1)
  173. self.associations["buttons"] = Association("Button", 0, -1)
  174. self.associations["collisions"] = Association("CollisionPhysics", 0, -1)
  175. self.associations["parent"] = Association("MainApp", 1, 1)
  176. self.semantics.big_step_maximality = StatechartSemantics.TakeMany
  177. self.semantics.internal_event_lifeline = StatechartSemantics.Queue
  178. self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
  179. self.semantics.priority = StatechartSemantics.SourceParent
  180. self.semantics.concurrency = StatechartSemantics.Single
  181. # build Statechart structure
  182. self.build_statechart_structure()
  183. # user defined attributes
  184. self.window_id = None
  185. self.canvas_id = None
  186. # call user defined constructor
  187. FieldInstance.user_defined_constructor(self)
  188. port_name = addInputPort("ui", start_port_id, True)
  189. atomdevs.state.port_mappings[port_name] = id
  190. port_name = addInputPort("<narrow_cast>", start_port_id)
  191. atomdevs.state.port_mappings[port_name] = id
  192. port_name = addInputPort("field_ui", start_port_id)
  193. atomdevs.state.port_mappings[port_name] = id
  194. self.inports["field_ui"] = port_name
  195. def user_defined_constructor(self):
  196. self.balls = {}
  197. self.collisions = []
  198. def user_defined_destructor(self):
  199. pass
  200. # user defined method
  201. def distance(self, point1, point2):
  202. return ((point1['x'] - point2['x']) ** 2 + (point1['y'] - point2['y']) ** 2) ** 0.5
  203. # user defined method
  204. def check_collision(self, ball1, ball2):
  205. # Calculate the distance between the centers of the two balls
  206. dist = self.distance(ball1['pos'], ball2['pos'])
  207. # Calculate the sum of the radii
  208. radii_sum = ball1['r'] + ball2['r']
  209. # Check if they are colliding
  210. return dist <= radii_sum
  211. # builds Statechart structure
  212. def build_statechart_structure(self):
  213. # state <root>
  214. self.states[""] = State(0, "", self)
  215. # state /root
  216. self.states["/root"] = State(1, "/root", self)
  217. # state /root/waiting
  218. self.states["/root/waiting"] = State(2, "/root/waiting", self)
  219. # state /root/creating_window
  220. self.states["/root/creating_window"] = State(3, "/root/creating_window", self)
  221. self.states["/root/creating_window"].setEnter(self._root_creating_window_enter)
  222. # state /root/creating_canvas
  223. self.states["/root/creating_canvas"] = State(4, "/root/creating_canvas", self)
  224. self.states["/root/creating_canvas"].setEnter(self._root_creating_canvas_enter)
  225. # state /root/creating_button
  226. self.states["/root/creating_button"] = State(5, "/root/creating_button", self)
  227. self.states["/root/creating_button"].setEnter(self._root_creating_button_enter)
  228. # state /root/running
  229. self.states["/root/running"] = ParallelState(6, "/root/running", self)
  230. # state /root/running/main_behaviour
  231. self.states["/root/running/main_behaviour"] = State(7, "/root/running/main_behaviour", self)
  232. # state /root/running/main_behaviour/running
  233. self.states["/root/running/main_behaviour/running"] = State(8, "/root/running/main_behaviour/running", self)
  234. # state /root/running/main_behaviour/creating_ball
  235. self.states["/root/running/main_behaviour/creating_ball"] = State(9, "/root/running/main_behaviour/creating_ball", self)
  236. # state /root/running/deleting_behaviour
  237. self.states["/root/running/deleting_behaviour"] = State(10, "/root/running/deleting_behaviour", self)
  238. # state /root/running/deleting_behaviour/running
  239. self.states["/root/running/deleting_behaviour/running"] = State(11, "/root/running/deleting_behaviour/running", self)
  240. # state /root/running/child_behaviour
  241. self.states["/root/running/child_behaviour"] = State(12, "/root/running/child_behaviour", self)
  242. # state /root/running/child_behaviour/listening
  243. self.states["/root/running/child_behaviour/listening"] = State(13, "/root/running/child_behaviour/listening", self)
  244. # state /root/running/deleting_balls_behaviour
  245. self.states["/root/running/deleting_balls_behaviour"] = State(14, "/root/running/deleting_balls_behaviour", self)
  246. # state /root/running/deleting_balls_behaviour/listening
  247. self.states["/root/running/deleting_balls_behaviour/listening"] = State(15, "/root/running/deleting_balls_behaviour/listening", self)
  248. # state /root/deleting
  249. self.states["/root/deleting"] = State(16, "/root/deleting", self)
  250. # state /root/deleted
  251. self.states["/root/deleted"] = State(17, "/root/deleted", self)
  252. # add children
  253. self.states[""].addChild(self.states["/root"])
  254. self.states["/root"].addChild(self.states["/root/waiting"])
  255. self.states["/root"].addChild(self.states["/root/creating_window"])
  256. self.states["/root"].addChild(self.states["/root/creating_canvas"])
  257. self.states["/root"].addChild(self.states["/root/creating_button"])
  258. self.states["/root"].addChild(self.states["/root/running"])
  259. self.states["/root"].addChild(self.states["/root/deleting"])
  260. self.states["/root"].addChild(self.states["/root/deleted"])
  261. self.states["/root/running"].addChild(self.states["/root/running/main_behaviour"])
  262. self.states["/root/running"].addChild(self.states["/root/running/deleting_behaviour"])
  263. self.states["/root/running"].addChild(self.states["/root/running/child_behaviour"])
  264. self.states["/root/running"].addChild(self.states["/root/running/deleting_balls_behaviour"])
  265. self.states["/root/running/main_behaviour"].addChild(self.states["/root/running/main_behaviour/running"])
  266. self.states["/root/running/main_behaviour"].addChild(self.states["/root/running/main_behaviour/creating_ball"])
  267. self.states["/root/running/deleting_behaviour"].addChild(self.states["/root/running/deleting_behaviour/running"])
  268. self.states["/root/running/child_behaviour"].addChild(self.states["/root/running/child_behaviour/listening"])
  269. self.states["/root/running/deleting_balls_behaviour"].addChild(self.states["/root/running/deleting_balls_behaviour/listening"])
  270. self.states[""].fixTree()
  271. self.states[""].default_state = self.states["/root"]
  272. self.states["/root"].default_state = self.states["/root/waiting"]
  273. self.states["/root/running/main_behaviour"].default_state = self.states["/root/running/main_behaviour/running"]
  274. self.states["/root/running/deleting_behaviour"].default_state = self.states["/root/running/deleting_behaviour/running"]
  275. self.states["/root/running/child_behaviour"].default_state = self.states["/root/running/child_behaviour/listening"]
  276. self.states["/root/running/deleting_balls_behaviour"].default_state = self.states["/root/running/deleting_balls_behaviour/listening"]
  277. # transition /root/waiting
  278. _root_waiting_0 = Transition(self, self.states["/root/waiting"], [self.states["/root/creating_window"]])
  279. _root_waiting_0.setAction(self._root_waiting_0_exec)
  280. _root_waiting_0.setTrigger(Event("set_association_name", None))
  281. self.states["/root/waiting"].addTransition(_root_waiting_0)
  282. # transition /root/creating_window
  283. _root_creating_window_0 = Transition(self, self.states["/root/creating_window"], [self.states["/root/creating_canvas"]])
  284. _root_creating_window_0.setAction(self._root_creating_window_0_exec)
  285. _root_creating_window_0.setTrigger(Event("window_created", None))
  286. self.states["/root/creating_window"].addTransition(_root_creating_window_0)
  287. # transition /root/creating_canvas
  288. _root_creating_canvas_0 = Transition(self, self.states["/root/creating_canvas"], [self.states["/root/creating_button"]])
  289. _root_creating_canvas_0.setAction(self._root_creating_canvas_0_exec)
  290. _root_creating_canvas_0.setTrigger(Event("canvas_created", None))
  291. self.states["/root/creating_canvas"].addTransition(_root_creating_canvas_0)
  292. # transition /root/creating_button
  293. _root_creating_button_0 = Transition(self, self.states["/root/creating_button"], [self.states["/root/running"]])
  294. _root_creating_button_0.setAction(self._root_creating_button_0_exec)
  295. _root_creating_button_0.setTrigger(Event("instance_created", None))
  296. self.states["/root/creating_button"].addTransition(_root_creating_button_0)
  297. # transition /root/running/main_behaviour/running
  298. _root_running_main_behaviour_running_0 = Transition(self, self.states["/root/running/main_behaviour/running"], [self.states["/root/running/main_behaviour/creating_ball"]])
  299. _root_running_main_behaviour_running_0.setAction(self._root_running_main_behaviour_running_0_exec)
  300. _root_running_main_behaviour_running_0.setTrigger(Event("right_click", self.getInPortName("field_ui")))
  301. self.states["/root/running/main_behaviour/running"].addTransition(_root_running_main_behaviour_running_0)
  302. # transition /root/running/main_behaviour/creating_ball
  303. _root_running_main_behaviour_creating_ball_0 = Transition(self, self.states["/root/running/main_behaviour/creating_ball"], [self.states["/root/running/main_behaviour/creating_ball"]])
  304. _root_running_main_behaviour_creating_ball_0.setAction(self._root_running_main_behaviour_creating_ball_0_exec)
  305. _root_running_main_behaviour_creating_ball_0.setTrigger(Event("instance_created", None))
  306. self.states["/root/running/main_behaviour/creating_ball"].addTransition(_root_running_main_behaviour_creating_ball_0)
  307. _root_running_main_behaviour_creating_ball_1 = Transition(self, self.states["/root/running/main_behaviour/creating_ball"], [self.states["/root/running/main_behaviour/running"]])
  308. _root_running_main_behaviour_creating_ball_1.setAction(self._root_running_main_behaviour_creating_ball_1_exec)
  309. _root_running_main_behaviour_creating_ball_1.setTrigger(Event("init_params", None))
  310. self.states["/root/running/main_behaviour/creating_ball"].addTransition(_root_running_main_behaviour_creating_ball_1)
  311. # transition /root/running/deleting_behaviour/running
  312. _root_running_deleting_behaviour_running_0 = Transition(self, self.states["/root/running/deleting_behaviour/running"], [self.states["/root/running/deleting_behaviour/running"]])
  313. _root_running_deleting_behaviour_running_0.setAction(self._root_running_deleting_behaviour_running_0_exec)
  314. _root_running_deleting_behaviour_running_0.setTrigger(Event("delete_ball", None))
  315. self.states["/root/running/deleting_behaviour/running"].addTransition(_root_running_deleting_behaviour_running_0)
  316. _root_running_deleting_behaviour_running_1 = Transition(self, self.states["/root/running/deleting_behaviour/running"], [self.states["/root/running/deleting_behaviour/running"]])
  317. _root_running_deleting_behaviour_running_1.setAction(self._root_running_deleting_behaviour_running_1_exec)
  318. _root_running_deleting_behaviour_running_1.setTrigger(Event("move_ball", None))
  319. self.states["/root/running/deleting_behaviour/running"].addTransition(_root_running_deleting_behaviour_running_1)
  320. _root_running_deleting_behaviour_running_2 = Transition(self, self.states["/root/running/deleting_behaviour/running"], [self.states["/root/running/deleting_behaviour/running"]])
  321. _root_running_deleting_behaviour_running_2.setAction(self._root_running_deleting_behaviour_running_2_exec)
  322. _root_running_deleting_behaviour_running_2.setTrigger(None)
  323. _root_running_deleting_behaviour_running_2.setGuard(self._root_running_deleting_behaviour_running_2_guard)
  324. self.states["/root/running/deleting_behaviour/running"].addTransition(_root_running_deleting_behaviour_running_2)
  325. _root_running_deleting_behaviour_running_3 = Transition(self, self.states["/root/running/deleting_behaviour/running"], [self.states["/root/running/deleting_behaviour/running"]])
  326. _root_running_deleting_behaviour_running_3.setAction(self._root_running_deleting_behaviour_running_3_exec)
  327. _root_running_deleting_behaviour_running_3.setTrigger(Event("instance_created", None))
  328. self.states["/root/running/deleting_behaviour/running"].addTransition(_root_running_deleting_behaviour_running_3)
  329. _root_running_deleting_behaviour_running_4 = Transition(self, self.states["/root/running/deleting_behaviour/running"], [self.states["/root/running/deleting_behaviour/running"]])
  330. _root_running_deleting_behaviour_running_4.setAction(self._root_running_deleting_behaviour_running_4_exec)
  331. _root_running_deleting_behaviour_running_4.setTrigger(Event("update_vel", None))
  332. self.states["/root/running/deleting_behaviour/running"].addTransition(_root_running_deleting_behaviour_running_4)
  333. _root_running_deleting_behaviour_running_5 = Transition(self, self.states["/root/running/deleting_behaviour/running"], [self.states["/root/running/deleting_behaviour/running"]])
  334. _root_running_deleting_behaviour_running_5.setAction(self._root_running_deleting_behaviour_running_5_exec)
  335. _root_running_deleting_behaviour_running_5.setTrigger(Event("delete_physics", None))
  336. self.states["/root/running/deleting_behaviour/running"].addTransition(_root_running_deleting_behaviour_running_5)
  337. # transition /root/running/child_behaviour/listening
  338. _root_running_child_behaviour_listening_0 = Transition(self, self.states["/root/running/child_behaviour/listening"], [self.states["/root/running/child_behaviour/listening"]])
  339. _root_running_child_behaviour_listening_0.setAction(self._root_running_child_behaviour_listening_0_exec)
  340. _root_running_child_behaviour_listening_0.setTrigger(Event("button_pressed", None))
  341. self.states["/root/running/child_behaviour/listening"].addTransition(_root_running_child_behaviour_listening_0)
  342. # transition /root/running/deleting_balls_behaviour/listening
  343. _root_running_deleting_balls_behaviour_listening_0 = Transition(self, self.states["/root/running/deleting_balls_behaviour/listening"], [self.states["/root/running/deleting_balls_behaviour/listening"]])
  344. _root_running_deleting_balls_behaviour_listening_0.setAction(self._root_running_deleting_balls_behaviour_listening_0_exec)
  345. _root_running_deleting_balls_behaviour_listening_0.setTrigger(Event("key_press", self.getInPortName("field_ui")))
  346. _root_running_deleting_balls_behaviour_listening_0.setGuard(self._root_running_deleting_balls_behaviour_listening_0_guard)
  347. self.states["/root/running/deleting_balls_behaviour/listening"].addTransition(_root_running_deleting_balls_behaviour_listening_0)
  348. # transition /root/deleting
  349. _root_deleting_0 = Transition(self, self.states["/root/deleting"], [self.states["/root/deleted"]])
  350. _root_deleting_0.setAction(self._root_deleting_0_exec)
  351. _root_deleting_0.setTrigger(None)
  352. self.states["/root/deleting"].addTransition(_root_deleting_0)
  353. # transition /root/running
  354. _root_running_0 = Transition(self, self.states["/root/running"], [self.states["/root/deleting"]])
  355. _root_running_0.setAction(self._root_running_0_exec)
  356. _root_running_0.setTrigger(Event("window_close", self.getInPortName("field_ui")))
  357. self.states["/root/running"].addTransition(_root_running_0)
  358. def _root_creating_window_enter(self):
  359. self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [800, 600, "BouncingBalls", self.inports['field_ui']]))
  360. def _root_creating_canvas_enter(self):
  361. self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, CANVAS_DIMS[0], CANVAS_DIMS[1], {'background':'#eee'}, self.inports['field_ui']]))
  362. def _root_creating_button_enter(self):
  363. self.big_step.outputEventOM(Event("create_instance", None, [self, "buttons", "Button", self.window_id, 'create_new_field', 'Spawn New Window']))
  364. def _root_running_0_exec(self, parameters):
  365. self.big_step.outputEventOM(Event("delete_instance", None, [self, "buttons"]))
  366. self.big_step.outputEventOM(Event("delete_instance", None, [self, "balls"]))
  367. def _root_waiting_0_exec(self, parameters):
  368. association_name = parameters[0]
  369. self.association_name = association_name
  370. def _root_creating_window_0_exec(self, parameters):
  371. window_id = parameters[0]
  372. self.window_id = window_id
  373. self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.WINDOW_CLOSE, 'window_close', self.inports['field_ui']]))
  374. self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.KEY_PRESS, 'key_press', self.inports['field_ui']]))
  375. def _root_creating_canvas_0_exec(self, parameters):
  376. canvas_id = parameters[0]
  377. self.canvas_id = canvas_id
  378. self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RIGHT_CLICK, 'right_click', self.inports['field_ui']]))
  379. self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['field_ui']]))
  380. self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RELEASE, 'mouse_release', self.inports['field_ui']]))
  381. def _root_creating_button_0_exec(self, parameters):
  382. association_name = parameters[0]
  383. self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
  384. def _root_running_main_behaviour_running_0_exec(self, parameters):
  385. x = parameters[0]
  386. y = parameters[1]
  387. button = parameters[2]
  388. self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, x, y]))
  389. def _root_running_main_behaviour_creating_ball_0_exec(self, parameters):
  390. association_name = parameters[0]
  391. self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
  392. self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("get_init_params", None, [association_name])]))
  393. def _root_running_main_behaviour_creating_ball_1_exec(self, parameters):
  394. link_id = parameters[0]
  395. ball_r = parameters[1]
  396. ball_vel = parameters[2]
  397. ball_pos = parameters[3]
  398. self.balls[link_id] = {'r': ball_r, 'vel': ball_vel, 'pos': ball_pos}
  399. def _root_running_deleting_behaviour_running_0_exec(self, parameters):
  400. association_name = parameters[0]
  401. self.big_step.outputEventOM(Event("delete_instance", None, [self, association_name]))
  402. def _root_running_deleting_behaviour_running_1_exec(self, parameters):
  403. link_id = parameters[0]
  404. ball_pos = parameters[1]
  405. ball_vel = parameters[2]
  406. # Update the position and velocity
  407. self.balls[link_id]['pos'] = ball_pos
  408. self.balls[link_id]['vel'] = ball_vel
  409. # Check for collisions
  410. collisions = []
  411. for other_id, other_ball in self.balls.items():
  412. if other_id != link_id: # Don't check collision with itself
  413. if self.check_collision(self.balls[link_id], other_ball):
  414. self.collisions.append((link_id, other_id))
  415. def _root_running_deleting_behaviour_running_2_exec(self, parameters):
  416. self.big_step.outputEventOM(Event("create_instance", None, [self, "collisions", "CollisionPhysics", self.collisions[-1][0], self.collisions[-1][1], self.balls[self.collisions[-1][0]], self.balls[self.collisions[-1][1]]]))
  417. self.collisions = self.collisions[:-1]
  418. def _root_running_deleting_behaviour_running_2_guard(self, parameters):
  419. return self.collisions
  420. def _root_running_deleting_behaviour_running_3_exec(self, parameters):
  421. association_name = parameters[0]
  422. self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name])]))
  423. self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
  424. def _root_running_deleting_behaviour_running_4_exec(self, parameters):
  425. ball1_id = parameters[0]
  426. ball2_id = parameters[1]
  427. new_vel1 = parameters[2]
  428. new_vel2 = parameters[3]
  429. self.big_step.outputEventOM(Event("narrow_cast", None, [self, ball1_id, Event("update_ball_vel", None, [new_vel1])]))
  430. self.big_step.outputEventOM(Event("narrow_cast", None, [self, ball2_id, Event("update_ball_vel", None, [new_vel2])]))
  431. def _root_running_deleting_behaviour_running_5_exec(self, parameters):
  432. association_id = parameters[0]
  433. self.big_step.outputEventOM(Event("delete_instance", None, [self, association_id]))
  434. def _root_running_child_behaviour_listening_0_exec(self, parameters):
  435. event_name = parameters[0]
  436. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("button_pressed", None, [event_name])]))
  437. def _root_running_deleting_balls_behaviour_listening_0_exec(self, parameters):
  438. key = parameters[0]
  439. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'balls', Event("delete_self", None, [])]))
  440. def _root_running_deleting_balls_behaviour_listening_0_guard(self, parameters):
  441. key = parameters[0]
  442. return key == ui.KEYCODES.DELETE
  443. def _root_deleting_0_exec(self, parameters):
  444. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("delete_field", None, [self.association_name])]))
  445. self.big_step.outputEvent(Event("destroy_window", self.getOutPortName("ui"), [self.window_id]))
  446. def initializeStatechart(self):
  447. # enter default state
  448. self.default_targets = self.states["/root"].getEffectiveTargetStates()
  449. RuntimeClassBase.initializeStatechart(self)
  450. class Field(ClassBase):
  451. def __init__(self, name):
  452. ClassBase.__init__(self, name)
  453. self.input = self.addInPort("input")
  454. self.glob_outputs["ui"] = self.addOutPort("ui")
  455. self.outputs["balls"] = self.addOutPort("balls")
  456. self.outputs["buttons"] = self.addOutPort("buttons")
  457. self.outputs["collisions"] = self.addOutPort("collisions")
  458. self.outputs["parent"] = self.addOutPort("parent")
  459. self.field_ui = self.addInPort("field_ui")
  460. def constructObject(self, id, start_port_id, parameters):
  461. new_instance = FieldInstance(self, id, start_port_id)
  462. return new_instance
  463. class ButtonInstance(RuntimeClassBase):
  464. def __init__(self, atomdevs, id, start_port_id, window_id, event_name, button_text):
  465. RuntimeClassBase.__init__(self, atomdevs, id)
  466. self.associations = {}
  467. self.associations["parent"] = Association("Field", 1, 1)
  468. self.semantics.big_step_maximality = StatechartSemantics.TakeMany
  469. self.semantics.internal_event_lifeline = StatechartSemantics.Queue
  470. self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
  471. self.semantics.priority = StatechartSemantics.SourceParent
  472. self.semantics.concurrency = StatechartSemantics.Single
  473. # build Statechart structure
  474. self.build_statechart_structure()
  475. # user defined attributes
  476. self.window_id = None
  477. self.event_name = None
  478. self.button_id = None
  479. # call user defined constructor
  480. ButtonInstance.user_defined_constructor(self, window_id, event_name, button_text)
  481. port_name = addInputPort("ui", start_port_id, True)
  482. atomdevs.state.port_mappings[port_name] = id
  483. port_name = addInputPort("<narrow_cast>", start_port_id)
  484. atomdevs.state.port_mappings[port_name] = id
  485. port_name = addInputPort("button_ui", start_port_id)
  486. atomdevs.state.port_mappings[port_name] = id
  487. self.inports["button_ui"] = port_name
  488. def user_defined_constructor(self, window_id, event_name, button_text):
  489. self.window_id = window_id;
  490. self.event_name = event_name;
  491. def user_defined_destructor(self):
  492. pass
  493. # builds Statechart structure
  494. def build_statechart_structure(self):
  495. # state <root>
  496. self.states[""] = State(0, "", self)
  497. # state /creating_button
  498. self.states["/creating_button"] = State(1, "/creating_button", self)
  499. self.states["/creating_button"].setEnter(self._creating_button_enter)
  500. # state /running
  501. self.states["/running"] = State(2, "/running", self)
  502. # add children
  503. self.states[""].addChild(self.states["/creating_button"])
  504. self.states[""].addChild(self.states["/running"])
  505. self.states[""].fixTree()
  506. self.states[""].default_state = self.states["/creating_button"]
  507. # transition /creating_button
  508. _creating_button_0 = Transition(self, self.states["/creating_button"], [self.states["/running"]])
  509. _creating_button_0.setAction(self._creating_button_0_exec)
  510. _creating_button_0.setTrigger(Event("button_created", None))
  511. self.states["/creating_button"].addTransition(_creating_button_0)
  512. # transition /running
  513. _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
  514. _running_0.setAction(self._running_0_exec)
  515. _running_0.setTrigger(Event("mouse_click", self.getInPortName("button_ui")))
  516. _running_0.setGuard(self._running_0_guard)
  517. self.states["/running"].addTransition(_running_0)
  518. def _creating_button_enter(self):
  519. self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, self.event_name, self.inports['button_ui']]))
  520. def _creating_button_0_exec(self, parameters):
  521. button_id = parameters[0]
  522. self.button_id = button_id
  523. self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [button_id, ui.EVENTS.MOUSE_CLICK, "mouse_click", self.inports['button_ui']]))
  524. def _running_0_exec(self, parameters):
  525. x = parameters[0]
  526. y = parameters[1]
  527. button = parameters[2]
  528. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("button_pressed", None, [self.event_name])]))
  529. def _running_0_guard(self, parameters):
  530. x = parameters[0]
  531. y = parameters[1]
  532. button = parameters[2]
  533. return button == ui.MOUSE_BUTTONS.LEFT
  534. def initializeStatechart(self):
  535. # enter default state
  536. self.default_targets = self.states["/creating_button"].getEffectiveTargetStates()
  537. RuntimeClassBase.initializeStatechart(self)
  538. class Button(ClassBase):
  539. def __init__(self, name):
  540. ClassBase.__init__(self, name)
  541. self.input = self.addInPort("input")
  542. self.glob_outputs["ui"] = self.addOutPort("ui")
  543. self.outputs["parent"] = self.addOutPort("parent")
  544. self.button_ui = self.addInPort("button_ui")
  545. def constructObject(self, id, start_port_id, parameters):
  546. new_instance = ButtonInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3])
  547. return new_instance
  548. class BallInstance(RuntimeClassBase):
  549. def __init__(self, atomdevs, id, start_port_id, canvas_id, x, y):
  550. RuntimeClassBase.__init__(self, atomdevs, id)
  551. self.associations = {}
  552. self.associations["parent"] = Association("Field", 1, 1)
  553. self.semantics.big_step_maximality = StatechartSemantics.TakeMany
  554. self.semantics.internal_event_lifeline = StatechartSemantics.Queue
  555. self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
  556. self.semantics.priority = StatechartSemantics.SourceParent
  557. self.semantics.concurrency = StatechartSemantics.Single
  558. # build Statechart structure
  559. self.build_statechart_structure()
  560. # user defined attributes
  561. self.canvas_id = None
  562. self.pos = None
  563. # call user defined constructor
  564. BallInstance.user_defined_constructor(self, canvas_id, x, y)
  565. port_name = addInputPort("ui", start_port_id, True)
  566. atomdevs.state.port_mappings[port_name] = id
  567. port_name = addInputPort("<narrow_cast>", start_port_id)
  568. atomdevs.state.port_mappings[port_name] = id
  569. port_name = addInputPort("ball_ui", start_port_id)
  570. atomdevs.state.port_mappings[port_name] = id
  571. self.inports["ball_ui"] = port_name
  572. def user_defined_constructor(self, canvas_id, x, y):
  573. self.canvas_id = canvas_id;
  574. self.r = 20.0;
  575. self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
  576. self.pos = {'x': x, 'y': y};
  577. self.smooth = 0.6; # value between 0 and 1
  578. def user_defined_destructor(self):
  579. pass
  580. # builds Statechart structure
  581. def build_statechart_structure(self):
  582. # state <root>
  583. self.states[""] = State(0, "", self)
  584. # state /main_behaviour
  585. self.states["/main_behaviour"] = State(1, "/main_behaviour", self)
  586. # state /main_behaviour/initializing
  587. self.states["/main_behaviour/initializing"] = State(2, "/main_behaviour/initializing", self)
  588. # state /main_behaviour/creating_circle
  589. self.states["/main_behaviour/creating_circle"] = State(3, "/main_behaviour/creating_circle", self)
  590. self.states["/main_behaviour/creating_circle"].setEnter(self._main_behaviour_creating_circle_enter)
  591. # state /main_behaviour/bouncing
  592. self.states["/main_behaviour/bouncing"] = State(4, "/main_behaviour/bouncing", self)
  593. self.states["/main_behaviour/bouncing"].setEnter(self._main_behaviour_bouncing_enter)
  594. self.states["/main_behaviour/bouncing"].setExit(self._main_behaviour_bouncing_exit)
  595. # state /main_behaviour/dragging
  596. self.states["/main_behaviour/dragging"] = State(5, "/main_behaviour/dragging", self)
  597. # state /main_behaviour/selected
  598. self.states["/main_behaviour/selected"] = State(6, "/main_behaviour/selected", self)
  599. # state /deleted
  600. self.states["/deleted"] = State(7, "/deleted", self)
  601. # add children
  602. self.states[""].addChild(self.states["/main_behaviour"])
  603. self.states[""].addChild(self.states["/deleted"])
  604. self.states["/main_behaviour"].addChild(self.states["/main_behaviour/initializing"])
  605. self.states["/main_behaviour"].addChild(self.states["/main_behaviour/creating_circle"])
  606. self.states["/main_behaviour"].addChild(self.states["/main_behaviour/bouncing"])
  607. self.states["/main_behaviour"].addChild(self.states["/main_behaviour/dragging"])
  608. self.states["/main_behaviour"].addChild(self.states["/main_behaviour/selected"])
  609. self.states[""].fixTree()
  610. self.states[""].default_state = self.states["/main_behaviour"]
  611. self.states["/main_behaviour"].default_state = self.states["/main_behaviour/initializing"]
  612. # transition /main_behaviour/initializing
  613. _main_behaviour_initializing_0 = Transition(self, self.states["/main_behaviour/initializing"], [self.states["/main_behaviour/creating_circle"]])
  614. _main_behaviour_initializing_0.setAction(self._main_behaviour_initializing_0_exec)
  615. _main_behaviour_initializing_0.setTrigger(Event("get_init_params", None))
  616. self.states["/main_behaviour/initializing"].addTransition(_main_behaviour_initializing_0)
  617. # transition /main_behaviour/creating_circle
  618. _main_behaviour_creating_circle_0 = Transition(self, self.states["/main_behaviour/creating_circle"], [self.states["/main_behaviour/bouncing"]])
  619. _main_behaviour_creating_circle_0.setAction(self._main_behaviour_creating_circle_0_exec)
  620. _main_behaviour_creating_circle_0.setTrigger(Event("circle_created", None))
  621. self.states["/main_behaviour/creating_circle"].addTransition(_main_behaviour_creating_circle_0)
  622. # transition /main_behaviour/bouncing
  623. _main_behaviour_bouncing_0 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
  624. _main_behaviour_bouncing_0.setAction(self._main_behaviour_bouncing_0_exec)
  625. _main_behaviour_bouncing_0.setTrigger(Event("_0after"))
  626. self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_0)
  627. _main_behaviour_bouncing_1 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
  628. _main_behaviour_bouncing_1.setAction(self._main_behaviour_bouncing_1_exec)
  629. _main_behaviour_bouncing_1.setTrigger(Event("update_ball_vel", None))
  630. self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_1)
  631. _main_behaviour_bouncing_2 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/selected"]])
  632. _main_behaviour_bouncing_2.setAction(self._main_behaviour_bouncing_2_exec)
  633. _main_behaviour_bouncing_2.setTrigger(Event("mouse_press", self.getInPortName("ball_ui")))
  634. _main_behaviour_bouncing_2.setGuard(self._main_behaviour_bouncing_2_guard)
  635. self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_2)
  636. # transition /main_behaviour/dragging
  637. _main_behaviour_dragging_0 = Transition(self, self.states["/main_behaviour/dragging"], [self.states["/main_behaviour/dragging"]])
  638. _main_behaviour_dragging_0.setAction(self._main_behaviour_dragging_0_exec)
  639. _main_behaviour_dragging_0.setTrigger(Event("mouse_move", self.getInPortName("ball_ui")))
  640. self.states["/main_behaviour/dragging"].addTransition(_main_behaviour_dragging_0)
  641. _main_behaviour_dragging_1 = Transition(self, self.states["/main_behaviour/dragging"], [self.states["/main_behaviour/bouncing"]])
  642. _main_behaviour_dragging_1.setAction(self._main_behaviour_dragging_1_exec)
  643. _main_behaviour_dragging_1.setTrigger(Event("mouse_release", self.getInPortName("ball_ui")))
  644. self.states["/main_behaviour/dragging"].addTransition(_main_behaviour_dragging_1)
  645. # transition /main_behaviour/selected
  646. _main_behaviour_selected_0 = Transition(self, self.states["/main_behaviour/selected"], [self.states["/main_behaviour/dragging"]])
  647. _main_behaviour_selected_0.setAction(self._main_behaviour_selected_0_exec)
  648. _main_behaviour_selected_0.setTrigger(Event("mouse_press", self.getInPortName("ball_ui")))
  649. _main_behaviour_selected_0.setGuard(self._main_behaviour_selected_0_guard)
  650. self.states["/main_behaviour/selected"].addTransition(_main_behaviour_selected_0)
  651. _main_behaviour_selected_1 = Transition(self, self.states["/main_behaviour/selected"], [self.states["/deleted"]])
  652. _main_behaviour_selected_1.setAction(self._main_behaviour_selected_1_exec)
  653. _main_behaviour_selected_1.setTrigger(Event("delete_self", None))
  654. self.states["/main_behaviour/selected"].addTransition(_main_behaviour_selected_1)
  655. def _main_behaviour_creating_circle_enter(self):
  656. self.big_step.outputEvent(Event("create_circle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.r, {'fill':'#000'}, self.inports['ball_ui']]))
  657. def _main_behaviour_bouncing_enter(self):
  658. self.addTimer(0, 0.02)
  659. def _main_behaviour_bouncing_exit(self):
  660. self.removeTimer(0)
  661. def _main_behaviour_initializing_0_exec(self, parameters):
  662. association_name = parameters[0]
  663. self.association_name = association_name
  664. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("init_params", None, [self.association_name, self.r, self.vel, self.pos])]))
  665. def _main_behaviour_creating_circle_0_exec(self, parameters):
  666. canvas_id = parameters[0]
  667. circle_id = parameters[1]
  668. self.circle_id = circle_id
  669. self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_PRESS, 'mouse_press', self.inports['ball_ui']]))
  670. self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['ball_ui']]))
  671. self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_RELEASE, 'mouse_release', self.inports['ball_ui']]))
  672. def _main_behaviour_bouncing_0_exec(self, parameters):
  673. # Invert velocity when colliding with canvas border:
  674. if self.pos['x']-self.r <= 0 or self.pos['x']+self.r >= CANVAS_DIMS[0]:
  675. self.vel['x'] = -self.vel['x'];
  676. if self.pos['y']-self.r <= 0 or self.pos['y']+self.r >= CANVAS_DIMS[1]:
  677. self.vel['y'] = -self.vel['y'];
  678. self.big_step.outputEvent(Event("move_element", self.getOutPortName("ui"), [self.canvas_id, self.circle_id, self.vel['x'], self.vel['y']]))
  679. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("move_ball", None, [self.association_name, self.pos, self.vel])]))
  680. self.pos['x'] += self.vel['x']
  681. self.pos['y'] += self.vel['y']
  682. def _main_behaviour_bouncing_1_exec(self, parameters):
  683. new_vel = parameters[0]
  684. self.vel = new_vel
  685. def _main_behaviour_bouncing_2_exec(self, parameters):
  686. x = parameters[0]
  687. y = parameters[1]
  688. button = parameters[2]
  689. self.big_step.outputEvent(Event("set_element_color", self.getOutPortName("ui"), [self.canvas_id, self.circle_id, '#ff0']))
  690. def _main_behaviour_bouncing_2_guard(self, parameters):
  691. x = parameters[0]
  692. y = parameters[1]
  693. button = parameters[2]
  694. return button == ui.MOUSE_BUTTONS.LEFT
  695. def _main_behaviour_dragging_0_exec(self, parameters):
  696. x = parameters[0]
  697. y = parameters[1]
  698. button = parameters[2]
  699. # Always keep ball within canvas:
  700. x = min(max(0+self.r, x), CANVAS_DIMS[0]-self.r)
  701. y = min(max(0+self.r, y), CANVAS_DIMS[1]-self.r)
  702. dx = x - self.pos['x']
  703. dy = y - self.pos['y']
  704. self.vel = {
  705. 'x': (1-self.smooth)*dx + self.smooth*self.vel['x'],
  706. 'y': (1-self.smooth)*dy + self.smooth*self.vel['y']
  707. }
  708. self.pos = {'x': x, 'y': y}
  709. self.big_step.outputEvent(Event("set_element_pos", self.getOutPortName("ui"), [self.canvas_id, self.circle_id, x-self.r, y-self.r]))
  710. def _main_behaviour_dragging_1_exec(self, parameters):
  711. x = parameters[0]
  712. y = parameters[1]
  713. self.big_step.outputEvent(Event("set_element_color", self.getOutPortName("ui"), [self.canvas_id, self.circle_id, '#f00']))
  714. def _main_behaviour_selected_0_exec(self, parameters):
  715. x = parameters[0]
  716. y = parameters[1]
  717. button = parameters[2]
  718. self.mouse_pos = {'x':x, 'y':y};
  719. def _main_behaviour_selected_0_guard(self, parameters):
  720. x = parameters[0]
  721. y = parameters[1]
  722. button = parameters[2]
  723. return button == ui.MOUSE_BUTTONS.LEFT
  724. def _main_behaviour_selected_1_exec(self, parameters):
  725. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("delete_ball", None, [self.association_name])]))
  726. self.big_step.outputEvent(Event("destroy_element", self.getOutPortName("ui"), [self.canvas_id, self.element_id]))
  727. def initializeStatechart(self):
  728. # enter default state
  729. self.default_targets = self.states["/main_behaviour"].getEffectiveTargetStates()
  730. RuntimeClassBase.initializeStatechart(self)
  731. class Ball(ClassBase):
  732. def __init__(self, name):
  733. ClassBase.__init__(self, name)
  734. self.input = self.addInPort("input")
  735. self.glob_outputs["ui"] = self.addOutPort("ui")
  736. self.outputs["parent"] = self.addOutPort("parent")
  737. self.ball_ui = self.addInPort("ball_ui")
  738. def constructObject(self, id, start_port_id, parameters):
  739. new_instance = BallInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3])
  740. return new_instance
  741. class CollisionPhysicsInstance(RuntimeClassBase):
  742. def __init__(self, atomdevs, id, start_port_id, ball1_id, ball2_id, ball1_info, ball2_info):
  743. RuntimeClassBase.__init__(self, atomdevs, id)
  744. self.associations = {}
  745. self.associations["parent"] = Association("Field", 1, 1)
  746. self.semantics.big_step_maximality = StatechartSemantics.TakeMany
  747. self.semantics.internal_event_lifeline = StatechartSemantics.Queue
  748. self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
  749. self.semantics.priority = StatechartSemantics.SourceParent
  750. self.semantics.concurrency = StatechartSemantics.Single
  751. # build Statechart structure
  752. self.build_statechart_structure()
  753. # user defined attributes
  754. self.ball2_info = None
  755. # call user defined constructor
  756. CollisionPhysicsInstance.user_defined_constructor(self, ball1_id, ball2_id, ball1_info, ball2_info)
  757. port_name = addInputPort("ui", start_port_id, True)
  758. atomdevs.state.port_mappings[port_name] = id
  759. port_name = addInputPort("<narrow_cast>", start_port_id)
  760. atomdevs.state.port_mappings[port_name] = id
  761. port_name = addInputPort("physics_ui", start_port_id)
  762. atomdevs.state.port_mappings[port_name] = id
  763. self.inports["physics_ui"] = port_name
  764. def user_defined_constructor(self, ball1_id, ball2_id, ball1_info, ball2_info):
  765. self.ball1_id = ball1_id
  766. self.ball2_id = ball2_id
  767. self.ball1_info = ball1_info
  768. self.ball2_info = ball2_info
  769. def user_defined_destructor(self):
  770. pass
  771. # user defined method
  772. def resolve_velocity(self, vel, normal):
  773. # Resolve the velocity into normal and tangential components.
  774. normal_velocity = np.dot(vel, normal) * normal
  775. tangential_velocity = vel - normal_velocity
  776. return normal_velocity, tangential_velocity
  777. # user defined method
  778. def handle_collision(self):
  779. pos1 = np.array([self.ball1_info['pos']['x'], self.ball1_info['pos']['y']])
  780. vel1 = np.array([self.ball1_info['vel']['x'], self.ball1_info['vel']['y']])
  781. r1 = self.ball1_info['r']
  782. pos2 = np.array([self.ball2_info['pos']['x'], self.ball2_info['pos']['y']])
  783. vel2 = np.array([self.ball2_info['vel']['x'], self.ball2_info['vel']['y']])
  784. r2 = self.ball2_info['r']
  785. # Calculate the normal vector from the center of ball1 to the center of ball2
  786. normal = pos2 - pos1
  787. normal = normal / np.linalg.norm(normal) # Normalize the normal vector
  788. # Calculate the relative velocity
  789. relative_velocity = vel1 - vel2
  790. # Calculate the velocities in the normal direction
  791. vel1_normal, vel1_tangential = self.resolve_velocity(vel1, normal)
  792. vel2_normal, vel2_tangential = self.resolve_velocity(vel2, normal)
  793. # Calculate new normal velocities after collision (1D elastic collision formula)
  794. vel1_normal_new = ((r1 - r2) * vel1_normal + 2 * r2 * vel2_normal) / (r1 + r2)
  795. vel2_normal_new = ((r2 - r1) * vel2_normal + 2 * r1 * vel1_normal) / (r1 + r2)
  796. # Combine the new normal and original tangential components
  797. vel1_new = vel1_normal_new + vel1_tangential
  798. vel2_new = vel2_normal_new + vel2_tangential
  799. # Update the velocities in the balls
  800. self.ball1_info['vel'] = {'x': vel1_new[0], 'y': vel1_new[1]}
  801. self.ball2_info['vel'] = {'x': vel2_new[0], 'y': vel2_new[1]}
  802. # builds Statechart structure
  803. def build_statechart_structure(self):
  804. # state <root>
  805. self.states[""] = State(0, "", self)
  806. # state /creating
  807. self.states["/creating"] = State(1, "/creating", self)
  808. self.states["/creating"].setEnter(self._creating_enter)
  809. # state /running
  810. self.states["/running"] = State(2, "/running", self)
  811. # state /delete
  812. self.states["/delete"] = State(3, "/delete", self)
  813. # add children
  814. self.states[""].addChild(self.states["/creating"])
  815. self.states[""].addChild(self.states["/running"])
  816. self.states[""].addChild(self.states["/delete"])
  817. self.states[""].fixTree()
  818. self.states[""].default_state = self.states["/creating"]
  819. # transition /creating
  820. _creating_0 = Transition(self, self.states["/creating"], [self.states["/running"]])
  821. _creating_0.setAction(self._creating_0_exec)
  822. _creating_0.setTrigger(Event("set_association_name", None))
  823. self.states["/creating"].addTransition(_creating_0)
  824. # transition /running
  825. _running_0 = Transition(self, self.states["/running"], [self.states["/delete"]])
  826. _running_0.setAction(self._running_0_exec)
  827. _running_0.setTrigger(None)
  828. self.states["/running"].addTransition(_running_0)
  829. def _creating_enter(self):
  830. self.handle_collision()
  831. def _creating_0_exec(self, parameters):
  832. association_name = parameters[0]
  833. self.association_name = association_name
  834. def _running_0_exec(self, parameters):
  835. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("update_vel", None, [self.ball1_id, self.ball2_id, self.ball1_info['vel'], self.ball2_info['vel']])]))
  836. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("delete_physics", None, [self.association_name])]))
  837. def initializeStatechart(self):
  838. # enter default state
  839. self.default_targets = self.states["/creating"].getEffectiveTargetStates()
  840. RuntimeClassBase.initializeStatechart(self)
  841. class CollisionPhysics(ClassBase):
  842. def __init__(self, name):
  843. ClassBase.__init__(self, name)
  844. self.input = self.addInPort("input")
  845. self.glob_outputs["ui"] = self.addOutPort("ui")
  846. self.outputs["parent"] = self.addOutPort("parent")
  847. self.physics_ui = self.addInPort("physics_ui")
  848. def constructObject(self, id, start_port_id, parameters):
  849. new_instance = CollisionPhysicsInstance(self, id, start_port_id, parameters[1], parameters[2], parameters[3], parameters[4])
  850. return new_instance
  851. class Dummy(ObjectManagerState):
  852. def __init__(self):
  853. ObjectManagerState.__init__(self)
  854. def instantiate(self, class_name, construct_params):
  855. instance = {}
  856. instance["name"] = class_name
  857. if class_name == "MainApp":
  858. self.narrow_cast_id = self.narrow_cast_id + 0
  859. instance["associations"] = {}
  860. instance["associations"]["fields"] = Association("Field", 0, -1)
  861. elif class_name == "Field":
  862. self.narrow_cast_id = self.narrow_cast_id + 1
  863. instance["associations"] = {}
  864. instance["associations"]["balls"] = Association("Ball", 0, -1)
  865. instance["associations"]["buttons"] = Association("Button", 0, -1)
  866. instance["associations"]["collisions"] = Association("CollisionPhysics", 0, -1)
  867. instance["associations"]["parent"] = Association("MainApp", 1, 1)
  868. elif class_name == "Button":
  869. self.narrow_cast_id = self.narrow_cast_id + 1
  870. instance["associations"] = {}
  871. instance["associations"]["parent"] = Association("Field", 1, 1)
  872. elif class_name == "Ball":
  873. self.narrow_cast_id = self.narrow_cast_id + 1
  874. instance["associations"] = {}
  875. instance["associations"]["parent"] = Association("Field", 1, 1)
  876. elif class_name == "CollisionPhysics":
  877. self.narrow_cast_id = self.narrow_cast_id + 1
  878. instance["associations"] = {}
  879. instance["associations"]["parent"] = Association("Field", 1, 1)
  880. else:
  881. raise Exception("Cannot instantiate class " + class_name)
  882. return instance
  883. class ObjectManager(ObjectManagerBase):
  884. def __init__(self, name):
  885. ObjectManagerBase.__init__(self, name)
  886. self.state = Dummy()
  887. self.input = self.addInPort("input")
  888. self.output["MainApp"] = self.addOutPort()
  889. self.output["Field"] = self.addOutPort()
  890. self.output["Button"] = self.addOutPort()
  891. self.output["Ball"] = self.addOutPort()
  892. self.output["CollisionPhysics"] = self.addOutPort()
  893. self.state.createInstance("MainApp", [])
  894. self.state.to_send.append((("MainApp", 0), ("MainApp", 0), Event("start_instance", None, ["MainApp[0]"])))
  895. class Controller(CoupledDEVS):
  896. def __init__(self, name):
  897. CoupledDEVS.__init__(self, name)
  898. self.in_ui = self.addInPort("ui")
  899. self.out_ui = self.addOutPort("ui")
  900. self.objectmanager = self.addSubModel(ObjectManager("ObjectManager"))
  901. self.atomics = []
  902. self.atomics.append(self.addSubModel(MainApp("MainApp")))
  903. self.atomics.append(self.addSubModel(Field("Field")))
  904. self.atomics.append(self.addSubModel(Button("Button")))
  905. self.atomics.append(self.addSubModel(Ball("Ball")))
  906. self.atomics.append(self.addSubModel(CollisionPhysics("CollisionPhysics")))
  907. self.connectPorts(self.atomics[0].obj_manager_out, self.objectmanager.input)
  908. self.connectPorts(self.objectmanager.output["MainApp"], self.atomics[0].obj_manager_in)
  909. self.connectPorts(self.atomics[0].outputs["fields"], self.atomics[1].input)
  910. self.connectPorts(self.atomics[1].obj_manager_out, self.objectmanager.input)
  911. self.connectPorts(self.objectmanager.output["Field"], self.atomics[1].obj_manager_in)
  912. self.connectPorts(self.atomics[1].outputs["balls"], self.atomics[3].input)
  913. self.connectPorts(self.atomics[1].outputs["buttons"], self.atomics[2].input)
  914. self.connectPorts(self.atomics[1].outputs["collisions"], self.atomics[4].input)
  915. self.connectPorts(self.atomics[1].outputs["parent"], self.atomics[0].input)
  916. self.connectPorts(self.atomics[2].obj_manager_out, self.objectmanager.input)
  917. self.connectPorts(self.objectmanager.output["Button"], self.atomics[2].obj_manager_in)
  918. self.connectPorts(self.atomics[2].outputs["parent"], self.atomics[1].input)
  919. self.connectPorts(self.atomics[3].obj_manager_out, self.objectmanager.input)
  920. self.connectPorts(self.objectmanager.output["Ball"], self.atomics[3].obj_manager_in)
  921. self.connectPorts(self.atomics[3].outputs["parent"], self.atomics[1].input)
  922. self.connectPorts(self.atomics[4].obj_manager_out, self.objectmanager.input)
  923. self.connectPorts(self.objectmanager.output["CollisionPhysics"], self.atomics[4].obj_manager_in)
  924. self.connectPorts(self.atomics[4].outputs["parent"], self.atomics[1].input)
  925. self.connectPorts(self.atomics[0].glob_outputs["ui"], self.out_ui)
  926. self.connectPorts(self.in_ui, self.atomics[0].input)
  927. self.connectPorts(self.atomics[1].glob_outputs["ui"], self.out_ui)
  928. self.connectPorts(self.in_ui, self.atomics[1].input)
  929. self.connectPorts(self.atomics[2].glob_outputs["ui"], self.out_ui)
  930. self.connectPorts(self.in_ui, self.atomics[2].input)
  931. self.connectPorts(self.atomics[3].glob_outputs["ui"], self.out_ui)
  932. self.connectPorts(self.in_ui, self.atomics[3].input)
  933. self.connectPorts(self.atomics[4].glob_outputs["ui"], self.out_ui)
  934. self.connectPorts(self.in_ui, self.atomics[4].input)