reflexion 0.5.3 → 0.7.0
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 +4 -4
- data/.doc/ext/reflex/application.cpp +56 -7
- data/.doc/ext/reflex/capture_event.cpp +1 -1
- data/.doc/ext/reflex/chase_constraint.cpp +84 -0
- data/.doc/ext/reflex/clipboard.cpp +65 -0
- data/.doc/ext/reflex/color_event.cpp +76 -0
- data/.doc/ext/reflex/color_picker.cpp +113 -0
- data/.doc/ext/reflex/constraint.cpp +135 -0
- data/.doc/ext/reflex/contact_event.cpp +1 -1
- data/.doc/ext/reflex/control_change_event.cpp +1 -1
- data/.doc/ext/reflex/device.cpp +1 -1
- data/.doc/ext/reflex/device_event.cpp +1 -1
- data/.doc/ext/reflex/draw_event.cpp +1 -1
- data/.doc/ext/reflex/ellipse_shape.cpp +1 -1
- data/.doc/ext/reflex/event.cpp +1 -1
- data/.doc/ext/reflex/file_dialog.cpp +181 -0
- data/.doc/ext/reflex/file_event.cpp +103 -0
- data/.doc/ext/reflex/filter.cpp +1 -1
- data/.doc/ext/reflex/focus_event.cpp +1 -1
- data/.doc/ext/reflex/frame_event.cpp +1 -1
- data/.doc/ext/reflex/gamepad.cpp +48 -0
- data/.doc/ext/reflex/image_view.cpp +1 -1
- data/.doc/ext/reflex/key_event.cpp +1 -274
- data/.doc/ext/reflex/line_shape.cpp +1 -1
- data/.doc/ext/reflex/link_constraint.cpp +178 -0
- data/.doc/ext/reflex/menu.cpp +303 -0
- data/.doc/ext/reflex/midi.cpp +9 -2
- data/.doc/ext/reflex/midi_event.cpp +1 -1
- data/.doc/ext/reflex/motion_event.cpp +1 -1
- data/.doc/ext/reflex/native.cpp +40 -10
- data/.doc/ext/reflex/note_event.cpp +1 -1
- data/.doc/ext/reflex/pin.cpp +156 -0
- data/.doc/ext/reflex/pointer.cpp +3 -1
- data/.doc/ext/reflex/pointer_event.cpp +3 -3
- data/.doc/ext/reflex/polygon_shape.cpp +1 -1
- data/.doc/ext/reflex/rect_shape.cpp +1 -1
- data/.doc/ext/reflex/reflex.cpp +606 -237
- data/.doc/ext/reflex/screen.cpp +27 -1
- data/.doc/ext/reflex/scroll_event.cpp +1 -1
- data/.doc/ext/reflex/selector.cpp +5 -5
- data/.doc/ext/reflex/shape.cpp +1 -1
- data/.doc/ext/reflex/snap_constraint.cpp +125 -0
- data/.doc/ext/reflex/style.cpp +1 -1
- data/.doc/ext/reflex/style_length.cpp +4 -3
- data/.doc/ext/reflex/text_event.cpp +104 -0
- data/.doc/ext/reflex/timer.cpp +1 -1
- data/.doc/ext/reflex/timer_event.cpp +1 -1
- data/.doc/ext/reflex/update_event.cpp +1 -1
- data/.doc/ext/reflex/view.cpp +206 -79
- data/.doc/ext/reflex/wheel_constraint.cpp +142 -0
- data/.doc/ext/reflex/wheel_event.cpp +1 -1
- data/.doc/ext/reflex/window.cpp +282 -31
- data/.github/workflows/release-gem.yml +2 -40
- data/.github/workflows/tag.yml +5 -28
- data/.github/workflows/test.yml +1 -28
- data/ChangeLog.md +79 -0
- data/Gemfile.lock +13 -8
- data/README.md +1 -0
- data/Rakefile +13 -2
- data/Reflex.podspec +2 -2
- data/VERSION +1 -1
- data/ext/reflex/application.cpp +62 -7
- data/ext/reflex/capture_event.cpp +1 -1
- data/ext/reflex/chase_constraint.cpp +89 -0
- data/ext/reflex/clipboard.cpp +69 -0
- data/ext/reflex/color_event.cpp +80 -0
- data/ext/reflex/color_picker.cpp +121 -0
- data/ext/reflex/constraint.cpp +146 -0
- data/ext/reflex/contact_event.cpp +1 -1
- data/ext/reflex/control_change_event.cpp +1 -1
- data/ext/reflex/device.cpp +1 -1
- data/ext/reflex/device_event.cpp +1 -1
- data/ext/reflex/draw_event.cpp +1 -1
- data/ext/reflex/ellipse_shape.cpp +1 -1
- data/ext/reflex/event.cpp +1 -1
- data/ext/reflex/extconf.rb +4 -2
- data/ext/reflex/file_dialog.cpp +194 -0
- data/ext/reflex/file_event.cpp +108 -0
- data/ext/reflex/filter.cpp +1 -1
- data/ext/reflex/focus_event.cpp +1 -1
- data/ext/reflex/frame_event.cpp +1 -1
- data/ext/reflex/gamepad.cpp +50 -0
- data/ext/reflex/image_view.cpp +1 -1
- data/ext/reflex/key_event.cpp +1 -275
- data/ext/reflex/line_shape.cpp +1 -1
- data/ext/reflex/link_constraint.cpp +194 -0
- data/ext/reflex/menu.cpp +331 -0
- data/ext/reflex/midi.cpp +11 -3
- data/ext/reflex/midi_event.cpp +1 -1
- data/ext/reflex/motion_event.cpp +1 -1
- data/ext/reflex/native.cpp +40 -10
- data/ext/reflex/note_event.cpp +1 -1
- data/ext/reflex/pin.cpp +165 -0
- data/ext/reflex/pointer.cpp +3 -1
- data/ext/reflex/pointer_event.cpp +3 -3
- data/ext/reflex/polygon_shape.cpp +1 -1
- data/ext/reflex/rect_shape.cpp +1 -1
- data/ext/reflex/reflex.cpp +608 -237
- data/ext/reflex/screen.cpp +31 -2
- data/ext/reflex/scroll_event.cpp +1 -1
- data/ext/reflex/selector.cpp +5 -5
- data/ext/reflex/selector.h +10 -10
- data/ext/reflex/shape.cpp +1 -1
- data/ext/reflex/snap_constraint.cpp +135 -0
- data/ext/reflex/style.cpp +1 -1
- data/ext/reflex/style_length.cpp +4 -3
- data/ext/reflex/text_event.cpp +111 -0
- data/ext/reflex/timer.cpp +1 -1
- data/ext/reflex/timer_event.cpp +1 -1
- data/ext/reflex/update_event.cpp +1 -1
- data/ext/reflex/view.cpp +236 -96
- data/ext/reflex/wheel_constraint.cpp +154 -0
- data/ext/reflex/wheel_event.cpp +1 -1
- data/ext/reflex/window.cpp +318 -40
- data/include/reflex/application.h +19 -0
- data/include/reflex/clipboard.h +53 -0
- data/include/reflex/color_picker.h +65 -0
- data/include/reflex/constraint.h +275 -0
- data/include/reflex/defs.h +204 -195
- data/include/reflex/event.h +180 -88
- data/include/reflex/file_dialog.h +73 -0
- data/include/reflex/gamepad.h +3 -0
- data/include/reflex/menu.h +120 -0
- data/include/reflex/midi.h +3 -0
- data/include/reflex/pin.h +68 -0
- data/include/reflex/pointer.h +4 -0
- data/include/reflex/reflex.h +2 -0
- data/include/reflex/ruby/application.h +6 -1
- data/include/reflex/ruby/clipboard.h +23 -0
- data/include/reflex/ruby/color_picker.h +89 -0
- data/include/reflex/ruby/constraint.h +94 -0
- data/include/reflex/ruby/event.h +62 -29
- data/include/reflex/ruby/file_dialog.h +89 -0
- data/include/reflex/ruby/gamepad.h +46 -0
- data/include/reflex/ruby/menu.h +103 -0
- data/include/reflex/ruby/pin.h +40 -0
- data/include/reflex/ruby/reflex.h +3 -0
- data/include/reflex/ruby/view.h +123 -39
- data/include/reflex/ruby/window.h +96 -19
- data/include/reflex/ruby.h +3 -0
- data/include/reflex/screen.h +11 -2
- data/include/reflex/view.h +66 -27
- data/include/reflex/window.h +57 -12
- data/include/reflex.h +8 -0
- data/lib/reflex/application.rb +5 -5
- data/lib/reflex/autoinit.rb +3 -1
- data/lib/reflex/button.rb +3 -3
- data/lib/reflex/chase_constraint.rb +15 -0
- data/lib/reflex/clipboard.rb +19 -0
- data/lib/reflex/color_event.rb +16 -0
- data/lib/reflex/color_picker.rb +45 -0
- data/lib/reflex/constraint.rb +29 -0
- data/lib/reflex/control_change_event.rb +17 -0
- data/lib/reflex/extension.rb +1 -1
- data/lib/reflex/file_dialog.rb +70 -0
- data/lib/reflex/file_event.rb +37 -0
- data/lib/reflex/helper.rb +79 -0
- data/lib/reflex/key_event.rb +14 -14
- data/lib/reflex/link_constraint.rb +31 -0
- data/lib/reflex/menu.rb +92 -0
- data/lib/reflex/model.rb +19 -19
- data/lib/reflex/note_event.rb +1 -1
- data/lib/reflex/pin.rb +39 -0
- data/lib/reflex/pointer.rb +30 -1
- data/lib/reflex/pointer_event.rb +13 -2
- data/lib/reflex/reflex.rb +5 -0
- data/lib/reflex/shape.rb +14 -14
- data/lib/reflex/snap_constraint.rb +28 -0
- data/lib/reflex/style.rb +16 -16
- data/lib/reflex/text_event.rb +40 -0
- data/lib/reflex/timer.rb +3 -3
- data/lib/reflex/view.rb +85 -18
- data/lib/reflex/wheel_constraint.rb +28 -0
- data/lib/reflex/wheel_event.rb +19 -1
- data/lib/reflex/window.rb +25 -13
- data/lib/reflex.rb +23 -8
- data/pod.rake +1 -1
- data/reflex.gemspec +4 -4
- data/samples/constraint.rb +152 -0
- data/samples/ime.rb +100 -0
- data/samples/ios/hello/hello.xcodeproj/project.pbxproj +236 -224
- data/samples/menu.rb +32 -0
- data/samples/model.rb +3 -3
- data/samples/test/alert.rb +93 -0
- data/samples/test/always_on.rb +76 -0
- data/samples/test/app_background.rb +51 -0
- data/samples/test/boundary.rb +75 -0
- data/samples/test/callback_exception.rb +101 -0
- data/samples/test/cancel.rb +53 -0
- data/samples/test/color_picker.rb +63 -0
- data/samples/test/file_dialog.rb +102 -0
- data/samples/window_style.rb +156 -0
- data/src/application.cpp +180 -20
- data/src/application.h +95 -5
- data/src/clipboard.cpp +81 -0
- data/src/color_picker.cpp +113 -0
- data/src/color_picker.h +36 -0
- data/src/constraint.cpp +1662 -0
- data/src/constraint.h +64 -0
- data/src/event.cpp +416 -252
- data/src/event.h +13 -2
- data/src/file_dialog.cpp +163 -0
- data/src/file_dialog.h +52 -0
- data/src/gamepad.cpp +42 -5
- data/src/gamepad.h +4 -0
- data/src/ios/app_delegate.mm +5 -3
- data/src/ios/application.mm +29 -0
- data/src/ios/clipboard.mm +44 -0
- data/src/ios/color_picker.mm +19 -0
- data/src/ios/event.h +6 -2
- data/src/ios/event.mm +31 -12
- data/src/ios/file_dialog.mm +21 -0
- data/src/ios/gamepad.mm +4 -4
- data/src/ios/menu.mm +41 -0
- data/src/ios/reflex.mm +8 -0
- data/src/ios/screen.mm +26 -0
- data/src/ios/view_controller.mm +47 -42
- data/src/ios/window.mm +44 -9
- data/src/menu.cpp +387 -0
- data/src/menu.h +81 -0
- data/src/midi.cpp +61 -31
- data/src/osx/app_delegate.h +4 -0
- data/src/osx/app_delegate.mm +168 -139
- data/src/osx/application.mm +103 -5
- data/src/osx/clipboard.mm +45 -0
- data/src/osx/color_picker.mm +112 -0
- data/src/osx/event.h +10 -0
- data/src/osx/event.mm +114 -30
- data/src/osx/file_dialog.mm +168 -0
- data/src/osx/gamepad.mm +2 -2
- data/src/osx/gamepad_hid.mm +1 -1
- data/src/osx/menu.h +25 -0
- data/src/osx/menu.mm +516 -0
- data/src/osx/native_window.h +16 -2
- data/src/osx/native_window.mm +141 -57
- data/src/osx/opengl_view.h +2 -1
- data/src/osx/opengl_view.mm +229 -37
- data/src/osx/reflex.mm +38 -0
- data/src/osx/screen.mm +36 -0
- data/src/osx/window.mm +117 -24
- data/src/pin.cpp +137 -0
- data/src/pointer.cpp +36 -16
- data/src/pointer.h +10 -0
- data/src/rays.h +46 -0
- data/src/sdl/application.cpp +73 -8
- data/src/sdl/clipboard.cpp +39 -0
- data/src/sdl/color_picker.cpp +18 -0
- data/src/sdl/event.cpp +44 -6
- data/src/sdl/event.h +18 -3
- data/src/sdl/file_dialog.cpp +20 -0
- data/src/sdl/gamepad.cpp +3 -7
- data/src/sdl/menu.cpp +40 -0
- data/src/sdl/reflex.cpp +20 -0
- data/src/sdl/screen.cpp +36 -0
- data/src/sdl/window.cpp +168 -37
- data/src/shape.cpp +15 -10
- data/src/view.cpp +583 -233
- data/src/view.h +22 -4
- data/src/vk.h +416 -0
- data/src/win32/application.cpp +167 -12
- data/src/win32/application.h +20 -0
- data/src/win32/clipboard.cpp +210 -0
- data/src/win32/color_picker.cpp +82 -0
- data/src/win32/event.cpp +123 -11
- data/src/win32/event.h +22 -3
- data/src/win32/file_dialog.cpp +226 -0
- data/src/win32/gamepad.cpp +9 -2
- data/src/win32/menu.cpp +490 -0
- data/src/win32/menu.h +35 -0
- data/src/win32/opengl.cpp +2 -9
- data/src/win32/reflex.cpp +44 -3
- data/src/win32/screen.cpp +164 -3
- data/src/win32/screen.h +8 -0
- data/src/win32/tray.cpp +191 -0
- data/src/win32/tray.h +22 -0
- data/src/win32/vk.cpp +11 -0
- data/src/win32/window.cpp +858 -135
- data/src/win32/window.h +9 -0
- data/src/window.cpp +929 -183
- data/src/window.h +77 -33
- data/src/world.cpp +86 -15
- data/src/world.h +9 -2
- data/test/helper.rb +24 -0
- data/test/test_application.rb +101 -1
- data/test/test_chase_constraint.rb +122 -0
- data/test/test_clipboard.rb +54 -0
- data/test/test_color_event.rb +36 -0
- data/test/test_color_picker.rb +62 -0
- data/test/test_constraint.rb +184 -0
- data/test/test_event.rb +1 -1
- data/test/test_file_dialog.rb +48 -0
- data/test/test_file_event.rb +43 -0
- data/test/test_has_text_preedit.rb +54 -0
- data/test/test_key_event.rb +23 -2
- data/test/test_link_constraint.rb +237 -0
- data/test/test_menu.rb +237 -0
- data/test/test_pin.rb +65 -0
- data/test/test_pointer.rb +50 -26
- data/test/test_pointer_event.rb +25 -10
- data/test/test_reflex.rb +36 -0
- data/test/test_screen.rb +24 -2
- data/test/test_snap_constraint.rb +140 -0
- data/test/test_text_event.rb +54 -0
- data/test/test_view.rb +152 -25
- data/test/test_wheel_constraint.rb +125 -0
- data/test/test_wheel_event.rb +24 -10
- data/test/test_window.rb +205 -43
- metadata +154 -10
- data/.github/workflows/utils.rb +0 -127
data/src/window.h
CHANGED
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
#include <map>
|
|
10
10
|
#include <xot/time.h>
|
|
11
11
|
#include <rays/point.h>
|
|
12
|
+
#include <rays/image.h>
|
|
12
13
|
#include <rays/painter.h>
|
|
13
14
|
#include "reflex/window.h"
|
|
14
15
|
#include "reflex/view.h"
|
|
16
|
+
#include "reflex/menu.h"
|
|
15
17
|
#include "application.h"
|
|
16
18
|
#include "pointer.h"
|
|
17
19
|
|
|
@@ -33,34 +35,54 @@ namespace Reflex
|
|
|
33
35
|
|
|
34
36
|
typedef std::map<View::Ref, CaptureTargetIDList> CaptureMap;
|
|
35
37
|
|
|
38
|
+
typedef std::vector<Xot::WeakRef<View>> WeakViewList;
|
|
39
|
+
|
|
40
|
+
typedef std::map<Pointer::ID, WeakViewList> HoveredViewMap;
|
|
41
|
+
|
|
36
42
|
enum Flag
|
|
37
43
|
{
|
|
38
44
|
|
|
39
|
-
ACTIVE
|
|
45
|
+
ACTIVE = Xot::bit(1, FLAG_LAST),
|
|
46
|
+
|
|
47
|
+
REDRAW = Xot::bit(2, FLAG_LAST),
|
|
48
|
+
|
|
49
|
+
POINTER_THROUGH_PAUSED = Xot::bit(3, FLAG_LAST),
|
|
50
|
+
|
|
51
|
+
POINTER_THROUGH_ENTERED = Xot::bit(4, FLAG_LAST),
|
|
40
52
|
|
|
41
53
|
};// Flag
|
|
42
54
|
|
|
43
55
|
int hide_count = 1;
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
uint flags;
|
|
46
58
|
|
|
47
59
|
Painter painter;
|
|
48
60
|
|
|
61
|
+
Image draw_cache;
|
|
62
|
+
|
|
63
|
+
Painter draw_cache_painter;
|
|
64
|
+
|
|
49
65
|
View::Ref root, focus;
|
|
50
66
|
|
|
67
|
+
Menu::Ref menu;
|
|
68
|
+
|
|
51
69
|
Point prev_position, prev_size;
|
|
52
70
|
|
|
53
71
|
double prev_time_update, prev_time_draw, prev_fps = 0;
|
|
54
72
|
|
|
55
|
-
|
|
73
|
+
int next_pointer_id = 1;
|
|
74
|
+
|
|
75
|
+
uint pointer_cancels = 0;
|
|
56
76
|
|
|
57
|
-
|
|
77
|
+
float pointer_through_alpha = 1;
|
|
58
78
|
|
|
59
79
|
Pointer prev_mouse_pointer;
|
|
60
80
|
|
|
61
81
|
PointerList prev_pointers;
|
|
62
82
|
|
|
63
|
-
|
|
83
|
+
CaptureMap captures;
|
|
84
|
+
|
|
85
|
+
HoveredViewMap hovered_views;
|
|
64
86
|
|
|
65
87
|
Data ();
|
|
66
88
|
|
|
@@ -81,7 +103,9 @@ namespace Reflex
|
|
|
81
103
|
};// Window::Data
|
|
82
104
|
|
|
83
105
|
|
|
84
|
-
|
|
106
|
+
typedef View* (*Window_CreateRootViewFun) ();
|
|
107
|
+
|
|
108
|
+
void Window_set_create_root_view_fun (Window_CreateRootViewFun fun);
|
|
85
109
|
|
|
86
110
|
void Window_register (Window* win);
|
|
87
111
|
|
|
@@ -91,6 +115,49 @@ namespace Reflex
|
|
|
91
115
|
|
|
92
116
|
Window* Window_get_active ();
|
|
93
117
|
|
|
118
|
+
void Window_skip_update_time_of_all (double seconds);
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
void Window_set_focus (Window* window, View* view);
|
|
122
|
+
|
|
123
|
+
void Window_register_capture (
|
|
124
|
+
Window* window, View* view, Pointer::ID target);
|
|
125
|
+
|
|
126
|
+
void Window_unregister_capture (
|
|
127
|
+
Window* window, View* view, Pointer::ID target);
|
|
128
|
+
|
|
129
|
+
void Window_cancel_active_pointers (Window* window);
|
|
130
|
+
|
|
131
|
+
uint Window_get_pointer_cancels (const Window& window);
|
|
132
|
+
|
|
133
|
+
void Window_call_close (Window* window);
|
|
134
|
+
|
|
135
|
+
void Window_call_activate_event (Window* window);
|
|
136
|
+
|
|
137
|
+
void Window_call_deactivate_event (Window* window);
|
|
138
|
+
|
|
139
|
+
void Window_call_update_event (Window* window);
|
|
140
|
+
|
|
141
|
+
void Window_call_draw_event (Window* window, DrawEvent* event);
|
|
142
|
+
|
|
143
|
+
void Window_call_frame_event (Window* window);
|
|
144
|
+
|
|
145
|
+
void Window_call_key_event (
|
|
146
|
+
Window* window, KeyEvent* event, bool capture = true);
|
|
147
|
+
|
|
148
|
+
void Window_call_text_event (
|
|
149
|
+
Window* window, TextEvent* event, bool synthesize_key_events = false);
|
|
150
|
+
|
|
151
|
+
void Window_call_pointer_event (Window* window, PointerEvent* event);
|
|
152
|
+
|
|
153
|
+
void Window_call_wheel_event (Window* window, WheelEvent* event);
|
|
154
|
+
|
|
155
|
+
void Window_call_file_event (Window* window, FileEvent* event);
|
|
156
|
+
|
|
157
|
+
void Window_call_midi_event (Window* window, MIDIEvent* event);
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
Window::Data* Window_create_data ();
|
|
94
161
|
|
|
95
162
|
uint Window_default_flags ();
|
|
96
163
|
|
|
@@ -111,40 +178,17 @@ namespace Reflex
|
|
|
111
178
|
|
|
112
179
|
Bounds Window_get_frame (const Window& window);
|
|
113
180
|
|
|
181
|
+
void Window_set_menu (Window* window, Menu* menu);
|
|
182
|
+
|
|
114
183
|
Screen Window_get_screen (const Window& window);
|
|
115
184
|
|
|
116
185
|
void Window_set_flags (Window* window, uint flags);
|
|
117
186
|
|
|
118
187
|
float Window_get_pixel_density (const Window& window);
|
|
119
188
|
|
|
120
|
-
void
|
|
121
|
-
|
|
122
|
-
void Window_register_capture (
|
|
123
|
-
Window* window, View* view, Pointer::ID target);
|
|
124
|
-
|
|
125
|
-
void Window_unregister_capture (
|
|
126
|
-
Window* window, View* view, Pointer::ID target);
|
|
127
|
-
|
|
128
|
-
void Window_call_activate_event (Window* window);
|
|
129
|
-
|
|
130
|
-
void Window_call_deactivate_event (Window* window);
|
|
131
|
-
|
|
132
|
-
void Window_call_update_event (Window* window);
|
|
133
|
-
|
|
134
|
-
void Window_call_draw_event (Window* window, DrawEvent* event);
|
|
189
|
+
void Window_set_pointer_through (Window* window, bool through);
|
|
135
190
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
void Window_call_pointer_event (Window* window, PointerEvent* event);
|
|
139
|
-
|
|
140
|
-
void Window_call_wheel_event (Window* window, WheelEvent* event);
|
|
141
|
-
|
|
142
|
-
void Window_call_midi_event (Window* window, MIDIEvent* event);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
typedef View* (*Window_CreateRootViewFun) ();
|
|
146
|
-
|
|
147
|
-
void Window_set_create_root_view_fun (Window_CreateRootViewFun fun);
|
|
191
|
+
bool Window_is_pointer_over_and_uncovered (Point* position, const Window& window);
|
|
148
192
|
|
|
149
193
|
|
|
150
194
|
}// Reflex
|
data/src/world.cpp
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
#include <assert.h>
|
|
5
|
+
#include <algorithm>
|
|
5
6
|
#include <memory>
|
|
6
7
|
#include <vector>
|
|
7
8
|
#include <map>
|
|
@@ -9,8 +10,9 @@
|
|
|
9
10
|
#include <box2d/box2d.h>
|
|
10
11
|
#include "reflex/event.h"
|
|
11
12
|
#include "reflex/exception.h"
|
|
12
|
-
#include "shape.h"
|
|
13
13
|
#include "view.h"
|
|
14
|
+
#include "shape.h"
|
|
15
|
+
#include "constraint.h"
|
|
14
16
|
#include "body.h"
|
|
15
17
|
#include "fixture.h"
|
|
16
18
|
|
|
@@ -218,7 +220,7 @@ namespace Reflex
|
|
|
218
220
|
static Shape*
|
|
219
221
|
get_shape (b2ShapeId b2shape)
|
|
220
222
|
{
|
|
221
|
-
if (
|
|
223
|
+
if (!b2Shape_IsValid(b2shape)) return NULL;
|
|
222
224
|
return (Shape*) b2Shape_GetUserData(b2shape);
|
|
223
225
|
}
|
|
224
226
|
|
|
@@ -257,6 +259,11 @@ namespace Reflex
|
|
|
257
259
|
if (!v1 || !v2 || !View_is_active(*v1) || !View_is_active(*v2))
|
|
258
260
|
return;
|
|
259
261
|
|
|
262
|
+
// the first handler is free to remove either view, so hold everything
|
|
263
|
+
// the second one needs until both have run
|
|
264
|
+
Shape::Ref sref1 = s1, sref2 = s2;
|
|
265
|
+
View::Ref vref1 = v1, vref2 = v2;
|
|
266
|
+
|
|
260
267
|
ContactEvent e1(action, s2), e2(action, s1);
|
|
261
268
|
Shape_call_contact_event(s1, &e1);
|
|
262
269
|
Shape_call_contact_event(s2, &e2);
|
|
@@ -274,12 +281,24 @@ namespace Reflex
|
|
|
274
281
|
|
|
275
282
|
bool stepping = false;
|
|
276
283
|
|
|
277
|
-
std::unique_ptr<DebugDraw> debug_draw;
|
|
278
|
-
|
|
279
284
|
// tracked to deliver contact-end events for shapes that Box2D has already
|
|
280
285
|
// forgotten on destruction
|
|
281
286
|
ShapePairMap touching_pairs;
|
|
282
287
|
|
|
288
|
+
std::vector<Xot::WeakRef<Constraint>> constraints;
|
|
289
|
+
|
|
290
|
+
// fixture-less static body for constraints that anchor to the world
|
|
291
|
+
// (e.g. chasing a target point) without affecting any collision
|
|
292
|
+
std::unique_ptr<Body> pground;
|
|
293
|
+
|
|
294
|
+
std::unique_ptr<DebugDraw> pdebug_draw;
|
|
295
|
+
|
|
296
|
+
Body* ground (World* world)
|
|
297
|
+
{
|
|
298
|
+
if (!pground) pground.reset(new Body(world));
|
|
299
|
+
return pground.get();
|
|
300
|
+
}
|
|
301
|
+
|
|
283
302
|
void begin_contact (b2ShapeId b2shape1, b2ShapeId b2shape2, bool is_sensor_event)
|
|
284
303
|
{
|
|
285
304
|
Shape* s1 = get_shape(b2shape1);
|
|
@@ -308,6 +327,9 @@ namespace Reflex
|
|
|
308
327
|
ShapePair pair = it->second;
|
|
309
328
|
touching_pairs.erase(it);
|
|
310
329
|
|
|
330
|
+
if (!b2Shape_IsValid(id1) || !b2Shape_IsValid(id2))
|
|
331
|
+
return;
|
|
332
|
+
|
|
311
333
|
call_contact_events(pair.first, pair.second, ContactEvent::END);
|
|
312
334
|
}
|
|
313
335
|
|
|
@@ -338,6 +360,25 @@ namespace Reflex
|
|
|
338
360
|
}
|
|
339
361
|
}
|
|
340
362
|
|
|
363
|
+
void update_constraints ()
|
|
364
|
+
{
|
|
365
|
+
for (auto& constraint : constraints)
|
|
366
|
+
{
|
|
367
|
+
if (constraint)
|
|
368
|
+
Constraint_on_world_update(constraint);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
void clear_constraints ()
|
|
373
|
+
{
|
|
374
|
+
for (auto& constraint : constraints)
|
|
375
|
+
{
|
|
376
|
+
if (constraint)
|
|
377
|
+
Constraint_on_world_destroyed(constraint);
|
|
378
|
+
}
|
|
379
|
+
constraints.clear();
|
|
380
|
+
}
|
|
381
|
+
|
|
341
382
|
};// World::Data
|
|
342
383
|
|
|
343
384
|
|
|
@@ -361,6 +402,8 @@ namespace Reflex
|
|
|
361
402
|
World::~World ()
|
|
362
403
|
{
|
|
363
404
|
self->touching_pairs.clear();
|
|
405
|
+
self->clear_constraints();
|
|
406
|
+
self->pground.reset();
|
|
364
407
|
|
|
365
408
|
b2DestroyWorld(self->b2world);
|
|
366
409
|
self->b2world = b2_nullWorldId;
|
|
@@ -377,6 +420,8 @@ namespace Reflex
|
|
|
377
420
|
|
|
378
421
|
for (int i = 0; i < count; ++i)
|
|
379
422
|
{
|
|
423
|
+
self->update_constraints();
|
|
424
|
+
|
|
380
425
|
self->stepping = true;
|
|
381
426
|
b2World_Step(self->b2world, dt, 4);
|
|
382
427
|
self->stepping = false;
|
|
@@ -426,19 +471,19 @@ namespace Reflex
|
|
|
426
471
|
if (state == debug()) return;
|
|
427
472
|
|
|
428
473
|
if (state)
|
|
429
|
-
self->
|
|
474
|
+
self->pdebug_draw.reset(new DebugDraw(self->ppm));
|
|
430
475
|
else
|
|
431
|
-
self->
|
|
476
|
+
self->pdebug_draw.reset();
|
|
432
477
|
}
|
|
433
478
|
|
|
434
479
|
bool
|
|
435
480
|
World::debug () const
|
|
436
481
|
{
|
|
437
|
-
return !!self->
|
|
482
|
+
return !!self->pdebug_draw;
|
|
438
483
|
}
|
|
439
484
|
|
|
440
485
|
void
|
|
441
|
-
World::on_update (
|
|
486
|
+
World::on_update ()
|
|
442
487
|
{
|
|
443
488
|
update(DELTA_TIME);
|
|
444
489
|
}
|
|
@@ -446,11 +491,11 @@ namespace Reflex
|
|
|
446
491
|
void
|
|
447
492
|
World::on_draw (Painter* painter)
|
|
448
493
|
{
|
|
449
|
-
if (!self->
|
|
494
|
+
if (!self->pdebug_draw) return;
|
|
450
495
|
|
|
451
|
-
self->
|
|
452
|
-
b2World_Draw(self->b2world, self->
|
|
453
|
-
self->
|
|
496
|
+
self->pdebug_draw->begin(painter);
|
|
497
|
+
b2World_Draw(self->b2world, self->pdebug_draw->b2ptr());
|
|
498
|
+
self->pdebug_draw->end();
|
|
454
499
|
}
|
|
455
500
|
|
|
456
501
|
|
|
@@ -460,10 +505,24 @@ namespace Reflex
|
|
|
460
505
|
return world ? world->self->b2world : b2_nullWorldId;
|
|
461
506
|
}
|
|
462
507
|
|
|
463
|
-
|
|
464
|
-
|
|
508
|
+
void
|
|
509
|
+
World_add_constraint (World* world, Constraint* constraint)
|
|
465
510
|
{
|
|
466
|
-
|
|
511
|
+
if (!world || !constraint)
|
|
512
|
+
argument_error(__FILE__, __LINE__);
|
|
513
|
+
|
|
514
|
+
world->self->constraints.emplace_back(constraint);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
void
|
|
518
|
+
World_remove_constraint (World* world, Constraint* constraint)
|
|
519
|
+
{
|
|
520
|
+
if (!world || !constraint)
|
|
521
|
+
argument_error(__FILE__, __LINE__);
|
|
522
|
+
|
|
523
|
+
std::erase_if(
|
|
524
|
+
world->self->constraints,
|
|
525
|
+
[=](auto& c) {return !c || c == constraint;});
|
|
467
526
|
}
|
|
468
527
|
|
|
469
528
|
void
|
|
@@ -490,6 +549,18 @@ namespace Reflex
|
|
|
490
549
|
call_contact_events(pair.first, pair.second, ContactEvent::END);
|
|
491
550
|
}
|
|
492
551
|
|
|
552
|
+
bool
|
|
553
|
+
World_is_stepping (const World* world)
|
|
554
|
+
{
|
|
555
|
+
return world ? world->self->stepping : false;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const Body*
|
|
559
|
+
World_get_ground (World* world)
|
|
560
|
+
{
|
|
561
|
+
return world ? world->self->ground(world) : NULL;
|
|
562
|
+
}
|
|
563
|
+
|
|
493
564
|
World*
|
|
494
565
|
World_get_temporary ()
|
|
495
566
|
{
|
data/src/world.h
CHANGED
|
@@ -19,6 +19,7 @@ namespace Reflex
|
|
|
19
19
|
|
|
20
20
|
class View;
|
|
21
21
|
class Body;
|
|
22
|
+
class Constraint;
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class World : public Xot::NonCopyable
|
|
@@ -51,7 +52,7 @@ namespace Reflex
|
|
|
51
52
|
|
|
52
53
|
bool debug () const;
|
|
53
54
|
|
|
54
|
-
virtual void on_update (
|
|
55
|
+
virtual void on_update ();
|
|
55
56
|
|
|
56
57
|
virtual void on_draw (Painter* painter);
|
|
57
58
|
|
|
@@ -104,10 +105,16 @@ namespace Reflex
|
|
|
104
105
|
|
|
105
106
|
b2WorldId World_get_id (const World* world);
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
void World_add_constraint (World* world, Constraint* constraint);
|
|
109
|
+
|
|
110
|
+
void World_remove_constraint (World* world, Constraint* constraint);
|
|
108
111
|
|
|
109
112
|
void World_end_contacts_for (World* world, b2ShapeId b2shape);
|
|
110
113
|
|
|
114
|
+
bool World_is_stepping (const World* world);
|
|
115
|
+
|
|
116
|
+
const Body* World_get_ground (World* world);
|
|
117
|
+
|
|
111
118
|
World* World_get_temporary ();
|
|
112
119
|
|
|
113
120
|
|
data/test/helper.rb
CHANGED
|
@@ -8,3 +8,27 @@ require 'reflex'
|
|
|
8
8
|
require 'test/unit'
|
|
9
9
|
|
|
10
10
|
include Xot::Test
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
module HasWindow
|
|
14
|
+
|
|
15
|
+
def window(*args, **kwargs, &block)
|
|
16
|
+
win = Reflex::Window.new(*args, **kwargs, &block)
|
|
17
|
+
(@windows_for_test__ ||= []).push win
|
|
18
|
+
win
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def teardown()
|
|
22
|
+
super
|
|
23
|
+
@windows_for_test__&.each(&:close)
|
|
24
|
+
@windows_for_test__ = nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end# HasWindow
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def assert_equal_point(expected, actual, delta = 0.01, *args)
|
|
31
|
+
assert_in_delta expected.x, actual.x, delta, *args
|
|
32
|
+
assert_in_delta expected.y, actual.y, delta, *args
|
|
33
|
+
assert_in_delta expected.z, actual.z, delta, *args
|
|
34
|
+
end
|
data/test/test_application.rb
CHANGED
|
@@ -5,12 +5,112 @@ class TestApplication < Test::Unit::TestCase
|
|
|
5
5
|
|
|
6
6
|
@@app = Reflex::Application.new
|
|
7
7
|
|
|
8
|
+
def start(&block)
|
|
9
|
+
@@app.on(:start) {|e| block.call}
|
|
10
|
+
@@app.start
|
|
11
|
+
ensure
|
|
12
|
+
@@app.singleton_class.remove_method :on_start
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def omit_on_macos_ci()
|
|
16
|
+
omit 'the macos runner aborts in CoreAnimation on an event loop' if ci? && osx?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_start_returns_on_quit()
|
|
20
|
+
omit_on_macos_ci
|
|
21
|
+
|
|
22
|
+
started = false
|
|
23
|
+
start {started = true; @@app.quit}
|
|
24
|
+
assert_true started
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_start_returns_when_last_window_closed()
|
|
28
|
+
omit_on_macos_ci
|
|
29
|
+
|
|
30
|
+
quit = false
|
|
31
|
+
@@app.on(:quit) {|e| quit = true}
|
|
32
|
+
start {w = Reflex.window; w.on(:update) {|e| w.close}}
|
|
33
|
+
assert_true quit
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_start_raises_on_start_block()
|
|
37
|
+
omit_on_macos_ci
|
|
38
|
+
|
|
39
|
+
e = assert_raise(RuntimeError) {start {raise 'boom'}}
|
|
40
|
+
assert_equal 'boom', e.message
|
|
41
|
+
assert_match(/#{__FILE__}/, e.backtrace.first)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_start_raises_from_window_event()
|
|
45
|
+
omit_on_macos_ci
|
|
46
|
+
|
|
47
|
+
w = nil
|
|
48
|
+
e = assert_raise(RuntimeError) do
|
|
49
|
+
start {w = Reflex::Window.new; w.on(:update) {|e| raise 'in update'}}
|
|
50
|
+
end
|
|
51
|
+
assert_equal 'in update', e.message
|
|
52
|
+
ensure
|
|
53
|
+
w&.close
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_start_passes_exit()
|
|
57
|
+
omit_on_macos_ci
|
|
58
|
+
|
|
59
|
+
e = assert_raise(SystemExit) {start {exit 3}}
|
|
60
|
+
assert_equal 3, e.status
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_start_passes_throw()
|
|
64
|
+
omit_on_macos_ci
|
|
65
|
+
|
|
66
|
+
assert_throw(:tag) {start {throw :tag}}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_start_twice()
|
|
70
|
+
omit_on_macos_ci
|
|
71
|
+
|
|
72
|
+
count = 0
|
|
73
|
+
2.times {start {count += 1; @@app.quit}}
|
|
74
|
+
assert_equal 2, count
|
|
75
|
+
end
|
|
76
|
+
|
|
8
77
|
def test_name()
|
|
9
|
-
|
|
78
|
+
assert_not_empty @@app.name
|
|
79
|
+
|
|
10
80
|
@@app.name = 'AppName'
|
|
11
81
|
assert_equal 'AppName', @@app.name
|
|
12
82
|
end
|
|
13
83
|
|
|
84
|
+
def test_menu()
|
|
85
|
+
m = Reflex::Menu.new
|
|
86
|
+
assert_nil @@app.menu
|
|
87
|
+
@@app.menu = m
|
|
88
|
+
assert_equal m, @@app.menu
|
|
89
|
+
@@app.menu = nil
|
|
90
|
+
assert_nil @@app.menu
|
|
91
|
+
|
|
92
|
+
assert_raise(TypeError) {@@app.menu = 1}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def test_background()
|
|
96
|
+
assert_false @@app.background?
|
|
97
|
+
@@app.background = true
|
|
98
|
+
assert_true @@app.background?
|
|
99
|
+
@@app.background = false
|
|
100
|
+
assert_false @@app.background?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_background_menu()
|
|
104
|
+
m = Reflex::Menu.new
|
|
105
|
+
assert_nil @@app.background_menu
|
|
106
|
+
@@app.background_menu = m
|
|
107
|
+
assert_equal m, @@app.background_menu
|
|
108
|
+
@@app.background_menu = nil
|
|
109
|
+
assert_nil @@app.background_menu
|
|
110
|
+
|
|
111
|
+
assert_raise(TypeError) {@@app.background_menu = 1}
|
|
112
|
+
end
|
|
113
|
+
|
|
14
114
|
def test_inspect()
|
|
15
115
|
assert_match %r|#<Reflex::Application:0x\w{16}>|, @@app.inspect
|
|
16
116
|
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require_relative 'helper'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TestChaseConstraint < Test::Unit::TestCase
|
|
5
|
+
|
|
6
|
+
include HasWindow
|
|
7
|
+
|
|
8
|
+
def view(x = 0, y = 0, w = 50, h = 50, **options, &block)
|
|
9
|
+
Reflex::View.new(
|
|
10
|
+
frame: [x, y, w, h],
|
|
11
|
+
shape: Reflex::RectShape.new(density: 1),
|
|
12
|
+
**options, &block)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def point(...)
|
|
16
|
+
Reflex::Point.new(...)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def setup_views(win = window)
|
|
20
|
+
v1 = view 100, 100, dynamic: true
|
|
21
|
+
v2 = view 200, 100, static: true
|
|
22
|
+
win&.add v1
|
|
23
|
+
win&.add v2
|
|
24
|
+
[v1, v2, win, win&.root]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_initial_state()
|
|
28
|
+
v1, v2, = setup_views
|
|
29
|
+
|
|
30
|
+
assert_equal v1, v1.chase(v2) .pins[0].view
|
|
31
|
+
assert_nil v1.chase(v2) .pins[1].view
|
|
32
|
+
assert_equal v2, v1.chase(v2) .target.view
|
|
33
|
+
assert_nil v1.chase(v2) .force
|
|
34
|
+
assert_equal 1, v1.chase(v2, force: 1) .force
|
|
35
|
+
assert_equal 5, v1.chase(v2) .spring
|
|
36
|
+
assert_equal 2, v1.chase(v2, spring: 2) .spring
|
|
37
|
+
assert_in_delta 0.7, v1.chase(v2) .damping
|
|
38
|
+
assert_in_delta 0.1, v1.chase(v2, damping: 0.1).damping
|
|
39
|
+
assert_false v1.chase(v2) .collide?
|
|
40
|
+
assert_true v1.chase(v2) .active?
|
|
41
|
+
assert_false v1.chase(v2) .removed?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_chase_view()
|
|
45
|
+
v1, v2, _, root = setup_views
|
|
46
|
+
|
|
47
|
+
c = v1.chase v2
|
|
48
|
+
assert_equal v2, c.target.view
|
|
49
|
+
|
|
50
|
+
root.update_world
|
|
51
|
+
assert_operator v1.linear_velocity.x, :>, 0
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_chase_world_point()
|
|
55
|
+
v1, _, _, root = setup_views
|
|
56
|
+
|
|
57
|
+
c = v1.chase [300, 300]
|
|
58
|
+
assert_nil c.target.view
|
|
59
|
+
assert_equal_point point(300, 300), c.target.pos
|
|
60
|
+
|
|
61
|
+
root.update_world
|
|
62
|
+
assert_operator v1.linear_velocity.x, :>, 0
|
|
63
|
+
assert_operator v1.linear_velocity.y, :>, 0
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_grabbing_corner_creates_torque()
|
|
67
|
+
v1, _, _, root = setup_views
|
|
68
|
+
|
|
69
|
+
c = v1.pin(0, 0).chase [300, 100], spring: 8
|
|
70
|
+
assert_equal_point point(0, 0), c.pins[0].pos
|
|
71
|
+
|
|
72
|
+
3.times {root.update_world}
|
|
73
|
+
assert_operator v1.angular_velocity.abs, :>, 1
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_chase_to_itself_error()
|
|
77
|
+
v1, v2, = setup_views
|
|
78
|
+
|
|
79
|
+
assert_raise(ArgumentError) {v1.chase v1}
|
|
80
|
+
assert_raise(ArgumentError) {v1.chase(v2).target = v1}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_target()
|
|
84
|
+
v1, v2, = setup_views
|
|
85
|
+
|
|
86
|
+
c = v1.chase [300, 300]
|
|
87
|
+
assert_nil c.target.view
|
|
88
|
+
assert_equal_point point(300, 300), c.target.pos
|
|
89
|
+
|
|
90
|
+
c.target = v2
|
|
91
|
+
assert_equal v2, c.target.view
|
|
92
|
+
assert_nil c.target.pos
|
|
93
|
+
|
|
94
|
+
c.target = v2.pin(0, 0)
|
|
95
|
+
assert_equal v2, c.target.view
|
|
96
|
+
assert_equal_point point(0, 0), c.target.pos
|
|
97
|
+
|
|
98
|
+
c.target = [v2, 5, 5]
|
|
99
|
+
assert_equal v2, c.target.view
|
|
100
|
+
assert_equal_point point(5, 5), c.target.pos
|
|
101
|
+
|
|
102
|
+
c.target = nil
|
|
103
|
+
assert_nil c.target.view
|
|
104
|
+
assert_nil c.target.pos
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def test_force()
|
|
108
|
+
v1, = setup_views
|
|
109
|
+
|
|
110
|
+
c = v1.chase [300, 100], force: 500
|
|
111
|
+
assert_equal 500, c.force
|
|
112
|
+
|
|
113
|
+
c.force = nil
|
|
114
|
+
assert_nil c.force
|
|
115
|
+
|
|
116
|
+
c.force = 100
|
|
117
|
+
assert_equal 100, c.force
|
|
118
|
+
|
|
119
|
+
assert_raise(ArgumentError) {c.force = -1}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end# TestChaseConstraint
|