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.
- checksums.yaml +5 -5
- data/.doc/ext/reflex/application.cpp +9 -5
- data/.doc/ext/reflex/capture_event.cpp +0 -4
- data/.doc/ext/reflex/contact_event.cpp +17 -10
- data/.doc/ext/reflex/draw_event.cpp +1 -5
- data/.doc/ext/reflex/ellipse_shape.cpp +51 -24
- data/.doc/ext/reflex/event.cpp +0 -4
- data/.doc/ext/reflex/filter.cpp +81 -0
- data/.doc/ext/reflex/focus_event.cpp +9 -13
- data/.doc/ext/reflex/frame_event.cpp +40 -6
- data/.doc/ext/reflex/image_view.cpp +1 -10
- data/.doc/ext/reflex/key_event.cpp +2 -6
- data/.doc/ext/reflex/line_shape.cpp +99 -0
- data/.doc/ext/reflex/motion_event.cpp +75 -0
- data/.doc/ext/reflex/native.cpp +18 -18
- data/.doc/ext/reflex/pointer_event.cpp +5 -11
- data/.doc/ext/reflex/polygon_shape.cpp +65 -0
- data/.doc/ext/reflex/rect_shape.cpp +102 -23
- data/.doc/ext/reflex/reflex.cpp +21 -2
- data/.doc/ext/reflex/scroll_event.cpp +0 -6
- data/.doc/ext/reflex/selector.cpp +43 -15
- data/.doc/ext/reflex/shape.cpp +211 -0
- data/.doc/ext/reflex/style.cpp +359 -185
- data/.doc/ext/reflex/style_length.cpp +163 -35
- data/.doc/ext/reflex/timer.cpp +101 -0
- data/.doc/ext/reflex/timer_event.cpp +123 -0
- data/.doc/ext/reflex/update_event.cpp +11 -6
- data/.doc/ext/reflex/view.cpp +548 -144
- data/.doc/ext/reflex/wheel_event.cpp +0 -22
- data/.doc/ext/reflex/window.cpp +7 -15
- data/README.md +1 -1
- data/Rakefile +14 -12
- data/VERSION +1 -1
- data/ext/reflex/application.cpp +10 -5
- data/ext/reflex/capture_event.cpp +1 -5
- data/ext/reflex/contact_event.cpp +19 -11
- data/ext/reflex/defs.h +5 -2
- data/ext/reflex/draw_event.cpp +2 -6
- data/ext/reflex/ellipse_shape.cpp +56 -25
- data/ext/reflex/event.cpp +0 -4
- data/ext/reflex/extconf.rb +1 -2
- data/ext/reflex/filter.cpp +86 -0
- data/ext/reflex/focus_event.cpp +11 -15
- data/ext/reflex/frame_event.cpp +46 -7
- data/ext/reflex/image_view.cpp +1 -10
- data/ext/reflex/key_event.cpp +3 -7
- data/ext/reflex/line_shape.cpp +104 -0
- data/ext/reflex/motion_event.cpp +79 -0
- data/ext/reflex/native.cpp +18 -18
- data/ext/reflex/pointer_event.cpp +6 -12
- data/ext/reflex/polygon_shape.cpp +68 -0
- data/ext/reflex/rect_shape.cpp +113 -24
- data/ext/reflex/reflex.cpp +21 -2
- data/ext/reflex/scroll_event.cpp +1 -7
- data/ext/reflex/selector.cpp +46 -16
- data/ext/reflex/selector.h +130 -0
- data/ext/reflex/shape.cpp +231 -0
- data/ext/reflex/style.cpp +363 -192
- data/ext/reflex/style_length.cpp +164 -37
- data/ext/reflex/timer.cpp +108 -0
- data/ext/reflex/timer_event.cpp +133 -0
- data/ext/reflex/update_event.cpp +13 -7
- data/ext/reflex/view.cpp +594 -150
- data/ext/reflex/wheel_event.cpp +1 -25
- data/ext/reflex/window.cpp +7 -15
- data/include/reflex/application.h +2 -0
- data/include/reflex/debug.h +22 -0
- data/include/reflex/defs.h +45 -0
- data/include/reflex/event.h +60 -16
- data/include/reflex/exception.h +9 -0
- data/include/reflex/filter.h +56 -0
- data/include/reflex/image_view.h +1 -1
- data/include/reflex/ruby/application.h +17 -9
- data/include/reflex/ruby/event.h +22 -0
- data/include/reflex/ruby/filter.h +69 -0
- data/include/reflex/ruby/selector.h +1 -1
- data/include/reflex/ruby/shape.h +140 -0
- data/include/reflex/ruby/style.h +1 -1
- data/include/reflex/ruby/timer.h +69 -0
- data/include/reflex/ruby/view.h +43 -76
- data/include/reflex/ruby/window.h +17 -32
- data/include/reflex/ruby.h +6 -4
- data/include/reflex/selector.h +54 -2
- data/include/reflex/shape.h +211 -0
- data/include/reflex/style.h +111 -77
- data/include/reflex/timer.h +73 -0
- data/include/reflex/view.h +181 -59
- data/include/reflex/window.h +4 -3
- data/include/reflex.h +5 -4
- data/lib/reflex/application.rb +6 -3
- data/lib/reflex/button.rb +2 -2
- data/lib/reflex/capture_event.rb +7 -6
- data/lib/reflex/contact_event.rb +10 -12
- data/lib/reflex/draw_event.rb +6 -1
- data/lib/reflex/ellipse_shape.rb +27 -0
- data/lib/reflex/filter.rb +18 -0
- data/lib/reflex/fixture.rb +4 -0
- data/lib/reflex/focus_event.rb +10 -12
- data/lib/reflex/frame_event.rb +1 -1
- data/lib/reflex/helper.rb +17 -29
- data/lib/reflex/key_event.rb +13 -11
- data/lib/reflex/line_shape.rb +18 -0
- data/lib/reflex/{texture.rb → matrix.rb} +2 -2
- data/lib/reflex/module.rb +4 -19
- data/lib/reflex/pointer_event.rb +26 -37
- data/lib/reflex/polygon.rb +14 -0
- data/lib/reflex/polygon_shape.rb +23 -0
- data/lib/reflex/polyline.rb +13 -0
- data/lib/reflex/rect_shape.rb +20 -0
- data/lib/reflex/reflex.rb +1 -3
- data/lib/reflex/scroll_event.rb +1 -1
- data/lib/reflex/selector.rb +2 -2
- data/lib/reflex/shape.rb +62 -0
- data/lib/reflex/style.rb +78 -11
- data/lib/reflex/style_length.rb +0 -11
- data/lib/reflex/text_view.rb +7 -24
- data/lib/reflex/timer.rb +30 -0
- data/lib/reflex/timer_event.rb +29 -0
- data/lib/reflex/update_event.rb +1 -1
- data/lib/reflex/view.rb +127 -32
- data/lib/reflex/wheel_event.rb +9 -1
- data/lib/reflex/window.rb +29 -9
- data/lib/reflex.rb +11 -5
- data/lib/reflexion.rb +23 -7
- data/reflex.gemspec +8 -10
- data/samples/bats.rb +4 -4
- data/samples/fans.rb +1 -1
- data/samples/fps.rb +5 -3
- data/samples/hello.rb +4 -6
- data/samples/image.rb +5 -4
- data/samples/ios/hello/hello.xcodeproj/project.pbxproj +0 -2
- data/samples/layout.rb +16 -7
- data/samples/model.rb +10 -7
- data/samples/physics.rb +22 -20
- data/samples/reflexion/breakout.rb +4 -5
- data/samples/reflexion/hello.rb +2 -2
- data/samples/reflexion/jump_action.rb +191 -0
- data/samples/reflexion/noise.rb +23 -0
- data/samples/reflexion/paint.rb +7 -6
- data/samples/reflexion/physics.rb +15 -8
- data/samples/reflexion/pulse.rb +24 -10
- data/samples/shader.rb +8 -6
- data/samples/shapes.rb +63 -14
- data/samples/tree.rb +9 -10
- data/samples/views.rb +3 -3
- data/samples/visuals.rb +2 -5
- data/src/body.cpp +146 -345
- data/src/body.h +91 -0
- data/src/event.cpp +66 -16
- data/src/exception.cpp +13 -3
- data/src/filter.cpp +76 -0
- data/src/fixture.cpp +164 -39
- data/src/fixture.h +85 -0
- data/src/image_view.cpp +4 -4
- data/src/ios/app_delegate.h +5 -10
- data/src/ios/app_delegate.mm +79 -41
- data/src/ios/application.h +32 -0
- data/src/ios/application.mm +35 -25
- data/src/ios/event.mm +8 -4
- data/src/ios/reflex.mm +0 -7
- data/src/ios/view_controller.h +33 -0
- data/src/ios/view_controller.mm +436 -0
- data/src/ios/window.h +40 -0
- data/src/ios/window.mm +59 -250
- data/src/osx/app_delegate.h +5 -10
- data/src/osx/app_delegate.mm +52 -55
- data/src/osx/application.h +32 -0
- data/src/osx/application.mm +44 -39
- data/src/osx/native_window.h +0 -15
- data/src/osx/native_window.mm +131 -115
- data/src/osx/opengl_view.h +0 -2
- data/src/osx/opengl_view.mm +12 -3
- data/src/osx/reflex.mm +0 -9
- data/src/osx/window.h +42 -0
- data/src/osx/window.mm +45 -252
- data/src/selector.cpp +232 -7
- data/src/selector.h +52 -0
- data/src/shape.cpp +1191 -0
- data/src/shape.h +61 -0
- data/src/style.cpp +571 -374
- data/src/style.h +39 -0
- data/src/timer.cpp +291 -0
- data/src/timer.h +55 -0
- data/src/view.cpp +1624 -984
- data/src/view.h +56 -0
- data/src/win32/window.cpp +3 -4
- data/src/window.cpp +275 -20
- data/src/window.h +92 -0
- data/src/world.cpp +112 -111
- data/src/world.h +34 -53
- data/task/box2d.rake +31 -10
- data/test/test_capture_event.rb +8 -6
- data/test/test_pointer_event.rb +85 -0
- data/test/test_selector.rb +1 -1
- data/test/test_shape.rb +71 -0
- data/test/test_style.rb +77 -11
- data/test/test_style_length.rb +42 -13
- data/test/test_view.rb +138 -14
- metadata +109 -210
- data/.doc/ext/reflex/arc_shape.cpp +0 -89
- data/.doc/ext/reflex/body.cpp +0 -299
- data/.doc/ext/reflex/fixture.cpp +0 -101
- data/.doc/ext/reflex/shape_view.cpp +0 -153
- data/ext/reflex/arc_shape.cpp +0 -94
- data/ext/reflex/body.cpp +0 -328
- data/ext/reflex/fixture.cpp +0 -108
- data/ext/reflex/shape_view.cpp +0 -161
- data/include/reflex/bitmap.h +0 -20
- data/include/reflex/body.h +0 -128
- data/include/reflex/bounds.h +0 -20
- data/include/reflex/color.h +0 -20
- data/include/reflex/color_space.h +0 -20
- data/include/reflex/fixture.h +0 -117
- data/include/reflex/font.h +0 -20
- data/include/reflex/image.h +0 -20
- data/include/reflex/matrix.h +0 -20
- data/include/reflex/painter.h +0 -20
- data/include/reflex/point.h +0 -24
- data/include/reflex/ruby/body.h +0 -41
- data/include/reflex/ruby/fixture.h +0 -41
- data/include/reflex/ruby/shape_view.h +0 -96
- data/include/reflex/shader.h +0 -20
- data/include/reflex/shape_view.h +0 -146
- data/include/reflex/texture.h +0 -20
- data/lib/reflex/body.rb +0 -22
- data/lib/reflex/flags.rb +0 -18
- data/lib/reflex/shape_view.rb +0 -25
- data/src/ios/application_data.h +0 -45
- data/src/ios/native_window.h +0 -39
- data/src/ios/native_window.mm +0 -224
- data/src/ios/opengl_view.h +0 -13
- data/src/ios/opengl_view.mm +0 -139
- data/src/ios/window_data.h +0 -75
- data/src/osx/application_data.h +0 -45
- data/src/osx/window_data.h +0 -75
- data/src/physics/Box2D/Box2D.h +0 -68
- data/src/physics/Box2D/Collision/Shapes/b2ChainShape.cpp +0 -193
- data/src/physics/Box2D/Collision/Shapes/b2ChainShape.h +0 -105
- data/src/physics/Box2D/Collision/Shapes/b2CircleShape.cpp +0 -99
- data/src/physics/Box2D/Collision/Shapes/b2CircleShape.h +0 -91
- data/src/physics/Box2D/Collision/Shapes/b2EdgeShape.cpp +0 -138
- data/src/physics/Box2D/Collision/Shapes/b2EdgeShape.h +0 -74
- data/src/physics/Box2D/Collision/Shapes/b2PolygonShape.cpp +0 -467
- data/src/physics/Box2D/Collision/Shapes/b2PolygonShape.h +0 -101
- data/src/physics/Box2D/Collision/Shapes/b2Shape.h +0 -101
- data/src/physics/Box2D/Collision/b2BroadPhase.cpp +0 -119
- data/src/physics/Box2D/Collision/b2BroadPhase.h +0 -257
- data/src/physics/Box2D/Collision/b2CollideCircle.cpp +0 -154
- data/src/physics/Box2D/Collision/b2CollideEdge.cpp +0 -698
- data/src/physics/Box2D/Collision/b2CollidePolygon.cpp +0 -239
- data/src/physics/Box2D/Collision/b2Collision.cpp +0 -252
- data/src/physics/Box2D/Collision/b2Collision.h +0 -277
- data/src/physics/Box2D/Collision/b2Distance.cpp +0 -603
- data/src/physics/Box2D/Collision/b2Distance.h +0 -141
- data/src/physics/Box2D/Collision/b2DynamicTree.cpp +0 -778
- data/src/physics/Box2D/Collision/b2DynamicTree.h +0 -289
- data/src/physics/Box2D/Collision/b2TimeOfImpact.cpp +0 -486
- data/src/physics/Box2D/Collision/b2TimeOfImpact.h +0 -58
- data/src/physics/Box2D/Common/b2BlockAllocator.cpp +0 -215
- data/src/physics/Box2D/Common/b2BlockAllocator.h +0 -62
- data/src/physics/Box2D/Common/b2Draw.cpp +0 -44
- data/src/physics/Box2D/Common/b2Draw.h +0 -86
- data/src/physics/Box2D/Common/b2GrowableStack.h +0 -85
- data/src/physics/Box2D/Common/b2Math.cpp +0 -94
- data/src/physics/Box2D/Common/b2Math.h +0 -720
- data/src/physics/Box2D/Common/b2Settings.cpp +0 -44
- data/src/physics/Box2D/Common/b2Settings.h +0 -151
- data/src/physics/Box2D/Common/b2StackAllocator.cpp +0 -83
- data/src/physics/Box2D/Common/b2StackAllocator.h +0 -60
- data/src/physics/Box2D/Common/b2Timer.cpp +0 -101
- data/src/physics/Box2D/Common/b2Timer.h +0 -50
- data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp +0 -53
- data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.h +0 -39
- data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp +0 -53
- data/src/physics/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.h +0 -39
- data/src/physics/Box2D/Dynamics/Contacts/b2CircleContact.cpp +0 -52
- data/src/physics/Box2D/Dynamics/Contacts/b2CircleContact.h +0 -39
- data/src/physics/Box2D/Dynamics/Contacts/b2Contact.cpp +0 -247
- data/src/physics/Box2D/Dynamics/Contacts/b2Contact.h +0 -349
- data/src/physics/Box2D/Dynamics/Contacts/b2ContactSolver.cpp +0 -838
- data/src/physics/Box2D/Dynamics/Contacts/b2ContactSolver.h +0 -95
- data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp +0 -49
- data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.h +0 -39
- data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp +0 -49
- data/src/physics/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.h +0 -39
- data/src/physics/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp +0 -49
- data/src/physics/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h +0 -38
- data/src/physics/Box2D/Dynamics/Contacts/b2PolygonContact.cpp +0 -52
- data/src/physics/Box2D/Dynamics/Contacts/b2PolygonContact.h +0 -39
- data/src/physics/Box2D/Dynamics/Joints/b2DistanceJoint.cpp +0 -260
- data/src/physics/Box2D/Dynamics/Joints/b2DistanceJoint.h +0 -169
- data/src/physics/Box2D/Dynamics/Joints/b2FrictionJoint.cpp +0 -251
- data/src/physics/Box2D/Dynamics/Joints/b2FrictionJoint.h +0 -119
- data/src/physics/Box2D/Dynamics/Joints/b2GearJoint.cpp +0 -419
- data/src/physics/Box2D/Dynamics/Joints/b2GearJoint.h +0 -125
- data/src/physics/Box2D/Dynamics/Joints/b2Joint.cpp +0 -211
- data/src/physics/Box2D/Dynamics/Joints/b2Joint.h +0 -226
- data/src/physics/Box2D/Dynamics/Joints/b2MotorJoint.cpp +0 -304
- data/src/physics/Box2D/Dynamics/Joints/b2MotorJoint.h +0 -133
- data/src/physics/Box2D/Dynamics/Joints/b2MouseJoint.cpp +0 -222
- data/src/physics/Box2D/Dynamics/Joints/b2MouseJoint.h +0 -129
- data/src/physics/Box2D/Dynamics/Joints/b2PrismaticJoint.cpp +0 -629
- data/src/physics/Box2D/Dynamics/Joints/b2PrismaticJoint.h +0 -196
- data/src/physics/Box2D/Dynamics/Joints/b2PulleyJoint.cpp +0 -348
- data/src/physics/Box2D/Dynamics/Joints/b2PulleyJoint.h +0 -152
- data/src/physics/Box2D/Dynamics/Joints/b2RevoluteJoint.cpp +0 -502
- data/src/physics/Box2D/Dynamics/Joints/b2RevoluteJoint.h +0 -204
- data/src/physics/Box2D/Dynamics/Joints/b2RopeJoint.cpp +0 -241
- data/src/physics/Box2D/Dynamics/Joints/b2RopeJoint.h +0 -114
- data/src/physics/Box2D/Dynamics/Joints/b2WeldJoint.cpp +0 -344
- data/src/physics/Box2D/Dynamics/Joints/b2WeldJoint.h +0 -126
- data/src/physics/Box2D/Dynamics/Joints/b2WheelJoint.cpp +0 -419
- data/src/physics/Box2D/Dynamics/Joints/b2WheelJoint.h +0 -210
- data/src/physics/Box2D/Dynamics/b2Body.cpp +0 -549
- data/src/physics/Box2D/Dynamics/b2Body.h +0 -860
- data/src/physics/Box2D/Dynamics/b2ContactManager.cpp +0 -296
- data/src/physics/Box2D/Dynamics/b2ContactManager.h +0 -52
- data/src/physics/Box2D/Dynamics/b2Fixture.cpp +0 -303
- data/src/physics/Box2D/Dynamics/b2Fixture.h +0 -345
- data/src/physics/Box2D/Dynamics/b2Island.cpp +0 -539
- data/src/physics/Box2D/Dynamics/b2Island.h +0 -93
- data/src/physics/Box2D/Dynamics/b2TimeStep.h +0 -70
- data/src/physics/Box2D/Dynamics/b2World.cpp +0 -1339
- data/src/physics/Box2D/Dynamics/b2World.h +0 -354
- data/src/physics/Box2D/Dynamics/b2WorldCallbacks.cpp +0 -36
- data/src/physics/Box2D/Dynamics/b2WorldCallbacks.h +0 -155
- data/src/physics/Box2D/Rope/b2Rope.cpp +0 -259
- data/src/physics/Box2D/Rope/b2Rope.h +0 -115
- 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
|