bouncing_balls.js.xml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. <?xml version="1.0" ?>
  2. <diagram name="Bouncing_Balls" author="Simon Van Mierlo+Joeri Exelmans+Raphael Mannadiar">
  3. <description>
  4. Tkinter frame with bouncing balls in it.
  5. </description>
  6. <inport name="field_ui"/>
  7. <inport name="ball_ui"/>
  8. <inport name="input"/>
  9. <class name="Button">
  10. <relationships>
  11. <association name="parent" class="Field" min="1" max="1"/>
  12. </relationships>
  13. <method name="Button">
  14. <parameter name="parent" type="Field"/>
  15. <parameter name="event_name" type="str"/>
  16. <parameter name="button_text" type="str"/>
  17. <body>
  18. <![CDATA[
  19. this.event_name = event_name;
  20. var button = ui.append_button(parent.field_window, event_name);
  21. ui.bind_event(button.element, ui.EVENTS.MOUSE_CLICK, this.controller, 'mouse_click');
  22. ]]>
  23. </body>
  24. </method>
  25. <scxml initial="initializing">
  26. <state id="initializing">
  27. <transition target="../running">
  28. <raise event="button_created" scope="narrow" target="'parent'">
  29. </raise>
  30. </transition>
  31. </state>
  32. <state id="running">
  33. <transition port="ui" target="." event="mouse_click" cond="button == ui.MOUSE_BUTTONS.LEFT">
  34. <parameter name="x" type="int"/>
  35. <parameter name="y" type="int"/>
  36. <parameter name="button" type="Button"/>
  37. <raise event="button_pressed" scope="narrow" target="'parent'">
  38. <parameter expr="this.event_name"/>
  39. </raise>
  40. </transition>
  41. </state>
  42. </scxml>
  43. </class>
  44. <class name="Field">
  45. <inport name="field_ui"/>
  46. <relationships>
  47. <association name="parent" class="MainApp" min="1" max="1"/>
  48. <association name="buttons" class="Button"/>
  49. <association name="balls" class="Ball"/>
  50. </relationships>
  51. <attribute name="field_window"/>
  52. <attribute name="canvas"/>
  53. <method name="Field">
  54. <body>
  55. <![CDATA[
  56. this.field_window = ui.new_window(400, 450);
  57. this.canvas = ui.append_canvas(this.field_window, 400, 400, {'background':'#eee'});
  58. ui.bind_event(this.field_window, ui.EVENTS.WINDOW_CLOSE, this.controller, 'window_close');
  59. ui.bind_event(this.field_window, ui.EVENTS.KEY_PRESS, this.controller, 'key_press');
  60. ui.bind_event(this.canvas.element, ui.EVENTS.MOUSE_RIGHT_CLICK, this.controller, 'right_click', this.inports['field_ui']);
  61. ui.bind_event(this.canvas.element, ui.EVENTS.MOUSE_MOVE, this.controller, 'mouse_move');
  62. ui.bind_event(this.canvas.element, ui.EVENTS.MOUSE_RELEASE, this.controller, 'mouse_release');
  63. ]]>
  64. </body>
  65. </method>
  66. <method name="~Field">
  67. <body>
  68. <![CDATA[
  69. ui.close_window(this.field_window);
  70. ]]>
  71. </body>
  72. </method>
  73. <scxml initial="root">
  74. <state id="root" initial="waiting">
  75. <state id="waiting">
  76. <transition target="../initializing" event="set_association_name">
  77. <parameter name="association_name" type="str"/>
  78. <script>
  79. <![CDATA[
  80. this.association_name = association_name;
  81. ]]>
  82. </script>
  83. </transition>
  84. </state>
  85. <state id="packing">
  86. <transition target="../running" event="button_created">
  87. </transition>
  88. </state>
  89. <state id="deleting">
  90. <transition after="0.05" target="../deleted">
  91. <raise event="delete_field" scope="narrow" target="'parent'">
  92. <parameter expr="this.association_name"/>
  93. </raise>
  94. </transition>
  95. </state>
  96. <state id="creating">
  97. <transition target="../packing" event="instance_created">
  98. <parameter name="association_name" type="string"/>
  99. <raise event="start_instance" scope="cd">
  100. <parameter expr="association_name"/>
  101. </raise>
  102. </transition>
  103. </state>
  104. <state id="initializing">
  105. <transition target="../creating">
  106. <raise event="create_instance" scope="cd">
  107. <parameter expr="'buttons'"/>
  108. <parameter expr="'Button'"/>
  109. <parameter expr="this"/>
  110. <parameter expr="'create_new_field'"/>
  111. <parameter expr="'Spawn New Window'"/>
  112. </raise>
  113. </transition>
  114. </state>
  115. <state id="deleted">
  116. </state>
  117. <parallel id="running">
  118. <transition port="ui" target="../deleting" event="window_close" cond="window == this.field_window || window == ui.window">
  119. <parameter name="window" type="Window"/>
  120. <raise event="delete_instance" scope="cd">
  121. <parameter expr="'buttons'"/>
  122. </raise>
  123. <raise event="delete_self" scope="narrow" target="'balls'">
  124. </raise>
  125. </transition>
  126. <state id="main_behaviour" initial="running">
  127. <state id="running">
  128. <transition port="field_ui" target="../creating" event="right_click">
  129. <parameter name="x" type="int"/>
  130. <parameter name="y" type="int"/>
  131. <parameter name="button" type="Button"/>
  132. <raise event="create_instance" scope="cd">
  133. <parameter expr="'balls'"/>
  134. <parameter expr="'Ball'"/>
  135. <parameter expr="this.canvas"/>
  136. <parameter expr="x"/>
  137. <parameter expr="y"/>
  138. <parameter expr="this.field_window"/>
  139. </raise>
  140. </transition>
  141. </state>
  142. <state id="creating">
  143. <transition target="../running" event="instance_created">
  144. <parameter name="association_name" type="string"/>
  145. <raise event="set_association_name" scope="narrow" target="association_name">
  146. <parameter expr="association_name"/>
  147. </raise>
  148. <raise event="start_instance" scope="cd">
  149. <parameter expr="association_name"/>
  150. </raise>
  151. </transition>
  152. </state>
  153. </state>
  154. <state id="deleting_behaviour" initial="running">
  155. <state id="running">
  156. <transition target="." event="delete_ball">
  157. <parameter name="association_name" type="str"/>
  158. <raise event="delete_instance" scope="cd">
  159. <parameter expr="association_name"/>
  160. </raise>
  161. </transition>
  162. </state>
  163. </state>
  164. <state id="child_behaviour" initial="listening">
  165. <state id="listening">
  166. <transition target="." event="button_pressed">
  167. <parameter name="event_name" type="str"/>
  168. <raise event="button_pressed" scope="narrow" target="'parent'">
  169. <parameter expr="event_name"/>
  170. </raise>
  171. </transition>
  172. </state>
  173. </state>
  174. </parallel>
  175. </state>
  176. </scxml>
  177. </class>
  178. <class name="MainApp" default="True">
  179. <relationships>
  180. <association name="fields" class="Field"/>
  181. </relationships>
  182. <method name="MainApp">
  183. <body>
  184. <![CDATA[
  185. this.nr_of_fields = 0;
  186. ui.bind_event(ui.window, ui.EVENTS.WINDOW_CLOSE, this.controller, 'window_close');
  187. ]]>
  188. </body>
  189. </method>
  190. <scxml initial="running">
  191. <state id="running" initial="root">
  192. <state id="stopped">
  193. </state>
  194. <parallel id="root">
  195. <state id="main_behaviour" initial="initializing">
  196. <state id="initializing">
  197. <transition target="../running">
  198. <raise event="create_field">
  199. </raise>
  200. </transition>
  201. </state>
  202. <state id="running">
  203. <transition target="." event="button_pressed" cond="event_name == 'create_new_field'">
  204. <parameter name="event_name" type="str"/>
  205. <raise event="create_field">
  206. </raise>
  207. </transition>
  208. </state>
  209. </state>
  210. <state id="cd_behaviour" initial="waiting">
  211. <state id="creating">
  212. <transition target="../waiting" event="instance_created">
  213. <parameter name="association_name" type="string"/>
  214. <raise event="start_instance" scope="cd">
  215. <parameter expr="association_name"/>
  216. </raise>
  217. <raise event="set_association_name" scope="narrow" target="association_name">
  218. <parameter expr="association_name"/>
  219. </raise>
  220. <script>
  221. <![CDATA[
  222. this.nr_of_fields += 1;
  223. ]]>
  224. </script>
  225. </transition>
  226. </state>
  227. <state id="waiting">
  228. <transition target="../creating" event="create_field">
  229. <raise event="create_instance" scope="cd">
  230. <parameter expr="'fields'"/>
  231. </raise>
  232. </transition>
  233. <transition target="../check_nr_of_fields" event="delete_field">
  234. <parameter name="association_name" type="str"/>
  235. <raise event="delete_instance" scope="cd">
  236. <parameter expr="association_name"/>
  237. </raise>
  238. <script>
  239. <![CDATA[
  240. this.nr_of_fields -= 1;
  241. ]]>
  242. </script>
  243. </transition>
  244. </state>
  245. <state id="check_nr_of_fields">
  246. <transition target="../waiting" cond="this.nr_of_fields != 0">
  247. </transition>
  248. <transition target="../../../stopped" cond="this.nr_of_fields == 0">
  249. <script>
  250. <![CDATA[
  251. ui.close_window(ui.window);
  252. ]]>
  253. </script>
  254. </transition>
  255. </state>
  256. </state>
  257. </parallel>
  258. </state>
  259. </scxml>
  260. </class>
  261. <class name="Ball">
  262. <inport name="ball_ui"/>
  263. <relationships>
  264. <association name="parent" class="Field" min="1" max="1"/>
  265. </relationships>
  266. <attribute name="field_window"/>
  267. <attribute name="canvas"/>
  268. <attribute name="element"/>
  269. <method name="Ball">
  270. <parameter name="canvas"/>
  271. <parameter name="x"/>
  272. <parameter name="y"/>
  273. <parameter name="field_window"/>
  274. <body>
  275. <![CDATA[
  276. this.canvas = canvas;
  277. this.field_window = field_window;
  278. this.r = 20.0;
  279. this.vel = {'x':utils.random() * 2.0 - 1.0, 'y':utils.random() * 2.0 - 1.0};
  280. this.mouse_pos = {'':''};
  281. this.smooth = 0.4;
  282. var circle = this.canvas.add_circle(x, y, this.r, {'fill':'#000'});
  283. ui.bind_event(circle, ui.EVENTS.MOUSE_PRESS, this.controller, 'mouse_press', this.inports['ball_ui']);
  284. ui.bind_event(circle, ui.EVENTS.MOUSE_RIGHT_CLICK, this.controller, 'right_click');
  285. this.element = circle;
  286. ]]>
  287. </body>
  288. </method>
  289. <method name="~Ball">
  290. <body>
  291. <![CDATA[
  292. this.canvas.remove_element(this.element);
  293. ]]>
  294. </body>
  295. </method>
  296. <scxml initial="main_behaviour">
  297. <state id="main_behaviour" initial="initializing">
  298. <transition target="../deleted" event="delete_self">
  299. <raise event="delete_ball" scope="narrow" target="'parent'">
  300. <parameter expr="this.association_name"/>
  301. </raise>
  302. </transition>
  303. <state id="dragging">
  304. <transition port="ui" target="../bouncing" event="mouse_release">
  305. <parameter name="x" type="int"/>
  306. <parameter name="y" type="int"/>
  307. <script>
  308. <![CDATA[
  309. this.element.set_color('#f00');
  310. ]]>
  311. </script>
  312. </transition>
  313. <transition port="ui" target="." event="mouse_move">
  314. <parameter name="x" type="int"/>
  315. <parameter name="y" type="int"/>
  316. <parameter name="button" type="Button"/>
  317. <script>
  318. <![CDATA[
  319. var dx = x - this.mouse_pos['x'];
  320. var dy = y - this.mouse_pos['y'];
  321. this.element.move(dx, dy);
  322. var pos = this.element.get_position();
  323. if(pos.x - this.r <= 0) {
  324. pos.x = this.r + 1;
  325. } else {
  326. if(pos.x + this.r >= this.canvas.width) {
  327. pos.x = this.canvas.width - this.r - 1;
  328. }
  329. }
  330. if(pos.y - this.r <= 0) {
  331. pos.y = this.r + 1;
  332. } else {
  333. if(pos.y + this.r >= this.canvas.height) {
  334. pos.y = this.canvas.height - this.r - 1;
  335. }
  336. }
  337. this.element.set_position(pos.x, pos.y);
  338. this.mouse_pos = {'x':x, 'y':y};
  339. this.vel = {'x':(1 - this.smooth) * dx + this.smooth * this.vel['x'], 'y':(1 - this.smooth) * dy + this.smooth * this.vel['y']};
  340. ]]>
  341. </script>
  342. </transition>
  343. </state>
  344. <state id="selected">
  345. <transition port="ball_ui" target="../dragging" event="mouse_press" cond="button == ui.MOUSE_BUTTONS.LEFT">
  346. <parameter name="x" type="int"/>
  347. <parameter name="y" type="int"/>
  348. <parameter name="button" type="Button"/>
  349. <script>
  350. <![CDATA[
  351. this.mouse_pos = {'x':x, 'y':y};
  352. ]]>
  353. </script>
  354. </transition>
  355. <transition port="ui" target="." event="key_press" cond="key == ui.KEYCODES.DELETE &amp;&amp; active_window == this.field_window">
  356. <parameter name="key" type="Key"/>
  357. <parameter name="active_window" type="Window"/>
  358. <raise event="delete_self" scope="local">
  359. </raise>
  360. </transition>
  361. </state>
  362. <state id="initializing">
  363. <transition target="../bouncing" event="set_association_name">
  364. <parameter name="association_name" type="str"/>
  365. <script>
  366. <![CDATA[
  367. this.association_name = association_name;
  368. ]]>
  369. </script>
  370. </transition>
  371. </state>
  372. <state id="bouncing">
  373. <transition after="0.01" target=".">
  374. <script>
  375. <![CDATA[
  376. var pos = this.element.get_position();
  377. if(pos.x - this.r <= 0 || pos.x + this.r >= this.canvas.width) {
  378. this.vel['x'] = -this.vel['x'];
  379. }
  380. if(pos.y - this.r <= 0 || pos.y + this.r >= this.canvas.height) {
  381. this.vel['y'] = -this.vel['y'];
  382. }
  383. this.element.move(this.vel['x'], this.vel['y']);
  384. ]]>
  385. </script>
  386. </transition>
  387. <transition port="ball_ui" target="../selected" event="mouse_press" cond="button == ui.MOUSE_BUTTONS.LEFT">
  388. <parameter name="x" type="int"/>
  389. <parameter name="y" type="int"/>
  390. <parameter name="button" type="Button"/>
  391. <script>
  392. <![CDATA[
  393. this.element.set_color('#ff0');
  394. ]]>
  395. </script>
  396. </transition>
  397. </state>
  398. </state>
  399. <state id="deleted">
  400. </state>
  401. </scxml>
  402. </class>
  403. </diagram>