reflexion 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. checksums.yaml +5 -5
  2. data/.doc/ext/reflex/application.cpp +9 -5
  3. data/.doc/ext/reflex/capture_event.cpp +0 -4
  4. data/.doc/ext/reflex/contact_event.cpp +17 -10
  5. data/.doc/ext/reflex/draw_event.cpp +1 -5
  6. data/.doc/ext/reflex/ellipse_shape.cpp +51 -24
  7. data/.doc/ext/reflex/event.cpp +0 -4
  8. data/.doc/ext/reflex/filter.cpp +81 -0
  9. data/.doc/ext/reflex/focus_event.cpp +9 -13
  10. data/.doc/ext/reflex/frame_event.cpp +40 -6
  11. data/.doc/ext/reflex/image_view.cpp +1 -10
  12. data/.doc/ext/reflex/key_event.cpp +2 -6
  13. data/.doc/ext/reflex/line_shape.cpp +99 -0
  14. data/.doc/ext/reflex/motion_event.cpp +75 -0
  15. data/.doc/ext/reflex/native.cpp +18 -18
  16. data/.doc/ext/reflex/pointer_event.cpp +5 -11
  17. data/.doc/ext/reflex/polygon_shape.cpp +65 -0
  18. data/.doc/ext/reflex/rect_shape.cpp +102 -23
  19. data/.doc/ext/reflex/reflex.cpp +21 -2
  20. data/.doc/ext/reflex/scroll_event.cpp +0 -6
  21. data/.doc/ext/reflex/selector.cpp +43 -15
  22. data/.doc/ext/reflex/shape.cpp +211 -0
  23. data/.doc/ext/reflex/style.cpp +359 -185
  24. data/.doc/ext/reflex/style_length.cpp +163 -35
  25. data/.doc/ext/reflex/timer.cpp +101 -0
  26. data/.doc/ext/reflex/timer_event.cpp +123 -0
  27. data/.doc/ext/reflex/update_event.cpp +11 -6
  28. data/.doc/ext/reflex/view.cpp +548 -144
  29. data/.doc/ext/reflex/wheel_event.cpp +0 -22
  30. data/.doc/ext/reflex/window.cpp +7 -15
  31. data/README.md +1 -1
  32. data/Rakefile +14 -12
  33. data/VERSION +1 -1
  34. data/ext/reflex/application.cpp +10 -5
  35. data/ext/reflex/capture_event.cpp +1 -5
  36. data/ext/reflex/contact_event.cpp +19 -11
  37. data/ext/reflex/defs.h +5 -2
  38. data/ext/reflex/draw_event.cpp +2 -6
  39. data/ext/reflex/ellipse_shape.cpp +56 -25
  40. data/ext/reflex/event.cpp +0 -4
  41. data/ext/reflex/extconf.rb +1 -2
  42. data/ext/reflex/filter.cpp +86 -0
  43. data/ext/reflex/focus_event.cpp +11 -15
  44. data/ext/reflex/frame_event.cpp +46 -7
  45. data/ext/reflex/image_view.cpp +1 -10
  46. data/ext/reflex/key_event.cpp +3 -7
  47. data/ext/reflex/line_shape.cpp +104 -0
  48. data/ext/reflex/motion_event.cpp +79 -0
  49. data/ext/reflex/native.cpp +18 -18
  50. data/ext/reflex/pointer_event.cpp +6 -12
  51. data/ext/reflex/polygon_shape.cpp +68 -0
  52. data/ext/reflex/rect_shape.cpp +113 -24
  53. data/ext/reflex/reflex.cpp +21 -2
  54. data/ext/reflex/scroll_event.cpp +1 -7
  55. data/ext/reflex/selector.cpp +46 -16
  56. data/ext/reflex/selector.h +130 -0
  57. data/ext/reflex/shape.cpp +231 -0
  58. data/ext/reflex/style.cpp +363 -192
  59. data/ext/reflex/style_length.cpp +164 -37
  60. data/ext/reflex/timer.cpp +108 -0
  61. data/ext/reflex/timer_event.cpp +133 -0
  62. data/ext/reflex/update_event.cpp +13 -7
  63. data/ext/reflex/view.cpp +594 -150
  64. data/ext/reflex/wheel_event.cpp +1 -25
  65. data/ext/reflex/window.cpp +7 -15
  66. data/include/reflex/application.h +2 -0
  67. data/include/reflex/debug.h +22 -0
  68. data/include/reflex/defs.h +45 -0
  69. data/include/reflex/event.h +60 -16
  70. data/include/reflex/exception.h +9 -0
  71. data/include/reflex/filter.h +56 -0
  72. data/include/reflex/image_view.h +1 -1
  73. data/include/reflex/ruby/application.h +17 -9
  74. data/include/reflex/ruby/event.h +22 -0
  75. data/include/reflex/ruby/filter.h +69 -0
  76. data/include/reflex/ruby/selector.h +1 -1
  77. data/include/reflex/ruby/shape.h +140 -0
  78. data/include/reflex/ruby/style.h +1 -1
  79. data/include/reflex/ruby/timer.h +69 -0
  80. data/include/reflex/ruby/view.h +43 -76
  81. data/include/reflex/ruby/window.h +17 -32
  82. data/include/reflex/ruby.h +6 -4
  83. data/include/reflex/selector.h +54 -2
  84. data/include/reflex/shape.h +211 -0
  85. data/include/reflex/style.h +111 -77
  86. data/include/reflex/timer.h +73 -0
  87. data/include/reflex/view.h +181 -59
  88. data/include/reflex/window.h +4 -3
  89. data/include/reflex.h +5 -4
  90. data/lib/reflex/application.rb +6 -3
  91. data/lib/reflex/button.rb +2 -2
  92. data/lib/reflex/capture_event.rb +7 -6
  93. data/lib/reflex/contact_event.rb +10 -12
  94. data/lib/reflex/draw_event.rb +6 -1
  95. data/lib/reflex/ellipse_shape.rb +27 -0
  96. data/lib/reflex/filter.rb +18 -0
  97. data/lib/reflex/fixture.rb +4 -0
  98. data/lib/reflex/focus_event.rb +10 -12
  99. data/lib/reflex/frame_event.rb +1 -1
  100. data/lib/reflex/helper.rb +17 -29
  101. data/lib/reflex/key_event.rb +13 -11
  102. data/lib/reflex/line_shape.rb +18 -0
  103. data/lib/reflex/{texture.rb → matrix.rb} +2 -2
  104. data/lib/reflex/module.rb +4 -19
  105. data/lib/reflex/pointer_event.rb +26 -37
  106. data/lib/reflex/polygon.rb +14 -0
  107. data/lib/reflex/polygon_shape.rb +23 -0
  108. data/lib/reflex/polyline.rb +13 -0
  109. data/lib/reflex/rect_shape.rb +20 -0
  110. data/lib/reflex/reflex.rb +1 -3
  111. data/lib/reflex/scroll_event.rb +1 -1
  112. data/lib/reflex/selector.rb +2 -2
  113. data/lib/reflex/shape.rb +62 -0
  114. data/lib/reflex/style.rb +78 -11
  115. data/lib/reflex/style_length.rb +0 -11
  116. data/lib/reflex/text_view.rb +7 -24
  117. data/lib/reflex/timer.rb +30 -0
  118. data/lib/reflex/timer_event.rb +29 -0
  119. data/lib/reflex/update_event.rb +1 -1
  120. data/lib/reflex/view.rb +127 -32
  121. data/lib/reflex/wheel_event.rb +9 -1
  122. data/lib/reflex/window.rb +29 -9
  123. data/lib/reflex.rb +11 -5
  124. data/lib/reflexion.rb +23 -7
  125. data/reflex.gemspec +8 -10
  126. data/samples/bats.rb +4 -4
  127. data/samples/fans.rb +1 -1
  128. data/samples/fps.rb +5 -3
  129. data/samples/hello.rb +4 -6
  130. data/samples/image.rb +5 -4
  131. data/samples/ios/hello/hello.xcodeproj/project.pbxproj +0 -2
  132. data/samples/layout.rb +16 -7
  133. data/samples/model.rb +10 -7
  134. data/samples/physics.rb +22 -20
  135. data/samples/reflexion/breakout.rb +4 -5
  136. data/samples/reflexion/hello.rb +2 -2
  137. data/samples/reflexion/jump_action.rb +191 -0
  138. data/samples/reflexion/noise.rb +23 -0
  139. data/samples/reflexion/paint.rb +7 -6
  140. data/samples/reflexion/physics.rb +15 -8
  141. data/samples/reflexion/pulse.rb +24 -10
  142. data/samples/shader.rb +8 -6
  143. data/samples/shapes.rb +63 -14
  144. data/samples/tree.rb +9 -10
  145. data/samples/views.rb +3 -3
  146. data/samples/visuals.rb +2 -5
  147. data/src/body.cpp +146 -345
  148. data/src/body.h +91 -0
  149. data/src/event.cpp +66 -16
  150. data/src/exception.cpp +13 -3
  151. data/src/filter.cpp +76 -0
  152. data/src/fixture.cpp +164 -39
  153. data/src/fixture.h +85 -0
  154. data/src/image_view.cpp +4 -4
  155. data/src/ios/app_delegate.h +5 -10
  156. data/src/ios/app_delegate.mm +79 -41
  157. data/src/ios/application.h +32 -0
  158. data/src/ios/application.mm +35 -25
  159. data/src/ios/event.mm +8 -4
  160. data/src/ios/reflex.mm +0 -7
  161. data/src/ios/view_controller.h +33 -0
  162. data/src/ios/view_controller.mm +436 -0
  163. data/src/ios/window.h +40 -0
  164. data/src/ios/window.mm +59 -250
  165. data/src/osx/app_delegate.h +5 -10
  166. data/src/osx/app_delegate.mm +52 -55
  167. data/src/osx/application.h +32 -0
  168. data/src/osx/application.mm +44 -39
  169. data/src/osx/native_window.h +0 -15
  170. data/src/osx/native_window.mm +131 -115
  171. data/src/osx/opengl_view.h +0 -2
  172. data/src/osx/opengl_view.mm +12 -3
  173. data/src/osx/reflex.mm +0 -9
  174. data/src/osx/window.h +42 -0
  175. data/src/osx/window.mm +45 -252
  176. data/src/selector.cpp +232 -7
  177. data/src/selector.h +52 -0
  178. data/src/shape.cpp +1191 -0
  179. data/src/shape.h +61 -0
  180. data/src/style.cpp +571 -374
  181. data/src/style.h +39 -0
  182. data/src/timer.cpp +291 -0
  183. data/src/timer.h +55 -0
  184. data/src/view.cpp +1624 -984
  185. data/src/view.h +56 -0
  186. data/src/win32/window.cpp +3 -4
  187. data/src/window.cpp +275 -20
  188. data/src/window.h +92 -0
  189. data/src/world.cpp +112 -111
  190. data/src/world.h +34 -53
  191. data/task/box2d.rake +31 -10
  192. data/test/test_capture_event.rb +8 -6
  193. data/test/test_pointer_event.rb +85 -0
  194. data/test/test_selector.rb +1 -1
  195. data/test/test_shape.rb +71 -0
  196. data/test/test_style.rb +77 -11
  197. data/test/test_style_length.rb +42 -13
  198. data/test/test_view.rb +138 -14
  199. metadata +109 -210
  200. data/.doc/ext/reflex/arc_shape.cpp +0 -89
  201. data/.doc/ext/reflex/body.cpp +0 -299
  202. data/.doc/ext/reflex/fixture.cpp +0 -101
  203. data/.doc/ext/reflex/shape_view.cpp +0 -153
  204. data/ext/reflex/arc_shape.cpp +0 -94
  205. data/ext/reflex/body.cpp +0 -328
  206. data/ext/reflex/fixture.cpp +0 -108
  207. data/ext/reflex/shape_view.cpp +0 -161
  208. data/include/reflex/bitmap.h +0 -20
  209. data/include/reflex/body.h +0 -128
  210. data/include/reflex/bounds.h +0 -20
  211. data/include/reflex/color.h +0 -20
  212. data/include/reflex/color_space.h +0 -20
  213. data/include/reflex/fixture.h +0 -117
  214. data/include/reflex/font.h +0 -20
  215. data/include/reflex/image.h +0 -20
  216. data/include/reflex/matrix.h +0 -20
  217. data/include/reflex/painter.h +0 -20
  218. data/include/reflex/point.h +0 -24
  219. data/include/reflex/ruby/body.h +0 -41
  220. data/include/reflex/ruby/fixture.h +0 -41
  221. data/include/reflex/ruby/shape_view.h +0 -96
  222. data/include/reflex/shader.h +0 -20
  223. data/include/reflex/shape_view.h +0 -146
  224. data/include/reflex/texture.h +0 -20
  225. data/lib/reflex/body.rb +0 -22
  226. data/lib/reflex/flags.rb +0 -18
  227. data/lib/reflex/shape_view.rb +0 -25
  228. data/src/ios/application_data.h +0 -45
  229. data/src/ios/native_window.h +0 -39
  230. data/src/ios/native_window.mm +0 -224
  231. data/src/ios/opengl_view.h +0 -13
  232. data/src/ios/opengl_view.mm +0 -139
  233. data/src/ios/window_data.h +0 -75
  234. data/src/osx/application_data.h +0 -45
  235. data/src/osx/window_data.h +0 -75
  236. data/src/physics/Box2D/Box2D.h +0 -68
  237. data/src/physics/Box2D/Collision/Shapes/b2ChainShape.cpp +0 -193
  238. data/src/physics/Box2D/Collision/Shapes/b2ChainShape.h +0 -105
  239. data/src/physics/Box2D/Collision/Shapes/b2CircleShape.cpp +0 -99
  240. data/src/physics/Box2D/Collision/Shapes/b2CircleShape.h +0 -91
  241. data/src/physics/Box2D/Collision/Shapes/b2EdgeShape.cpp +0 -138
  242. data/src/physics/Box2D/Collision/Shapes/b2EdgeShape.h +0 -74
  243. data/src/physics/Box2D/Collision/Shapes/b2PolygonShape.cpp +0 -467
  244. data/src/physics/Box2D/Collision/Shapes/b2PolygonShape.h +0 -101
  245. data/src/physics/Box2D/Collision/Shapes/b2Shape.h +0 -101
  246. data/src/physics/Box2D/Collision/b2BroadPhase.cpp +0 -119
  247. data/src/physics/Box2D/Collision/b2BroadPhase.h +0 -257
  248. data/src/physics/Box2D/Collision/b2CollideCircle.cpp +0 -154
  249. data/src/physics/Box2D/Collision/b2CollideEdge.cpp +0 -698
  250. data/src/physics/Box2D/Collision/b2CollidePolygon.cpp +0 -239
  251. data/src/physics/Box2D/Collision/b2Collision.cpp +0 -252
  252. data/src/physics/Box2D/Collision/b2Collision.h +0 -277
  253. data/src/physics/Box2D/Collision/b2Distance.cpp +0 -603
  254. data/src/physics/Box2D/Collision/b2Distance.h +0 -141
  255. data/src/physics/Box2D/Collision/b2DynamicTree.cpp +0 -778
  256. data/src/physics/Box2D/Collision/b2DynamicTree.h +0 -289
  257. data/src/physics/Box2D/Collision/b2TimeOfImpact.cpp +0 -486
  258. data/src/physics/Box2D/Collision/b2TimeOfImpact.h +0 -58
  259. data/src/physics/Box2D/Common/b2BlockAllocator.cpp +0 -215
  260. data/src/physics/Box2D/Common/b2BlockAllocator.h +0 -62
  261. data/src/physics/Box2D/Common/b2Draw.cpp +0 -44
  262. data/src/physics/Box2D/Common/b2Draw.h +0 -86
  263. data/src/physics/Box2D/Common/b2GrowableStack.h +0 -85
  264. data/src/physics/Box2D/Common/b2Math.cpp +0 -94
  265. data/src/physics/Box2D/Common/b2Math.h +0 -720
  266. data/src/physics/Box2D/Common/b2Settings.cpp +0 -44
  267. data/src/physics/Box2D/Common/b2Settings.h +0 -151
  268. data/src/physics/Box2D/Common/b2StackAllocator.cpp +0 -83
  269. data/src/physics/Box2D/Common/b2StackAllocator.h +0 -60
  270. data/src/physics/Box2D/Common/b2Timer.cpp +0 -101
  271. data/src/physics/Box2D/Common/b2Timer.h +0 -50
  272. data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp +0 -53
  273. data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.h +0 -39
  274. data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp +0 -53
  275. data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.h +0 -39
  276. data/src/physics/Box2D/Dynamics/Contacts/b2CircleContact.cpp +0 -52
  277. data/src/physics/Box2D/Dynamics/Contacts/b2CircleContact.h +0 -39
  278. data/src/physics/Box2D/Dynamics/Contacts/b2Contact.cpp +0 -247
  279. data/src/physics/Box2D/Dynamics/Contacts/b2Contact.h +0 -349
  280. data/src/physics/Box2D/Dynamics/Contacts/b2ContactSolver.cpp +0 -838
  281. data/src/physics/Box2D/Dynamics/Contacts/b2ContactSolver.h +0 -95
  282. data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp +0 -49
  283. data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.h +0 -39
  284. data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp +0 -49
  285. data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.h +0 -39
  286. data/src/physics/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp +0 -49
  287. data/src/physics/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h +0 -38
  288. data/src/physics/Box2D/Dynamics/Contacts/b2PolygonContact.cpp +0 -52
  289. data/src/physics/Box2D/Dynamics/Contacts/b2PolygonContact.h +0 -39
  290. data/src/physics/Box2D/Dynamics/Joints/b2DistanceJoint.cpp +0 -260
  291. data/src/physics/Box2D/Dynamics/Joints/b2DistanceJoint.h +0 -169
  292. data/src/physics/Box2D/Dynamics/Joints/b2FrictionJoint.cpp +0 -251
  293. data/src/physics/Box2D/Dynamics/Joints/b2FrictionJoint.h +0 -119
  294. data/src/physics/Box2D/Dynamics/Joints/b2GearJoint.cpp +0 -419
  295. data/src/physics/Box2D/Dynamics/Joints/b2GearJoint.h +0 -125
  296. data/src/physics/Box2D/Dynamics/Joints/b2Joint.cpp +0 -211
  297. data/src/physics/Box2D/Dynamics/Joints/b2Joint.h +0 -226
  298. data/src/physics/Box2D/Dynamics/Joints/b2MotorJoint.cpp +0 -304
  299. data/src/physics/Box2D/Dynamics/Joints/b2MotorJoint.h +0 -133
  300. data/src/physics/Box2D/Dynamics/Joints/b2MouseJoint.cpp +0 -222
  301. data/src/physics/Box2D/Dynamics/Joints/b2MouseJoint.h +0 -129
  302. data/src/physics/Box2D/Dynamics/Joints/b2PrismaticJoint.cpp +0 -629
  303. data/src/physics/Box2D/Dynamics/Joints/b2PrismaticJoint.h +0 -196
  304. data/src/physics/Box2D/Dynamics/Joints/b2PulleyJoint.cpp +0 -348
  305. data/src/physics/Box2D/Dynamics/Joints/b2PulleyJoint.h +0 -152
  306. data/src/physics/Box2D/Dynamics/Joints/b2RevoluteJoint.cpp +0 -502
  307. data/src/physics/Box2D/Dynamics/Joints/b2RevoluteJoint.h +0 -204
  308. data/src/physics/Box2D/Dynamics/Joints/b2RopeJoint.cpp +0 -241
  309. data/src/physics/Box2D/Dynamics/Joints/b2RopeJoint.h +0 -114
  310. data/src/physics/Box2D/Dynamics/Joints/b2WeldJoint.cpp +0 -344
  311. data/src/physics/Box2D/Dynamics/Joints/b2WeldJoint.h +0 -126
  312. data/src/physics/Box2D/Dynamics/Joints/b2WheelJoint.cpp +0 -419
  313. data/src/physics/Box2D/Dynamics/Joints/b2WheelJoint.h +0 -210
  314. data/src/physics/Box2D/Dynamics/b2Body.cpp +0 -549
  315. data/src/physics/Box2D/Dynamics/b2Body.h +0 -860
  316. data/src/physics/Box2D/Dynamics/b2ContactManager.cpp +0 -296
  317. data/src/physics/Box2D/Dynamics/b2ContactManager.h +0 -52
  318. data/src/physics/Box2D/Dynamics/b2Fixture.cpp +0 -303
  319. data/src/physics/Box2D/Dynamics/b2Fixture.h +0 -345
  320. data/src/physics/Box2D/Dynamics/b2Island.cpp +0 -539
  321. data/src/physics/Box2D/Dynamics/b2Island.h +0 -93
  322. data/src/physics/Box2D/Dynamics/b2TimeStep.h +0 -70
  323. data/src/physics/Box2D/Dynamics/b2World.cpp +0 -1339
  324. data/src/physics/Box2D/Dynamics/b2World.h +0 -354
  325. data/src/physics/Box2D/Dynamics/b2WorldCallbacks.cpp +0 -36
  326. data/src/physics/Box2D/Dynamics/b2WorldCallbacks.h +0 -155
  327. data/src/physics/Box2D/Rope/b2Rope.cpp +0 -259
  328. data/src/physics/Box2D/Rope/b2Rope.h +0 -115
  329. data/src/shape_view.cpp +0 -306
data/src/shape.cpp ADDED
@@ -0,0 +1,1191 @@
1
+ #include "shape.h"
2
+
3
+
4
+ #include <Box2D/Dynamics/b2Body.h>
5
+ #include <Box2D/Dynamics/b2Fixture.h>
6
+ #include <Box2D/Collision/Shapes/b2CircleShape.h>
7
+ #include <Box2D/Collision/Shapes/b2EdgeShape.h>
8
+ #include <Box2D/Collision/Shapes/b2ChainShape.h>
9
+ #include <Box2D/Collision/Shapes/b2PolygonShape.h>
10
+ #include <rays/polygon.h>
11
+ #include "reflex/exception.h"
12
+ #include "reflex/debug.h"
13
+ #include "selector.h"
14
+ #include "view.h"
15
+ #include "world.h"
16
+ #include "body.h"
17
+ #include "fixture.h"
18
+
19
+
20
+ namespace Reflex
21
+ {
22
+
23
+
24
+ static const Style*
25
+ get_style (const Shape* shape)
26
+ {
27
+ assert(shape);
28
+
29
+ const View* owner = shape->owner();
30
+ if (!owner) return NULL;
31
+
32
+ return &View_get_style(owner);
33
+ }
34
+
35
+ static bool
36
+ is_default_shape (const Shape* shape)
37
+ {
38
+ assert(shape);
39
+
40
+ const View* owner = shape->owner();
41
+ if (!owner) return false;
42
+
43
+ return shape == owner->shape();
44
+ }
45
+
46
+ static const Color*
47
+ get_fill (const Shape* shape)
48
+ {
49
+ assert(shape);
50
+
51
+ const Style* style = get_style(shape);
52
+ if (!style) return NULL;
53
+
54
+ return is_default_shape(shape)
55
+ ? &style->background_fill()
56
+ : &style->foreground_fill();
57
+ }
58
+
59
+ static coord
60
+ get_stroke_width (const Shape* shape)
61
+ {
62
+ assert(shape);
63
+
64
+ const Style* style = get_style(shape);
65
+ if (!style) return 0;
66
+
67
+ return is_default_shape(shape)
68
+ ? style->background_stroke_width()
69
+ : style->foreground_stroke_width();
70
+ }
71
+
72
+ static bool
73
+ has_fill (const Shape* shape)
74
+ {
75
+ assert(shape);
76
+
77
+ const Color* fill = get_fill(shape);
78
+ return fill && *fill;
79
+ }
80
+
81
+ static bool
82
+ has_stroke_width (const Shape* shape)
83
+ {
84
+ assert(shape);
85
+
86
+ return get_stroke_width(shape) > 0;
87
+ }
88
+
89
+ static bool
90
+ triangulate (Polygon::TrianglePointList* triangles, const Polygon& polygon)
91
+ {
92
+ class TriangulatablePolygon : public Polygon
93
+ {
94
+ public:
95
+ using Polygon::triangulate;
96
+ };
97
+
98
+ return ((const TriangulatablePolygon&) polygon).triangulate(triangles);
99
+ }
100
+
101
+
102
+ class FixtureBuilder
103
+ {
104
+
105
+ public:
106
+
107
+ FixtureBuilder (Shape* shape, const b2Shape* head = NULL)
108
+ : shape(shape), head(NULL), tail(NULL)
109
+ {
110
+ assert(shape);
111
+
112
+ if (head) add(head);
113
+ }
114
+
115
+ void add (const b2Shape* b2shape)
116
+ {
117
+ assert(b2shape);
118
+
119
+ Body* body = View_get_body(shape->owner());
120
+ if (!body)
121
+ invalid_state_error(__FILE__, __LINE__);
122
+
123
+ append(new Fixture(body, b2shape, shape));
124
+ }
125
+
126
+ Fixture* fixtures () const
127
+ {
128
+ return head;
129
+ }
130
+
131
+ private:
132
+
133
+ Shape* shape;
134
+
135
+ Fixture *head, *tail;
136
+
137
+ void append (Fixture* fixture)
138
+ {
139
+ if (!fixture) return;
140
+
141
+ if (tail)
142
+ tail->set_next(fixture);
143
+ else
144
+ {
145
+ assert(!head && !tail);
146
+ head = tail = fixture;
147
+ }
148
+
149
+ while (tail && tail->next())
150
+ tail = tail->next();
151
+ }
152
+
153
+ };// FixtureBuilder
154
+
155
+
156
+ static Fixture*
157
+ create_empty_fixture (Shape* shape)
158
+ {
159
+ assert(shape);
160
+
161
+ b2CircleShape b2shape;
162
+ return FixtureBuilder(shape, &b2shape).fixtures();
163
+ }
164
+
165
+ static Fixture*
166
+ create_solid_fixtures (Shape* shape, const Polygon& polygon, float ppm)
167
+ {
168
+ assert(shape);
169
+
170
+ Polygon::TrianglePointList triangles;
171
+ if (!triangulate(&triangles, polygon))
172
+ return NULL;
173
+
174
+ assert((triangles.size() % 3) == 0);
175
+
176
+ if (triangles.empty())
177
+ return NULL;
178
+
179
+ std::vector<b2Vec2> b2points;
180
+ b2points.reserve(triangles.size());
181
+ for (const auto& point : triangles)
182
+ b2points.emplace_back(to_b2vec2(point, ppm));
183
+
184
+ FixtureBuilder builder(shape);
185
+ for (size_t i = 0; i < b2points.size(); i += 3)
186
+ {
187
+ b2PolygonShape b2shape;
188
+ b2shape.Set(&b2points[i], 3);
189
+ if (b2shape.m_count != 3)
190
+ continue;// skip too small triangle
191
+
192
+ builder.add(&b2shape);
193
+ }
194
+
195
+ return builder.fixtures();
196
+ }
197
+
198
+ static void
199
+ add_polyline (
200
+ FixtureBuilder* builder, const Polyline& polyline, float ppm,
201
+ std::vector<b2Vec2>* buffer)
202
+ {
203
+ assert(builder && buffer);
204
+
205
+ buffer->clear();
206
+ buffer->reserve(polyline.size());
207
+ for (const auto& point : polyline)
208
+ buffer->emplace_back(to_b2vec2(point, ppm));
209
+
210
+ b2ChainShape b2shape;
211
+ if (polyline.loop())
212
+ b2shape.CreateLoop( &(*buffer)[0], (int32) buffer->size());
213
+ else
214
+ b2shape.CreateChain(&(*buffer)[0], (int32) buffer->size());
215
+
216
+ builder->add(&b2shape);
217
+ }
218
+
219
+ static Fixture*
220
+ create_line_fixtures (Shape* shape, const Polygon& polygon, float ppm)
221
+ {
222
+ assert(shape);
223
+
224
+ FixtureBuilder builder(shape);
225
+
226
+ std::vector<b2Vec2> b2points;
227
+ for (const auto& polyline : polygon)
228
+ add_polyline(&builder, polyline, ppm, &b2points);
229
+
230
+ return builder.fixtures();
231
+ }
232
+
233
+
234
+ struct Shape::Data
235
+ {
236
+
237
+ enum Flags
238
+ {
239
+
240
+ UPDATE_POLYGON = Xot::bit(0),
241
+
242
+ DEFAULT_FLAGS = 0
243
+
244
+ };// Flags
245
+
246
+ View* owner = NULL;
247
+
248
+ uint flags = DEFAULT_FLAGS;
249
+
250
+ Polygon polygon;
251
+
252
+ SelectorPtr pselector;
253
+
254
+ std::unique_ptr<Bounds> pframe;
255
+
256
+ std::unique_ptr<Fixture> pfixtures;
257
+
258
+ virtual ~Data ()
259
+ {
260
+ }
261
+
262
+ virtual void set_frame (const Bounds& frame)
263
+ {
264
+ if (pframe && *pframe == frame)
265
+ return;
266
+
267
+ if (pframe)
268
+ *pframe = frame;
269
+ else
270
+ pframe.reset(new Bounds(frame));
271
+
272
+ update_polygon_on_next_update();
273
+ }
274
+
275
+ virtual Bounds get_frame () const
276
+ {
277
+ if (pframe)
278
+ return *pframe;
279
+ else if (owner)
280
+ return owner->frame().dup().move_to(0, 0);
281
+ else
282
+ return 0;
283
+ }
284
+
285
+ virtual bool has_frame () const
286
+ {
287
+ return (bool) pframe;
288
+ }
289
+
290
+ void update_polygon_on_next_update ()
291
+ {
292
+ if (!owner) return;
293
+
294
+ Xot::add_flag(&flags, UPDATE_POLYGON);
295
+ View_update_shapes(owner);
296
+ }
297
+
298
+ void update_polygon (Shape* shape, bool force = false)
299
+ {
300
+ assert(shape);
301
+
302
+ if (!owner || !View_is_active(*owner))
303
+ polygon = Polygon();
304
+ else
305
+ {
306
+ Polygon poly = get_polygon_for_shape();
307
+ if (!force && poly.self == polygon.self)
308
+ return;
309
+
310
+ polygon = poly;//clip_polygon(poly);
311
+ }
312
+
313
+ update_fixtures(shape);
314
+ }
315
+
316
+ Polygon clip_polygon (const Polygon& polygon)
317
+ {
318
+ if (!pframe || !polygon)
319
+ return polygon;
320
+
321
+ return polygon & Rays::create_rect(0, 0, pframe->width, pframe->height);
322
+ }
323
+
324
+ void update_fixtures (Shape* shape)
325
+ {
326
+ if (pfixtures)
327
+ {
328
+ std::unique_ptr<Fixture> old_fix = std::move(pfixtures);
329
+ Fixture_copy_attributes(&fixtures(shape), *old_fix);
330
+ }
331
+ else if (has_body())
332
+ fixtures(shape);
333
+ }
334
+
335
+ Fixture& fixtures (Shape* shape)
336
+ {
337
+ assert(shape);
338
+
339
+ if (!pfixtures)
340
+ {
341
+ Fixture* fix;
342
+ if (has_body())
343
+ {
344
+ fix = create_fixtures(shape);
345
+ if (!fix) fix = create_empty_fixture(shape);
346
+ }
347
+ else
348
+ fix = Fixture_create_temporary();
349
+
350
+ assert(fix);
351
+ pfixtures.reset(fix);
352
+ }
353
+ return *pfixtures;
354
+ }
355
+
356
+ bool has_body () const
357
+ {
358
+ Body* body = View_get_body(owner, false);
359
+ return body && !Body_is_temporary(*body);
360
+ }
361
+
362
+ virtual Fixture* create_fixtures (Shape* shape)
363
+ {
364
+ if (!owner)
365
+ invalid_state_error(__FILE__, __LINE__);
366
+
367
+ Polygon polygon = get_polygon_for_fixtures();
368
+ if (!polygon || polygon.empty())
369
+ return NULL;
370
+
371
+ float ppm = owner->meter2pixel();
372
+
373
+ if (has_fill(shape))
374
+ return create_solid_fixtures(shape, polygon, ppm);
375
+ else if (has_stroke_width(shape))
376
+ {
377
+ Polygon hole;
378
+ if (!polygon.expand(&hole, -get_stroke_width(shape)))
379
+ return NULL;
380
+
381
+ return create_solid_fixtures(shape, polygon - hole, ppm);
382
+ }
383
+ else
384
+ return create_line_fixtures(shape, polygon, ppm);
385
+ }
386
+
387
+ virtual Polygon get_polygon_for_shape () const = 0;
388
+
389
+ virtual Polygon get_polygon_for_fixtures () const
390
+ {
391
+ return polygon;
392
+ }
393
+
394
+ };// Shape::Data
395
+
396
+
397
+ bool
398
+ Shape_set_owner (Shape* shape, View* owner)
399
+ {
400
+ if (!shape)
401
+ argument_error(__FILE__, __LINE__);
402
+
403
+ Shape::Data* self = shape->self.get();
404
+
405
+ if (owner == self->owner)
406
+ return false;
407
+
408
+ if (owner && self->owner)
409
+ invalid_state_error(__FILE__, __LINE__);
410
+
411
+ self->owner = owner;
412
+ return true;
413
+ }
414
+
415
+ bool
416
+ Shape_has_frame (const Shape& shape)
417
+ {
418
+ return shape.self->has_frame();
419
+ }
420
+
421
+ void
422
+ Shape_update (Shape* shape, bool force)
423
+ {
424
+ if (!shape)
425
+ argument_error(__FILE__, __LINE__);
426
+
427
+ bool update = Xot::check_and_remove_flag(
428
+ &shape->self->flags, Shape::Data::UPDATE_POLYGON);
429
+
430
+ if (update || force)
431
+ shape->self->update_polygon(shape, force);
432
+ }
433
+
434
+ void
435
+ Shape_call_contact_event (Shape* shape, const ContactEvent& event)
436
+ {
437
+ if (!shape)
438
+ argument_error(__FILE__, __LINE__);
439
+
440
+ ContactEvent e = event;
441
+ shape->on_contact(&e);
442
+
443
+ switch (e.type)
444
+ {
445
+ case ContactEvent::BEGIN: shape->on_contact_begin(&e); break;
446
+ case ContactEvent::END: shape->on_contact_end(&e); break;
447
+ case ContactEvent::NONE: break;
448
+ }
449
+
450
+ if (e.is_blocked())
451
+ return;
452
+
453
+ View_call_contact_event(shape->owner(), e);
454
+ }
455
+
456
+
457
+ Shape::Shape (Data* data, const char* name)
458
+ : self(data)
459
+ {
460
+ if (name) set_name(name);
461
+ }
462
+
463
+ Shape::~Shape ()
464
+ {
465
+ }
466
+
467
+ View*
468
+ Shape::owner ()
469
+ {
470
+ return self->owner;
471
+ }
472
+
473
+ const View*
474
+ Shape::owner () const
475
+ {
476
+ return const_cast<Shape*>(this)->owner();
477
+ }
478
+
479
+ void
480
+ Shape::set_frame (coord x, coord y, coord width, coord height)
481
+ {
482
+ set_frame(Bounds(x, y, width, height));
483
+ }
484
+
485
+ void
486
+ Shape::set_frame (const Bounds& frame)
487
+ {
488
+ self->set_frame(frame);
489
+ }
490
+
491
+ Bounds
492
+ Shape::frame () const
493
+ {
494
+ return self->get_frame();
495
+ }
496
+
497
+ void
498
+ Shape::set_density (float density)
499
+ {
500
+ if (density == this->density()) return;
501
+
502
+ self->fixtures(this).set_density(density);
503
+ }
504
+
505
+ float
506
+ Shape::density () const
507
+ {
508
+ const Fixture* f = self->pfixtures.get();
509
+ return f ? f->density() : 0;
510
+ }
511
+
512
+ void
513
+ Shape::set_friction (float friction)
514
+ {
515
+ if (friction == this->friction()) return;
516
+
517
+ self->fixtures(this).set_friction(friction);
518
+ }
519
+
520
+ float
521
+ Shape::friction () const
522
+ {
523
+ const Fixture* f = self->pfixtures.get();
524
+ return f ? f->friction() : 0;
525
+ }
526
+
527
+ void
528
+ Shape::set_restitution (float restitution)
529
+ {
530
+ if (restitution == this->restitution()) return;
531
+
532
+ self->fixtures(this).set_restitution(restitution);
533
+ }
534
+
535
+ float
536
+ Shape::restitution () const
537
+ {
538
+ const Fixture* f = self->pfixtures.get();
539
+ return f ? f->restitution() : 0;
540
+ }
541
+
542
+ void
543
+ Shape::set_sensor (bool state)
544
+ {
545
+ if (state == is_sensor()) return;
546
+
547
+ self->fixtures(this).set_sensor(state);
548
+ }
549
+
550
+ bool
551
+ Shape::is_sensor () const
552
+ {
553
+ const Fixture* f = self->pfixtures.get();
554
+ return f ? f->is_sensor() : false;
555
+ }
556
+
557
+ void
558
+ Shape::set_category_bits (uint bits)
559
+ {
560
+ if (bits == category_bits()) return;
561
+
562
+ self->fixtures(this).set_category_bits(bits);
563
+ }
564
+
565
+ uint
566
+ Shape::category_bits () const
567
+ {
568
+ const Fixture* f = self->pfixtures.get();
569
+ return f ? f->category_bits() : 0x1;
570
+ }
571
+
572
+ void
573
+ Shape::set_collision_mask (uint mask)
574
+ {
575
+ if (mask == collision_mask()) return;
576
+
577
+ self->fixtures(this).set_collision_mask(mask);
578
+ }
579
+
580
+ uint
581
+ Shape::collision_mask () const
582
+ {
583
+ const Fixture* f = self->pfixtures.get();
584
+ return f ? f->collision_mask() : 0xffff;
585
+ }
586
+
587
+ void
588
+ Shape::on_draw (DrawEvent* e)
589
+ {
590
+ assert(e && e->painter);
591
+
592
+ e->painter->polygon(self->polygon);
593
+ }
594
+
595
+ void
596
+ Shape::on_resize (FrameEvent* e)
597
+ {
598
+ if (!self->has_frame())
599
+ self->update_polygon_on_next_update();
600
+ }
601
+
602
+ void
603
+ Shape::on_contact (ContactEvent* e)
604
+ {
605
+ }
606
+
607
+ void
608
+ Shape::on_contact_begin (ContactEvent* e)
609
+ {
610
+ }
611
+
612
+ void
613
+ Shape::on_contact_end (ContactEvent* e)
614
+ {
615
+ }
616
+
617
+ SelectorPtr*
618
+ Shape::get_selector_ptr ()
619
+ {
620
+ return &self->pselector;
621
+ }
622
+
623
+
624
+ struct FixedFrameShapeData : public Shape::Data
625
+ {
626
+
627
+ void set_frame (const Bounds& frame) override
628
+ {
629
+ // updating frame for shape has fixed frame is not supported.
630
+ not_implemented_error(__FILE__, __LINE__);
631
+ }
632
+
633
+ Bounds get_frame () const override
634
+ {
635
+ return get_fixed_frame();
636
+ }
637
+
638
+ bool has_frame () const override
639
+ {
640
+ return has_fixed_frame();
641
+ }
642
+
643
+ virtual Bounds get_fixed_frame () const = 0;
644
+
645
+ virtual bool has_fixed_frame () const = 0;
646
+
647
+ };// FixedFrameShapeData
648
+
649
+
650
+ struct PolygonShapeData : public FixedFrameShapeData
651
+ {
652
+
653
+ Polygon polygon;
654
+
655
+ Polygon get_polygon_for_shape () const override
656
+ {
657
+ return polygon;
658
+ }
659
+
660
+ Bounds get_fixed_frame () const override
661
+ {
662
+ return polygon.bounds();
663
+ }
664
+
665
+ bool has_fixed_frame () const override
666
+ {
667
+ return !polygon.empty(true);
668
+ }
669
+
670
+ };// PolygonShapeData
671
+
672
+
673
+ static PolygonShapeData&
674
+ get_data (PolygonShape& shape)
675
+ {
676
+ return (PolygonShapeData&) *shape.self;
677
+ }
678
+
679
+ static const PolygonShapeData&
680
+ get_data (const PolygonShape& shape)
681
+ {
682
+ return get_data(const_cast<PolygonShape&>(shape));
683
+ }
684
+
685
+
686
+ PolygonShape::PolygonShape (const char* name)
687
+ : Super(new PolygonShapeData, name)
688
+ {
689
+ }
690
+
691
+ PolygonShape::~PolygonShape ()
692
+ {
693
+ }
694
+
695
+ void
696
+ PolygonShape::set_polygon (const Polygon& polygon)
697
+ {
698
+ get_data(*this).polygon = polygon;
699
+
700
+ self->update_polygon_on_next_update();
701
+ }
702
+
703
+ const Polygon&
704
+ PolygonShape::polygon () const
705
+ {
706
+ return get_data(*this).polygon;
707
+ }
708
+
709
+
710
+ struct LineShapeData : public FixedFrameShapeData
711
+ {
712
+
713
+ std::vector<Point> points;
714
+
715
+ bool loop = false;
716
+
717
+ Polygon get_polygon_for_shape () const override
718
+ {
719
+ if (points.empty())
720
+ return Polygon();
721
+
722
+ return Rays::create_line(&points[0], points.size(), loop);
723
+ }
724
+
725
+ Bounds get_fixed_frame () const override
726
+ {
727
+ if (points.empty()) return Bounds(-1, -1, -1);
728
+
729
+ Bounds b(points[0], 0);
730
+ for (const auto& point : points)
731
+ b |= point;
732
+ return b;
733
+ }
734
+
735
+ bool has_fixed_frame () const override
736
+ {
737
+ return !points.empty();
738
+ }
739
+
740
+ };// LineShapeData
741
+
742
+
743
+ static LineShapeData&
744
+ get_data (LineShape& shape)
745
+ {
746
+ return (LineShapeData&) *shape.self;
747
+ }
748
+
749
+ static const LineShapeData&
750
+ get_data (const LineShape& shape)
751
+ {
752
+ return get_data(const_cast<LineShape&>(shape));
753
+ }
754
+
755
+
756
+ LineShape::LineShape (const char* name)
757
+ : Super(new LineShapeData, name)
758
+ {
759
+ }
760
+
761
+ LineShape::~LineShape ()
762
+ {
763
+ }
764
+
765
+ void
766
+ LineShape::add_point (coord x, coord y, coord z)
767
+ {
768
+ add_point(Point(x, y, z));
769
+ }
770
+
771
+ void
772
+ LineShape::add_point (const Point& point)
773
+ {
774
+ get_data(*this).points.emplace_back(point);
775
+
776
+ self->update_polygon_on_next_update();
777
+ }
778
+
779
+ void
780
+ LineShape::add_points (const Point* points, size_t size)
781
+ {
782
+ auto& array = get_data(*this).points;
783
+ array.insert(array.end(), points, points + size);
784
+
785
+ self->update_polygon_on_next_update();
786
+ }
787
+
788
+ void
789
+ LineShape::set_loop (bool loop)
790
+ {
791
+ get_data(*this).loop = loop;
792
+ }
793
+
794
+ bool
795
+ LineShape::loop () const
796
+ {
797
+ return get_data(*this).loop;
798
+ }
799
+
800
+
801
+ struct RectShapeData : public Shape::Data
802
+ {
803
+
804
+ typedef Shape::Data Super;
805
+
806
+ coord round_left_top = 0;
807
+ coord round_right_top = 0;
808
+ coord round_left_bottom = 0;
809
+ coord round_right_bottom = 0;
810
+
811
+ uint nsegment = 0;
812
+
813
+ Polygon get_polygon_for_shape () const override
814
+ {
815
+ return Rays::create_rect(
816
+ get_frame(),
817
+ round_left_top, round_right_top,
818
+ round_left_bottom, round_right_bottom,
819
+ nsegment);
820
+ }
821
+
822
+ Polygon get_polygon_for_fixtures () const override
823
+ {
824
+ if (nsegment <= 0 && has_rounds())
825
+ return Rays::create_rect(get_frame(), 0, 0, 0, 0, 1);
826
+ else
827
+ return Super::get_polygon_for_fixtures();
828
+ }
829
+
830
+ bool has_rounds () const
831
+ {
832
+ return
833
+ round_left_top != 0 ||
834
+ round_right_top != 0 ||
835
+ round_left_bottom != 0 ||
836
+ round_right_bottom != 0;
837
+ }
838
+
839
+ };// RectShapeData
840
+
841
+
842
+ static RectShapeData&
843
+ get_data (RectShape& shape)
844
+ {
845
+ return (RectShapeData&) *shape.self;
846
+ }
847
+
848
+ static const RectShapeData&
849
+ get_data (const RectShape& shape)
850
+ {
851
+ return get_data(const_cast<RectShape&>(shape));
852
+ }
853
+
854
+
855
+ RectShape::RectShape (const char* name)
856
+ : Super(new RectShapeData, name)
857
+ {
858
+ }
859
+
860
+ RectShape::~RectShape ()
861
+ {
862
+ }
863
+
864
+ void
865
+ RectShape::set_round (coord round)
866
+ {
867
+ set_round(round, round, round, round);
868
+ }
869
+
870
+ void
871
+ RectShape::set_round (
872
+ coord left_top, coord right_top, coord left_bottom, coord right_bottom)
873
+ {
874
+ RectShapeData& data = get_data(*this);
875
+ data.round_left_top = left_top;
876
+ data.round_right_top = right_top;
877
+ data.round_left_bottom = left_bottom;
878
+ data.round_right_bottom = right_bottom;
879
+
880
+ self->update_polygon_on_next_update();
881
+ }
882
+
883
+ void
884
+ RectShape::set_round_left_top (coord round)
885
+ {
886
+ get_data(*this).round_left_top = round;
887
+
888
+ self->update_polygon_on_next_update();
889
+ }
890
+
891
+ coord
892
+ RectShape::round_left_top () const
893
+ {
894
+ return get_data(*this).round_left_top;
895
+ }
896
+
897
+ void
898
+ RectShape::set_round_right_top (coord round)
899
+ {
900
+ get_data(*this).round_right_top = round;
901
+
902
+ self->update_polygon_on_next_update();
903
+ }
904
+
905
+ coord
906
+ RectShape::round_right_top () const
907
+ {
908
+ return get_data(*this).round_right_top;
909
+ }
910
+
911
+ void
912
+ RectShape::set_round_left_bottom (coord round)
913
+ {
914
+ get_data(*this).round_left_bottom = round;
915
+
916
+ self->update_polygon_on_next_update();
917
+ }
918
+
919
+ coord
920
+ RectShape::round_left_bottom () const
921
+ {
922
+ return get_data(*this).round_left_bottom;
923
+ }
924
+
925
+ void
926
+ RectShape::set_round_right_bottom (coord round)
927
+ {
928
+ get_data(*this).round_right_bottom = round;
929
+
930
+ self->update_polygon_on_next_update();
931
+ }
932
+
933
+ coord
934
+ RectShape::round_right_bottom () const
935
+ {
936
+ return get_data(*this).round_right_bottom;
937
+ }
938
+
939
+ void
940
+ RectShape::set_nsegment (uint nsegment)
941
+ {
942
+ get_data(*this).nsegment = nsegment;
943
+
944
+ self->update_polygon_on_next_update();
945
+ }
946
+
947
+ uint
948
+ RectShape::nsegment () const
949
+ {
950
+ return get_data(*this).nsegment;
951
+ }
952
+
953
+
954
+ struct EllipseShapeData : public Shape::Data
955
+ {
956
+
957
+ typedef Shape::Data Super;
958
+
959
+ enum
960
+ {
961
+ DEFAULT_ANGLE_FROM = 0,
962
+ DEFAULT_ANGLE_TO = 360,
963
+
964
+ ANGLE_MAX = DEFAULT_ANGLE_TO - DEFAULT_ANGLE_FROM
965
+ };
966
+
967
+ Point hole_size;
968
+
969
+ float angle_from = DEFAULT_ANGLE_FROM;
970
+ float angle_to = DEFAULT_ANGLE_TO;
971
+
972
+ uint nsegment = 0;
973
+
974
+ bool has_hole () const
975
+ {
976
+ return hole_size.x != 0 && hole_size.y != 0;
977
+ }
978
+
979
+ bool has_angle () const
980
+ {
981
+ return
982
+ angle_from != DEFAULT_ANGLE_FROM ||
983
+ angle_to != DEFAULT_ANGLE_TO;
984
+ }
985
+
986
+ Fixture* create_fixtures (Shape* shape) override
987
+ {
988
+ Bounds f = get_frame();
989
+ bool circle = f.size() != 0 && f.width == f.height;
990
+ if (circle && !has_angle() && !has_hole() && has_fill(shape))
991
+ return create_circle_fixture(shape, f);
992
+ else
993
+ return Super::create_fixtures(shape);
994
+ }
995
+
996
+ Fixture* create_circle_fixture (Shape* shape, const Bounds& frame)
997
+ {
998
+ assert(shape);
999
+
1000
+ if (!owner)
1001
+ invalid_state_error(__FILE__, __LINE__);
1002
+
1003
+ float ppm = owner->meter2pixel();
1004
+
1005
+ b2CircleShape b2shape;
1006
+ b2shape.m_p = to_b2vec2(frame.center(), ppm);
1007
+ b2shape.m_radius = to_b2coord(frame.width / 2, ppm);
1008
+
1009
+ return FixtureBuilder(shape, &b2shape).fixtures();
1010
+ }
1011
+
1012
+ Polygon get_polygon_for_shape () const override
1013
+ {
1014
+ return Rays::create_ellipse(
1015
+ get_frame(), hole_size, angle_from, angle_to, nsegment);
1016
+ }
1017
+
1018
+ Polygon get_polygon_for_fixtures () const override
1019
+ {
1020
+ if (nsegment <= 0)
1021
+ {
1022
+ return Rays::create_ellipse(
1023
+ get_frame(), hole_size, angle_from, angle_to, 8);
1024
+ }
1025
+ else
1026
+ return Super::get_polygon_for_fixtures();
1027
+ }
1028
+
1029
+ };// EllipseShapeData
1030
+
1031
+
1032
+ static EllipseShapeData&
1033
+ get_data (EllipseShape& shape)
1034
+ {
1035
+ return (EllipseShapeData&) *shape.self;
1036
+ }
1037
+
1038
+ static const EllipseShapeData&
1039
+ get_data (const EllipseShape& shape)
1040
+ {
1041
+ return get_data(const_cast<EllipseShape&>(shape));
1042
+ }
1043
+
1044
+
1045
+ EllipseShape::EllipseShape (const char* name)
1046
+ : Super(new EllipseShapeData, name)
1047
+ {
1048
+ }
1049
+
1050
+ EllipseShape::~EllipseShape ()
1051
+ {
1052
+ }
1053
+
1054
+ void
1055
+ EllipseShape::set_hole_size (coord width, coord height)
1056
+ {
1057
+ get_data(*this).hole_size.reset(width, height);
1058
+
1059
+ self->update_polygon_on_next_update();
1060
+ }
1061
+
1062
+ void
1063
+ EllipseShape::set_hole_size (const Point& hole_size)
1064
+ {
1065
+ set_hole_size(hole_size.x, hole_size.y);
1066
+ }
1067
+
1068
+ const Point&
1069
+ EllipseShape::hole_size () const
1070
+ {
1071
+ return get_data(*this).hole_size;
1072
+ }
1073
+
1074
+ void
1075
+ EllipseShape::set_angle_from (float degree)
1076
+ {
1077
+ get_data(*this).angle_from = degree;
1078
+
1079
+ self->update_polygon_on_next_update();
1080
+ }
1081
+
1082
+ float
1083
+ EllipseShape::angle_from () const
1084
+ {
1085
+ return get_data(*this).angle_from;
1086
+ }
1087
+
1088
+ void
1089
+ EllipseShape::set_angle_to (float degree)
1090
+ {
1091
+ get_data(*this).angle_to = degree;
1092
+
1093
+ self->update_polygon_on_next_update();
1094
+ }
1095
+
1096
+ float
1097
+ EllipseShape::angle_to () const
1098
+ {
1099
+ return get_data(*this).angle_to;
1100
+ }
1101
+
1102
+ void
1103
+ EllipseShape::set_nsegment (uint num_of_segments)
1104
+ {
1105
+ get_data(*this).nsegment = num_of_segments;
1106
+
1107
+ self->update_polygon_on_next_update();
1108
+ }
1109
+
1110
+ uint
1111
+ EllipseShape::nsegment () const
1112
+ {
1113
+ return get_data(*this).nsegment;
1114
+ }
1115
+
1116
+
1117
+ struct WallShapeData : public Shape::Data
1118
+ {
1119
+
1120
+ uint positions = 0;
1121
+
1122
+ coord thickness = 0;
1123
+
1124
+ Polygon get_polygon_for_shape () const override
1125
+ {
1126
+ Bounds frame = get_frame();
1127
+
1128
+ Polygon poly;
1129
+ add_wall_polygon(&poly, WallShape::LEFT, frame);
1130
+ add_wall_polygon(&poly, WallShape::TOP, frame);
1131
+ add_wall_polygon(&poly, WallShape::RIGHT, frame);
1132
+ add_wall_polygon(&poly, WallShape::BOTTOM, frame);
1133
+ return poly;
1134
+ }
1135
+
1136
+ void add_wall_polygon (
1137
+ Polygon* polygon, WallShape::Position position, const Bounds& frame) const
1138
+ {
1139
+ assert(polygon);
1140
+
1141
+ if (positions & position)
1142
+ *polygon = *polygon | create_wall_polygon(position, frame, thickness);
1143
+ }
1144
+
1145
+ static Polygon create_wall_polygon (
1146
+ WallShape::Position pos, const Bounds& frame, coord thickness)
1147
+ {
1148
+ coord w = frame.width, h = frame.height, t = thickness, tt = thickness * 2;
1149
+ switch (pos)
1150
+ {
1151
+ case WallShape::LEFT: return Rays::create_rect(-t, -t, t, h + tt);
1152
+ case WallShape::TOP: return Rays::create_rect(-t, -t, w + tt, t);
1153
+ case WallShape::RIGHT: return Rays::create_rect( w, -t, t, h + tt);
1154
+ case WallShape::BOTTOM: return Rays::create_rect(-t, h, w + tt, t);
1155
+ default: argument_error(__FILE__, __LINE__, "invalid wall position.");
1156
+ }
1157
+ return Polygon();
1158
+ }
1159
+
1160
+ };// WallShapeData
1161
+
1162
+
1163
+ static WallShapeData&
1164
+ get_data (WallShape& shape)
1165
+ {
1166
+ return (WallShapeData&) *shape.self;
1167
+ }
1168
+
1169
+ static const WallShapeData&
1170
+ get_data (const WallShape& shape)
1171
+ {
1172
+ return get_data(const_cast<WallShape&>(shape));
1173
+ }
1174
+
1175
+
1176
+ WallShape::WallShape (uint positions, coord thickness)
1177
+ : Super(new WallShapeData)
1178
+ {
1179
+ WallShapeData& data = get_data(*this);
1180
+ data.positions = positions;
1181
+ data.thickness = thickness;
1182
+ }
1183
+
1184
+ void
1185
+ WallShape::on_draw (DrawEvent* e)
1186
+ {
1187
+ // wall is invisible, so draw nothing
1188
+ }
1189
+
1190
+
1191
+ }// Reflex