target.py 64 KB

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