target.py 62 KB

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