reflexion 0.1.11 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (333) hide show
  1. checksums.yaml +5 -5
  2. data/.doc/ext/reflex/application.cpp +9 -5
  3. data/.doc/ext/reflex/capture_event.cpp +4 -9
  4. data/.doc/ext/reflex/contact_event.cpp +17 -13
  5. data/.doc/ext/reflex/draw_event.cpp +3 -8
  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 +47 -14
  11. data/.doc/ext/reflex/image_view.cpp +1 -10
  12. data/.doc/ext/reflex/key_event.cpp +9 -14
  13. data/.doc/ext/reflex/line_shape.cpp +99 -0
  14. data/.doc/ext/reflex/motion_event.cpp +73 -0
  15. data/.doc/ext/reflex/native.cpp +18 -18
  16. data/.doc/ext/reflex/pointer_event.cpp +27 -25
  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 +24 -3
  20. data/.doc/ext/reflex/scroll_event.cpp +8 -15
  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 +12 -8
  28. data/.doc/ext/reflex/view.cpp +548 -144
  29. data/.doc/ext/reflex/wheel_event.cpp +5 -28
  30. data/.doc/ext/reflex/window.cpp +7 -15
  31. data/LICENSE +21 -0
  32. data/README.md +1 -1
  33. data/Rakefile +14 -12
  34. data/VERSION +1 -1
  35. data/ext/reflex/application.cpp +10 -5
  36. data/ext/reflex/capture_event.cpp +4 -9
  37. data/ext/reflex/contact_event.cpp +18 -13
  38. data/ext/reflex/defs.h +5 -2
  39. data/ext/reflex/draw_event.cpp +3 -8
  40. data/ext/reflex/ellipse_shape.cpp +56 -25
  41. data/ext/reflex/event.cpp +0 -4
  42. data/ext/reflex/extconf.rb +1 -2
  43. data/ext/reflex/filter.cpp +86 -0
  44. data/ext/reflex/focus_event.cpp +11 -15
  45. data/ext/reflex/frame_event.cpp +52 -14
  46. data/ext/reflex/image_view.cpp +1 -10
  47. data/ext/reflex/key_event.cpp +9 -14
  48. data/ext/reflex/line_shape.cpp +104 -0
  49. data/ext/reflex/motion_event.cpp +77 -0
  50. data/ext/reflex/native.cpp +18 -18
  51. data/ext/reflex/pointer_event.cpp +27 -25
  52. data/ext/reflex/polygon_shape.cpp +68 -0
  53. data/ext/reflex/rect_shape.cpp +113 -24
  54. data/ext/reflex/reflex.cpp +24 -3
  55. data/ext/reflex/scroll_event.cpp +8 -15
  56. data/ext/reflex/selector.cpp +46 -16
  57. data/ext/reflex/selector.h +130 -0
  58. data/ext/reflex/shape.cpp +231 -0
  59. data/ext/reflex/style.cpp +363 -192
  60. data/ext/reflex/style_length.cpp +164 -37
  61. data/ext/reflex/timer.cpp +108 -0
  62. data/ext/reflex/timer_event.cpp +133 -0
  63. data/ext/reflex/update_event.cpp +13 -8
  64. data/ext/reflex/view.cpp +594 -150
  65. data/ext/reflex/wheel_event.cpp +5 -30
  66. data/ext/reflex/window.cpp +7 -15
  67. data/include/reflex.h +5 -4
  68. data/include/reflex/application.h +2 -0
  69. data/include/reflex/debug.h +22 -0
  70. data/include/reflex/defs.h +45 -2
  71. data/include/reflex/event.h +55 -11
  72. data/include/reflex/exception.h +17 -2
  73. data/include/reflex/filter.h +56 -0
  74. data/include/reflex/image_view.h +1 -1
  75. data/include/reflex/ruby.h +6 -4
  76. data/include/reflex/ruby/application.h +17 -9
  77. data/include/reflex/ruby/event.h +22 -0
  78. data/include/reflex/ruby/filter.h +69 -0
  79. data/include/reflex/ruby/reflex.h +1 -0
  80. data/include/reflex/ruby/selector.h +1 -1
  81. data/include/reflex/ruby/shape.h +140 -0
  82. data/include/reflex/ruby/style.h +1 -1
  83. data/include/reflex/ruby/timer.h +69 -0
  84. data/include/reflex/ruby/view.h +43 -76
  85. data/include/reflex/ruby/window.h +17 -32
  86. data/include/reflex/selector.h +54 -2
  87. data/include/reflex/shape.h +211 -0
  88. data/include/reflex/style.h +136 -76
  89. data/include/reflex/timer.h +73 -0
  90. data/include/reflex/view.h +181 -59
  91. data/include/reflex/window.h +4 -3
  92. data/lib/reflex.rb +13 -6
  93. data/lib/reflex/application.rb +6 -3
  94. data/lib/reflex/button.rb +2 -2
  95. data/lib/reflex/{texture.rb → camera.rb} +2 -2
  96. data/lib/reflex/capture_event.rb +7 -6
  97. data/lib/reflex/contact_event.rb +10 -12
  98. data/lib/reflex/draw_event.rb +6 -1
  99. data/lib/reflex/ellipse_shape.rb +27 -0
  100. data/lib/reflex/filter.rb +18 -0
  101. data/lib/reflex/fixture.rb +4 -0
  102. data/lib/reflex/focus_event.rb +10 -12
  103. data/lib/reflex/frame_event.rb +1 -1
  104. data/lib/reflex/helper.rb +17 -29
  105. data/lib/reflex/key_event.rb +13 -11
  106. data/lib/reflex/line_shape.rb +18 -0
  107. data/lib/reflex/matrix.rb +13 -0
  108. data/lib/reflex/module.rb +4 -19
  109. data/lib/reflex/pointer_event.rb +28 -35
  110. data/lib/reflex/polygon.rb +14 -0
  111. data/lib/reflex/polygon_shape.rb +23 -0
  112. data/lib/reflex/polyline.rb +13 -0
  113. data/lib/reflex/rect_shape.rb +20 -0
  114. data/lib/reflex/reflex.rb +1 -3
  115. data/lib/reflex/scroll_event.rb +1 -1
  116. data/lib/reflex/selector.rb +2 -2
  117. data/lib/reflex/shape.rb +62 -0
  118. data/lib/reflex/style.rb +78 -11
  119. data/lib/reflex/style_length.rb +0 -11
  120. data/lib/reflex/text_view.rb +7 -24
  121. data/lib/reflex/timer.rb +30 -0
  122. data/lib/reflex/timer_event.rb +29 -0
  123. data/lib/reflex/update_event.rb +1 -1
  124. data/lib/reflex/view.rb +127 -32
  125. data/lib/reflex/wheel_event.rb +9 -1
  126. data/lib/reflex/window.rb +29 -9
  127. data/lib/reflexion.rb +23 -7
  128. data/reflex.gemspec +7 -8
  129. data/samples/bats.rb +4 -4
  130. data/samples/camera.rb +32 -0
  131. data/samples/fans.rb +1 -1
  132. data/samples/fps.rb +5 -3
  133. data/samples/hello.rb +4 -6
  134. data/samples/image.rb +5 -4
  135. data/samples/ios/hello/hello.xcodeproj/project.pbxproj +0 -2
  136. data/samples/layout.rb +16 -7
  137. data/samples/model.rb +10 -7
  138. data/samples/physics.rb +22 -20
  139. data/samples/reflexion/breakout.rb +4 -5
  140. data/samples/reflexion/hello.rb +2 -2
  141. data/samples/reflexion/jump_action.rb +191 -0
  142. data/samples/reflexion/noise.rb +23 -0
  143. data/samples/reflexion/paint.rb +7 -6
  144. data/samples/reflexion/physics.rb +15 -8
  145. data/samples/reflexion/pulse.rb +24 -10
  146. data/samples/shader.rb +8 -6
  147. data/samples/shapes.rb +79 -14
  148. data/samples/tree.rb +9 -10
  149. data/samples/views.rb +3 -3
  150. data/samples/visuals.rb +2 -5
  151. data/src/body.cpp +146 -345
  152. data/src/body.h +91 -0
  153. data/src/event.cpp +65 -15
  154. data/src/exception.cpp +13 -3
  155. data/src/filter.cpp +76 -0
  156. data/src/fixture.cpp +164 -39
  157. data/src/fixture.h +85 -0
  158. data/src/image_view.cpp +4 -4
  159. data/src/ios/app_delegate.h +5 -10
  160. data/src/ios/app_delegate.mm +79 -41
  161. data/src/ios/application.h +32 -0
  162. data/src/ios/application.mm +35 -25
  163. data/src/ios/event.mm +8 -4
  164. data/src/ios/reflex.mm +0 -7
  165. data/src/ios/view_controller.h +37 -0
  166. data/src/ios/view_controller.mm +424 -0
  167. data/src/ios/window.h +40 -0
  168. data/src/ios/window.mm +59 -250
  169. data/src/osx/app_delegate.h +5 -10
  170. data/src/osx/app_delegate.mm +52 -55
  171. data/src/osx/application.h +32 -0
  172. data/src/osx/application.mm +44 -39
  173. data/src/osx/native_window.h +0 -15
  174. data/src/osx/native_window.mm +127 -127
  175. data/src/osx/opengl_view.h +0 -2
  176. data/src/osx/opengl_view.mm +12 -3
  177. data/src/osx/reflex.mm +0 -9
  178. data/src/osx/window.h +42 -0
  179. data/src/osx/window.mm +45 -252
  180. data/src/selector.cpp +232 -7
  181. data/src/selector.h +52 -0
  182. data/src/shape.cpp +1191 -0
  183. data/src/shape.h +61 -0
  184. data/src/style.cpp +573 -376
  185. data/src/style.h +39 -0
  186. data/src/timer.cpp +288 -0
  187. data/src/timer.h +55 -0
  188. data/src/view.cpp +1624 -984
  189. data/src/view.h +56 -0
  190. data/src/win32/window.cpp +3 -4
  191. data/src/window.cpp +302 -20
  192. data/src/window.h +94 -0
  193. data/src/world.cpp +112 -111
  194. data/src/world.h +34 -53
  195. data/task/box2d.rake +31 -10
  196. data/test/test_capture_event.rb +8 -6
  197. data/test/test_pointer_event.rb +130 -0
  198. data/test/test_selector.rb +1 -1
  199. data/test/test_shape.rb +71 -0
  200. data/test/test_style.rb +77 -11
  201. data/test/test_style_length.rb +42 -13
  202. data/test/test_view.rb +138 -14
  203. metadata +118 -202
  204. data/.doc/ext/reflex/arc_shape.cpp +0 -89
  205. data/.doc/ext/reflex/body.cpp +0 -299
  206. data/.doc/ext/reflex/fixture.cpp +0 -101
  207. data/.doc/ext/reflex/shape_view.cpp +0 -153
  208. data/ext/reflex/arc_shape.cpp +0 -94
  209. data/ext/reflex/body.cpp +0 -328
  210. data/ext/reflex/fixture.cpp +0 -108
  211. data/ext/reflex/shape_view.cpp +0 -161
  212. data/include/reflex/bitmap.h +0 -20
  213. data/include/reflex/body.h +0 -128
  214. data/include/reflex/bounds.h +0 -20
  215. data/include/reflex/color.h +0 -20
  216. data/include/reflex/color_space.h +0 -20
  217. data/include/reflex/fixture.h +0 -117
  218. data/include/reflex/font.h +0 -20
  219. data/include/reflex/image.h +0 -20
  220. data/include/reflex/matrix.h +0 -20
  221. data/include/reflex/painter.h +0 -20
  222. data/include/reflex/point.h +0 -24
  223. data/include/reflex/ruby/body.h +0 -41
  224. data/include/reflex/ruby/fixture.h +0 -41
  225. data/include/reflex/ruby/shape_view.h +0 -96
  226. data/include/reflex/shader.h +0 -20
  227. data/include/reflex/shape_view.h +0 -146
  228. data/include/reflex/texture.h +0 -20
  229. data/lib/reflex/body.rb +0 -22
  230. data/lib/reflex/flags.rb +0 -18
  231. data/lib/reflex/shape_view.rb +0 -25
  232. data/src/ios/application_data.h +0 -45
  233. data/src/ios/native_window.h +0 -39
  234. data/src/ios/native_window.mm +0 -224
  235. data/src/ios/opengl_view.h +0 -13
  236. data/src/ios/opengl_view.mm +0 -139
  237. data/src/ios/window_data.h +0 -75
  238. data/src/osx/application_data.h +0 -45
  239. data/src/osx/window_data.h +0 -75
  240. data/src/physics/Box2D/Box2D.h +0 -68
  241. data/src/physics/Box2D/Collision/Shapes/b2ChainShape.cpp +0 -193
  242. data/src/physics/Box2D/Collision/Shapes/b2ChainShape.h +0 -105
  243. data/src/physics/Box2D/Collision/Shapes/b2CircleShape.cpp +0 -99
  244. data/src/physics/Box2D/Collision/Shapes/b2CircleShape.h +0 -91
  245. data/src/physics/Box2D/Collision/Shapes/b2EdgeShape.cpp +0 -138
  246. data/src/physics/Box2D/Collision/Shapes/b2EdgeShape.h +0 -74
  247. data/src/physics/Box2D/Collision/Shapes/b2PolygonShape.cpp +0 -467
  248. data/src/physics/Box2D/Collision/Shapes/b2PolygonShape.h +0 -101
  249. data/src/physics/Box2D/Collision/Shapes/b2Shape.h +0 -101
  250. data/src/physics/Box2D/Collision/b2BroadPhase.cpp +0 -119
  251. data/src/physics/Box2D/Collision/b2BroadPhase.h +0 -257
  252. data/src/physics/Box2D/Collision/b2CollideCircle.cpp +0 -154
  253. data/src/physics/Box2D/Collision/b2CollideEdge.cpp +0 -698
  254. data/src/physics/Box2D/Collision/b2CollidePolygon.cpp +0 -239
  255. data/src/physics/Box2D/Collision/b2Collision.cpp +0 -252
  256. data/src/physics/Box2D/Collision/b2Collision.h +0 -277
  257. data/src/physics/Box2D/Collision/b2Distance.cpp +0 -603
  258. data/src/physics/Box2D/Collision/b2Distance.h +0 -141
  259. data/src/physics/Box2D/Collision/b2DynamicTree.cpp +0 -778
  260. data/src/physics/Box2D/Collision/b2DynamicTree.h +0 -289
  261. data/src/physics/Box2D/Collision/b2TimeOfImpact.cpp +0 -486
  262. data/src/physics/Box2D/Collision/b2TimeOfImpact.h +0 -58
  263. data/src/physics/Box2D/Common/b2BlockAllocator.cpp +0 -215
  264. data/src/physics/Box2D/Common/b2BlockAllocator.h +0 -62
  265. data/src/physics/Box2D/Common/b2Draw.cpp +0 -44
  266. data/src/physics/Box2D/Common/b2Draw.h +0 -86
  267. data/src/physics/Box2D/Common/b2GrowableStack.h +0 -85
  268. data/src/physics/Box2D/Common/b2Math.cpp +0 -94
  269. data/src/physics/Box2D/Common/b2Math.h +0 -720
  270. data/src/physics/Box2D/Common/b2Settings.cpp +0 -44
  271. data/src/physics/Box2D/Common/b2Settings.h +0 -151
  272. data/src/physics/Box2D/Common/b2StackAllocator.cpp +0 -83
  273. data/src/physics/Box2D/Common/b2StackAllocator.h +0 -60
  274. data/src/physics/Box2D/Common/b2Timer.cpp +0 -101
  275. data/src/physics/Box2D/Common/b2Timer.h +0 -50
  276. data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp +0 -53
  277. data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.h +0 -39
  278. data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp +0 -53
  279. data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.h +0 -39
  280. data/src/physics/Box2D/Dynamics/Contacts/b2CircleContact.cpp +0 -52
  281. data/src/physics/Box2D/Dynamics/Contacts/b2CircleContact.h +0 -39
  282. data/src/physics/Box2D/Dynamics/Contacts/b2Contact.cpp +0 -247
  283. data/src/physics/Box2D/Dynamics/Contacts/b2Contact.h +0 -349
  284. data/src/physics/Box2D/Dynamics/Contacts/b2ContactSolver.cpp +0 -838
  285. data/src/physics/Box2D/Dynamics/Contacts/b2ContactSolver.h +0 -95
  286. data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp +0 -49
  287. data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.h +0 -39
  288. data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp +0 -49
  289. data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.h +0 -39
  290. data/src/physics/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp +0 -49
  291. data/src/physics/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h +0 -38
  292. data/src/physics/Box2D/Dynamics/Contacts/b2PolygonContact.cpp +0 -52
  293. data/src/physics/Box2D/Dynamics/Contacts/b2PolygonContact.h +0 -39
  294. data/src/physics/Box2D/Dynamics/Joints/b2DistanceJoint.cpp +0 -260
  295. data/src/physics/Box2D/Dynamics/Joints/b2DistanceJoint.h +0 -169
  296. data/src/physics/Box2D/Dynamics/Joints/b2FrictionJoint.cpp +0 -251
  297. data/src/physics/Box2D/Dynamics/Joints/b2FrictionJoint.h +0 -119
  298. data/src/physics/Box2D/Dynamics/Joints/b2GearJoint.cpp +0 -419
  299. data/src/physics/Box2D/Dynamics/Joints/b2GearJoint.h +0 -125
  300. data/src/physics/Box2D/Dynamics/Joints/b2Joint.cpp +0 -211
  301. data/src/physics/Box2D/Dynamics/Joints/b2Joint.h +0 -226
  302. data/src/physics/Box2D/Dynamics/Joints/b2MotorJoint.cpp +0 -304
  303. data/src/physics/Box2D/Dynamics/Joints/b2MotorJoint.h +0 -133
  304. data/src/physics/Box2D/Dynamics/Joints/b2MouseJoint.cpp +0 -222
  305. data/src/physics/Box2D/Dynamics/Joints/b2MouseJoint.h +0 -129
  306. data/src/physics/Box2D/Dynamics/Joints/b2PrismaticJoint.cpp +0 -629
  307. data/src/physics/Box2D/Dynamics/Joints/b2PrismaticJoint.h +0 -196
  308. data/src/physics/Box2D/Dynamics/Joints/b2PulleyJoint.cpp +0 -348
  309. data/src/physics/Box2D/Dynamics/Joints/b2PulleyJoint.h +0 -152
  310. data/src/physics/Box2D/Dynamics/Joints/b2RevoluteJoint.cpp +0 -502
  311. data/src/physics/Box2D/Dynamics/Joints/b2RevoluteJoint.h +0 -204
  312. data/src/physics/Box2D/Dynamics/Joints/b2RopeJoint.cpp +0 -241
  313. data/src/physics/Box2D/Dynamics/Joints/b2RopeJoint.h +0 -114
  314. data/src/physics/Box2D/Dynamics/Joints/b2WeldJoint.cpp +0 -344
  315. data/src/physics/Box2D/Dynamics/Joints/b2WeldJoint.h +0 -126
  316. data/src/physics/Box2D/Dynamics/Joints/b2WheelJoint.cpp +0 -419
  317. data/src/physics/Box2D/Dynamics/Joints/b2WheelJoint.h +0 -210
  318. data/src/physics/Box2D/Dynamics/b2Body.cpp +0 -549
  319. data/src/physics/Box2D/Dynamics/b2Body.h +0 -860
  320. data/src/physics/Box2D/Dynamics/b2ContactManager.cpp +0 -296
  321. data/src/physics/Box2D/Dynamics/b2ContactManager.h +0 -52
  322. data/src/physics/Box2D/Dynamics/b2Fixture.cpp +0 -303
  323. data/src/physics/Box2D/Dynamics/b2Fixture.h +0 -345
  324. data/src/physics/Box2D/Dynamics/b2Island.cpp +0 -539
  325. data/src/physics/Box2D/Dynamics/b2Island.h +0 -93
  326. data/src/physics/Box2D/Dynamics/b2TimeStep.h +0 -70
  327. data/src/physics/Box2D/Dynamics/b2World.cpp +0 -1339
  328. data/src/physics/Box2D/Dynamics/b2World.h +0 -354
  329. data/src/physics/Box2D/Dynamics/b2WorldCallbacks.cpp +0 -36
  330. data/src/physics/Box2D/Dynamics/b2WorldCallbacks.h +0 -155
  331. data/src/physics/Box2D/Rope/b2Rope.cpp +0 -259
  332. data/src/physics/Box2D/Rope/b2Rope.h +0 -115
  333. data/src/shape_view.cpp +0 -306
@@ -1,7 +1,9 @@
1
1
  #include "reflex/selector.h"
2
2
 
3
3
 
4
+ #include <assert.h>
4
5
  #include "reflex/exception.h"
6
+ #include "selector.h"
5
7
 
6
8
 
7
9
  namespace Reflex
@@ -45,10 +47,12 @@ namespace Reflex
45
47
  const TagSet& tags = self->tags;
46
48
  const_iterator tags_end = tags.end();
47
49
 
48
- iterator end = selector.end();
49
- for (iterator tag = selector.begin(); tag != end; ++tag)
50
+ const_iterator end = selector.end();
51
+ for (const_iterator tag = selector.begin(); tag != end; ++tag)
52
+ {
50
53
  if (tags.find(*tag) == tags_end)
51
54
  return false;
55
+ }
52
56
 
53
57
  return selector.self->name.empty() || selector.self->name == self->name;
54
58
  }
@@ -56,13 +60,17 @@ namespace Reflex
56
60
  void
57
61
  Selector::set_name (const char* name)
58
62
  {
59
- self->name = name ? name : "";
63
+ if (name && *name != '\0')
64
+ self->name = name;
65
+ else
66
+ self->name.clear();
60
67
  }
61
68
 
62
69
  const char*
63
70
  Selector::name () const
64
71
  {
65
- return self->name.c_str();
72
+ const String& s = self->name;
73
+ return !s.empty() ? s.c_str() : NULL;
66
74
  }
67
75
 
68
76
  void
@@ -72,7 +80,8 @@ namespace Reflex
72
80
  argument_error(__FILE__, __LINE__);
73
81
 
74
82
  iterator it = self->tags.find(tag);
75
- if (it != self->tags.end()) return;
83
+ if (it != self->tags.end())
84
+ return;
76
85
 
77
86
  self->tags.insert(tag);
78
87
  }
@@ -80,15 +89,31 @@ namespace Reflex
80
89
  void
81
90
  Selector::remove_tag (const char* tag)
82
91
  {
83
- if (!tag || *tag == '\0')
92
+ if (!tag)
84
93
  argument_error(__FILE__, __LINE__);
85
94
 
86
95
  iterator it = self->tags.find(tag);
87
- if (it == self->tags.end()) return;
96
+ if (it == self->tags.end())
97
+ return;
88
98
 
89
99
  self->tags.erase(it);
90
100
  }
91
101
 
102
+ void
103
+ Selector::clear_tags ()
104
+ {
105
+ self->tags.clear();
106
+ }
107
+
108
+ bool
109
+ Selector::has_tag (const char* tag) const
110
+ {
111
+ if (!tag || *tag == '\0')
112
+ return false;
113
+
114
+ return self->tags.find(tag) != self->tags.end();
115
+ }
116
+
92
117
  Selector::iterator
93
118
  Selector::begin ()
94
119
  {
@@ -140,4 +165,204 @@ namespace Reflex
140
165
  }
141
166
 
142
167
 
168
+ static Selector*
169
+ get_selector (SelectorPtr* this_, bool create = false)
170
+ {
171
+ assert(this_);
172
+
173
+ SelectorPtr& ptr = *this_;
174
+
175
+ if (create && !ptr) ptr.reset(new Selector());
176
+ return ptr.get();
177
+ }
178
+
179
+ static const Selector*
180
+ get_selector (const SelectorPtr* this_)
181
+ {
182
+ return get_selector(const_cast<SelectorPtr*>(this_));
183
+ }
184
+
185
+ void
186
+ SelectorPtr::set_name (const char* name)
187
+ {
188
+ get_selector(this, true)->set_name(name);
189
+ }
190
+
191
+ const char*
192
+ SelectorPtr::name () const
193
+ {
194
+ const Selector* sel = get_selector(this);
195
+ return sel ? sel->name() : NULL;
196
+ }
197
+
198
+ void
199
+ SelectorPtr::add_tag (const char* tag)
200
+ {
201
+ get_selector(this, true)->add_tag(tag);
202
+ }
203
+
204
+ void
205
+ SelectorPtr::remove_tag (const char* tag)
206
+ {
207
+ Selector* sel = get_selector(this);
208
+ if (sel) sel->remove_tag(tag);
209
+ }
210
+
211
+ void
212
+ SelectorPtr::clear_tags ()
213
+ {
214
+ Selector* sel = get_selector(this);
215
+ if (sel) sel->clear_tags();
216
+ }
217
+
218
+ bool
219
+ SelectorPtr::has_tag (const char* tag) const
220
+ {
221
+ const Selector* sel = get_selector(this);
222
+ return sel ? sel->has_tag(tag) : false;
223
+ }
224
+
225
+ static Selector::TagSet empty_tags;
226
+
227
+ Selector::iterator
228
+ SelectorPtr::tag_begin ()
229
+ {
230
+ assert(empty_tags.empty());
231
+
232
+ Selector* sel = get_selector(this);
233
+ return sel ? sel->begin() : empty_tags.begin();
234
+ }
235
+
236
+ Selector::const_iterator
237
+ SelectorPtr::tag_begin () const
238
+ {
239
+ return selector().begin();
240
+ }
241
+
242
+ Selector::iterator
243
+ SelectorPtr::tag_end ()
244
+ {
245
+ assert(empty_tags.empty());
246
+
247
+ Selector* sel = get_selector(this);
248
+ return sel ? sel->end() : empty_tags.end();
249
+ }
250
+
251
+ Selector::const_iterator
252
+ SelectorPtr::tag_end () const
253
+ {
254
+ return selector().end();
255
+ }
256
+
257
+ void
258
+ SelectorPtr::set_selector (const Selector& selector)
259
+ {
260
+ *get_selector(this, true) = selector;
261
+ }
262
+
263
+ Selector&
264
+ SelectorPtr::selector ()
265
+ {
266
+ return *get_selector(this, true);
267
+ }
268
+
269
+ const Selector&
270
+ SelectorPtr::selector () const
271
+ {
272
+ static const Selector EMPTY;
273
+
274
+ const Selector* sel = get_selector(this);
275
+ return sel ? *sel : EMPTY;
276
+ }
277
+
278
+
279
+ HasSelector::~HasSelector ()
280
+ {
281
+ }
282
+
283
+ void
284
+ HasSelector::set_name (const char* name)
285
+ {
286
+ get_selector_ptr()->set_name(name);
287
+ }
288
+
289
+ const char*
290
+ HasSelector::name () const
291
+ {
292
+ return get_selector_ptr()->name();
293
+ }
294
+
295
+ void
296
+ HasSelector::add_tag (const char* tag)
297
+ {
298
+ get_selector_ptr()->add_tag(tag);
299
+ }
300
+
301
+ void
302
+ HasSelector::remove_tag (const char* tag)
303
+ {
304
+ get_selector_ptr()->remove_tag(tag);
305
+ }
306
+
307
+ void
308
+ HasSelector::clear_tags ()
309
+ {
310
+ get_selector_ptr()->clear_tags();
311
+ }
312
+
313
+ bool
314
+ HasSelector::has_tag (const char* tag) const
315
+ {
316
+ return get_selector_ptr()->has_tag(tag);
317
+ }
318
+
319
+ Selector::iterator
320
+ HasSelector::tag_begin ()
321
+ {
322
+ return get_selector_ptr()->tag_begin();
323
+ }
324
+
325
+ Selector::const_iterator
326
+ HasSelector::tag_begin () const
327
+ {
328
+ return get_selector_ptr()->tag_begin();
329
+ }
330
+
331
+ Selector::iterator
332
+ HasSelector::tag_end ()
333
+ {
334
+ return get_selector_ptr()->tag_end();
335
+ }
336
+
337
+ Selector::const_iterator
338
+ HasSelector::tag_end () const
339
+ {
340
+ return get_selector_ptr()->tag_end();
341
+ }
342
+
343
+ void
344
+ HasSelector::set_selector (const Selector& selector)
345
+ {
346
+ get_selector_ptr()->set_selector(selector);
347
+ }
348
+
349
+ Selector&
350
+ HasSelector::selector ()
351
+ {
352
+ return get_selector_ptr()->selector();
353
+ }
354
+
355
+ const Selector&
356
+ HasSelector::selector () const
357
+ {
358
+ return get_selector_ptr()->selector();
359
+ }
360
+
361
+ const SelectorPtr*
362
+ HasSelector::get_selector_ptr () const
363
+ {
364
+ return const_cast<HasSelector*>(this)->get_selector_ptr();
365
+ }
366
+
367
+
143
368
  }// Reflex
@@ -0,0 +1,52 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __REFLEX_SRC_SELECTOR_H__
4
+ #define __REFLEX_SRC_SELECTOR_H__
5
+
6
+
7
+ #include <memory>
8
+ #include <reflex/selector.h>
9
+
10
+
11
+ namespace Reflex
12
+ {
13
+
14
+
15
+ class SelectorPtr : public std::unique_ptr<Selector>
16
+ {
17
+
18
+ public:
19
+
20
+ void set_name (const char* name);
21
+
22
+ const char* name () const;
23
+
24
+ void add_tag (const char* tag);
25
+
26
+ void remove_tag (const char* tag);
27
+
28
+ void clear_tags ();
29
+
30
+ bool has_tag (const char* tag) const;
31
+
32
+ Selector:: iterator tag_begin ();
33
+
34
+ Selector::const_iterator tag_begin () const;
35
+
36
+ Selector:: iterator tag_end ();
37
+
38
+ Selector::const_iterator tag_end () const;
39
+
40
+ void set_selector (const Selector& selector);
41
+
42
+ Selector& selector ();
43
+
44
+ const Selector& selector () const;
45
+
46
+ };// SelectorPtr
47
+
48
+
49
+ }// Reflex
50
+
51
+
52
+ #endif//EOH
@@ -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