reflexion 0.5.2 → 0.6.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 +19 -1
- data/.doc/ext/reflex/chase_constraint.cpp +84 -0
- data/.doc/ext/reflex/clipboard.cpp +65 -0
- data/.doc/ext/reflex/constraint.cpp +135 -0
- data/.doc/ext/reflex/key_event.cpp +6 -6
- data/.doc/ext/reflex/link_constraint.cpp +178 -0
- data/.doc/ext/reflex/menu.cpp +302 -0
- data/.doc/ext/reflex/native.cpp +22 -4
- data/.doc/ext/reflex/pin.cpp +156 -0
- data/.doc/ext/reflex/pointer.cpp +2 -0
- data/.doc/ext/reflex/pointer_event.cpp +1 -1
- data/.doc/ext/reflex/reflex.cpp +42 -7
- data/.doc/ext/reflex/selector.cpp +4 -4
- data/.doc/ext/reflex/snap_constraint.cpp +125 -0
- data/.doc/ext/reflex/style_length.cpp +3 -2
- data/.doc/ext/reflex/view.cpp +96 -23
- data/.doc/ext/reflex/wheel_constraint.cpp +142 -0
- data/.doc/ext/reflex/window.cpp +59 -17
- data/.github/workflows/release-gem.yml +10 -1
- data/.github/workflows/test.yml +9 -0
- data/ChangeLog.md +30 -0
- data/README.md +1 -0
- data/VERSION +1 -1
- data/ext/reflex/application.cpp +21 -1
- data/ext/reflex/chase_constraint.cpp +89 -0
- data/ext/reflex/clipboard.cpp +69 -0
- data/ext/reflex/constraint.cpp +146 -0
- data/ext/reflex/key_event.cpp +6 -6
- data/ext/reflex/link_constraint.cpp +194 -0
- data/ext/reflex/menu.cpp +330 -0
- data/ext/reflex/native.cpp +22 -4
- data/ext/reflex/pin.cpp +165 -0
- data/ext/reflex/pointer.cpp +2 -0
- data/ext/reflex/pointer_event.cpp +1 -1
- data/ext/reflex/reflex.cpp +42 -7
- data/ext/reflex/selector.cpp +4 -4
- data/ext/reflex/selector.h +1 -1
- data/ext/reflex/snap_constraint.cpp +135 -0
- data/ext/reflex/style_length.cpp +3 -2
- data/ext/reflex/view.cpp +117 -37
- data/ext/reflex/wheel_constraint.cpp +154 -0
- data/ext/reflex/window.cpp +65 -18
- data/include/reflex/application.h +9 -0
- data/include/reflex/clipboard.h +53 -0
- data/include/reflex/constraint.h +275 -0
- data/include/reflex/defs.h +204 -195
- data/include/reflex/event.h +2 -0
- data/include/reflex/menu.h +120 -0
- data/include/reflex/pin.h +68 -0
- data/include/reflex/pointer.h +4 -0
- data/include/reflex/ruby/clipboard.h +23 -0
- data/include/reflex/ruby/constraint.h +94 -0
- data/include/reflex/ruby/menu.h +103 -0
- data/include/reflex/ruby/pin.h +40 -0
- data/include/reflex/ruby/view.h +36 -0
- data/include/reflex/ruby/window.h +36 -18
- data/include/reflex/view.h +39 -12
- data/include/reflex/window.h +17 -4
- data/include/reflex.h +5 -0
- data/lib/reflex/chase_constraint.rb +15 -0
- data/lib/reflex/clipboard.rb +19 -0
- data/lib/reflex/constraint.rb +29 -0
- data/lib/reflex/extension.rb +1 -1
- data/lib/reflex/helper.rb +28 -0
- data/lib/reflex/key_event.rb +7 -12
- data/lib/reflex/link_constraint.rb +31 -0
- data/lib/reflex/menu.rb +76 -0
- data/lib/reflex/pin.rb +39 -0
- data/lib/reflex/pointer.rb +18 -0
- data/lib/reflex/pointer_event.rb +1 -1
- data/lib/reflex/snap_constraint.rb +28 -0
- data/lib/reflex/view.rb +56 -4
- data/lib/reflex/wheel_constraint.rb +28 -0
- data/lib/reflex/wheel_event.rb +9 -0
- data/lib/reflex.rb +15 -6
- data/pod.rake +4 -2
- data/reflex.gemspec +3 -3
- data/samples/constraint.rb +152 -0
- data/samples/menu.rb +29 -0
- data/src/application.cpp +21 -2
- data/src/application.h +5 -0
- data/src/clipboard.cpp +81 -0
- data/src/constraint.cpp +1662 -0
- data/src/constraint.h +64 -0
- data/src/event.cpp +7 -1
- data/src/event.h +1 -2
- data/src/ios/application.mm +5 -0
- data/src/ios/clipboard.mm +44 -0
- data/src/ios/event.h +6 -2
- data/src/ios/event.mm +31 -12
- data/src/ios/menu.mm +36 -0
- data/src/ios/view_controller.mm +45 -12
- data/src/ios/window.mm +6 -0
- data/src/menu.cpp +325 -0
- data/src/menu.h +65 -0
- data/src/osx/app_delegate.mm +74 -125
- data/src/osx/application.mm +16 -0
- data/src/osx/clipboard.mm +45 -0
- data/src/osx/event.mm +40 -10
- data/src/osx/menu.h +25 -0
- data/src/osx/menu.mm +372 -0
- data/src/osx/native_window.mm +27 -0
- data/src/osx/opengl_view.mm +51 -0
- data/src/osx/window.mm +11 -0
- data/src/pin.cpp +137 -0
- data/src/pointer.cpp +27 -16
- data/src/pointer.h +6 -0
- data/src/sdl/application.cpp +5 -0
- data/src/sdl/clipboard.cpp +39 -0
- data/src/sdl/event.cpp +20 -3
- data/src/sdl/event.h +6 -3
- data/src/sdl/menu.cpp +35 -0
- data/src/sdl/window.cpp +26 -8
- data/src/view.cpp +313 -52
- data/src/view.h +18 -2
- data/src/win32/application.cpp +5 -0
- data/src/win32/clipboard.cpp +210 -0
- data/src/win32/event.cpp +11 -1
- data/src/win32/event.h +2 -0
- data/src/win32/menu.cpp +352 -0
- data/src/win32/menu.h +27 -0
- data/src/win32/window.cpp +62 -0
- data/src/win32/window.h +3 -0
- data/src/window.cpp +235 -22
- data/src/window.h +13 -2
- data/src/world.cpp +77 -14
- data/src/world.h +9 -2
- data/test/helper.rb +7 -0
- data/test/test_application.rb +11 -0
- data/test/test_chase_constraint.rb +124 -0
- data/test/test_clipboard.rb +54 -0
- data/test/test_constraint.rb +186 -0
- data/test/test_key_event.rb +6 -0
- data/test/test_link_constraint.rb +239 -0
- data/test/test_menu.rb +207 -0
- data/test/test_pin.rb +65 -0
- data/test/test_pointer.rb +23 -9
- data/test/test_pointer_event.rb +1 -1
- data/test/test_snap_constraint.rb +142 -0
- data/test/test_view.rb +113 -23
- data/test/test_wheel_constraint.rb +127 -0
- data/test/test_wheel_event.rb +15 -9
- data/test/test_window.rb +10 -0
- metadata +82 -8
data/src/win32/window.h
CHANGED
data/src/window.cpp
CHANGED
|
@@ -14,14 +14,14 @@ namespace Reflex
|
|
|
14
14
|
{
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
using ViewList = std::vector<View::Ref>;
|
|
18
|
-
|
|
19
17
|
using PointerMap = std::map<Pointer::ID, Pointer>;
|
|
20
18
|
|
|
21
19
|
using ExtractedPointerIDSet = std::set<Pointer::ID>;
|
|
22
20
|
|
|
23
21
|
using CaptureTargetIDList = Window::Data::CaptureTargetIDList;
|
|
24
22
|
|
|
23
|
+
using WeakViewList = Window::Data::WeakViewList;
|
|
24
|
+
|
|
25
25
|
|
|
26
26
|
void
|
|
27
27
|
Window_register (Window* win)
|
|
@@ -176,6 +176,9 @@ namespace Reflex
|
|
|
176
176
|
|
|
177
177
|
Event e;
|
|
178
178
|
window->on_activate(&e);
|
|
179
|
+
if (e.is_blocked()) return;
|
|
180
|
+
|
|
181
|
+
View_activate_tree(window->root(), &e);
|
|
179
182
|
}
|
|
180
183
|
|
|
181
184
|
void
|
|
@@ -183,10 +186,13 @@ namespace Reflex
|
|
|
183
186
|
{
|
|
184
187
|
if (!window) return;
|
|
185
188
|
|
|
189
|
+
Xot::remove_flag(&window->self->flags, Window::Data::ACTIVE);
|
|
190
|
+
|
|
186
191
|
Event e;
|
|
187
192
|
window->on_deactivate(&e);
|
|
193
|
+
if (e.is_blocked()) return;
|
|
188
194
|
|
|
189
|
-
|
|
195
|
+
View_deactivate_tree(window->root(), &e);
|
|
190
196
|
}
|
|
191
197
|
|
|
192
198
|
void
|
|
@@ -288,6 +294,14 @@ namespace Reflex
|
|
|
288
294
|
cleanup_captures(window);
|
|
289
295
|
}
|
|
290
296
|
|
|
297
|
+
static bool
|
|
298
|
+
need_next_pointer_id (const Pointer& pointer, const Pointer& prev_pointer)
|
|
299
|
+
{
|
|
300
|
+
return
|
|
301
|
+
pointer.action() == Pointer::DOWN ||
|
|
302
|
+
prev_pointer.action() == Pointer::UP;
|
|
303
|
+
}
|
|
304
|
+
|
|
291
305
|
static Pointer::ID
|
|
292
306
|
get_next_pointer_id (Window* window)
|
|
293
307
|
{
|
|
@@ -304,14 +318,13 @@ namespace Reflex
|
|
|
304
318
|
|
|
305
319
|
Window::Data* self = window->self.get();
|
|
306
320
|
|
|
307
|
-
auto action = pointer->action();
|
|
308
321
|
auto& prev_pointer = self->prev_mouse_pointer;
|
|
309
322
|
|
|
310
323
|
auto id = prev_pointer ? prev_pointer.id() : get_next_pointer_id(window);
|
|
311
324
|
auto* down = prev_pointer.down();
|
|
312
325
|
if (
|
|
313
326
|
Pointer_mask_flag(prev_pointer, MOUSE_BUTTONS) == 0 &&
|
|
314
|
-
(
|
|
327
|
+
need_next_pointer_id(*pointer, prev_pointer))
|
|
315
328
|
{
|
|
316
329
|
id = get_next_pointer_id(window);
|
|
317
330
|
down = NULL;
|
|
@@ -322,6 +335,7 @@ namespace Reflex
|
|
|
322
335
|
Pointer_set_prev(pointer, &prev_pointer);
|
|
323
336
|
Pointer_set_down(pointer, down);
|
|
324
337
|
|
|
338
|
+
auto action = pointer->action();
|
|
325
339
|
if (action == Pointer::DOWN)
|
|
326
340
|
Pointer_add_flag(pointer, pointer->types() & MOUSE_BUTTONS);
|
|
327
341
|
|
|
@@ -351,6 +365,21 @@ namespace Reflex
|
|
|
351
365
|
});
|
|
352
366
|
}
|
|
353
367
|
|
|
368
|
+
static bool
|
|
369
|
+
is_last_pointer_event (const Pointer& pointer)
|
|
370
|
+
{
|
|
371
|
+
auto action = pointer.action();
|
|
372
|
+
if (action == Pointer::UP || action == Pointer::CANCEL)
|
|
373
|
+
{
|
|
374
|
+
// a mouse cursor and a floatable pen (Apple Pencil) survive their
|
|
375
|
+
// up/cancel; a finger or non-floatable pen ends here.
|
|
376
|
+
return
|
|
377
|
+
!(pointer.types() & Pointer::MOUSE) &&
|
|
378
|
+
!Pointer_is_floatable(pointer);
|
|
379
|
+
}
|
|
380
|
+
return action == Pointer::LEAVE;
|
|
381
|
+
}
|
|
382
|
+
|
|
354
383
|
static void
|
|
355
384
|
setup_pointer (Window* window, Pointer* pointer)
|
|
356
385
|
{
|
|
@@ -362,16 +391,21 @@ namespace Reflex
|
|
|
362
391
|
|
|
363
392
|
if (prev_pointer)
|
|
364
393
|
{
|
|
365
|
-
|
|
394
|
+
if (need_next_pointer_id(*pointer, *prev_pointer))
|
|
395
|
+
Pointer_set_id(pointer, get_next_pointer_id(window));
|
|
396
|
+
else
|
|
397
|
+
{
|
|
398
|
+
Pointer_set_id(pointer, prev_pointer->id());
|
|
399
|
+
Pointer_set_down(pointer, prev_pointer->down());
|
|
400
|
+
}
|
|
401
|
+
Pointer_set_floatable(pointer, Pointer_is_floatable(*prev_pointer));
|
|
366
402
|
Pointer_set_prev(pointer, prev_pointer);
|
|
367
|
-
Pointer_set_down(pointer, prev_pointer->down());
|
|
368
403
|
prev_pointers.erase(it);
|
|
369
404
|
}
|
|
370
405
|
else
|
|
371
406
|
Pointer_set_id(pointer, get_next_pointer_id(window));
|
|
372
407
|
|
|
373
|
-
|
|
374
|
-
if (action != Pointer::UP && action != Pointer::CANCEL)
|
|
408
|
+
if (!is_last_pointer_event(*pointer))
|
|
375
409
|
{
|
|
376
410
|
prev_pointers.emplace_back(*pointer);
|
|
377
411
|
Pointer_set_prev(&prev_pointers.back(), NULL);
|
|
@@ -460,7 +494,7 @@ namespace Reflex
|
|
|
460
494
|
extract_targeted_pointers(&event, extracteds, targets, pointers);
|
|
461
495
|
if (event.empty()) continue;
|
|
462
496
|
|
|
463
|
-
|
|
497
|
+
PointerEvent_to_view_coord(&event, view);
|
|
464
498
|
View_call_pointer_event(const_cast<View*>(view.get()), &event);
|
|
465
499
|
|
|
466
500
|
if (event.is_blocked()) *blocked = true;
|
|
@@ -502,7 +536,7 @@ namespace Reflex
|
|
|
502
536
|
if (!view->window()) continue;
|
|
503
537
|
|
|
504
538
|
PointerEvent e = event.dup();
|
|
505
|
-
|
|
539
|
+
PointerEvent_to_view_coord(&e, view);
|
|
506
540
|
View_call_pointer_event(const_cast<View*>(view.get()), &e);
|
|
507
541
|
|
|
508
542
|
if (e.is_blocked()) *blocked = true;
|
|
@@ -561,6 +595,137 @@ namespace Reflex
|
|
|
561
595
|
if (blocked) event->block();
|
|
562
596
|
}
|
|
563
597
|
|
|
598
|
+
static void
|
|
599
|
+
get_current_hovered_views (
|
|
600
|
+
ViewList* result, Window* window, const Pointer& pointer)
|
|
601
|
+
{
|
|
602
|
+
if (pointer.is_drag())
|
|
603
|
+
{
|
|
604
|
+
// while dragging, only the capturing view(s) take part in enter/leave,
|
|
605
|
+
// tested against their own frame; views merely passed over are ignored.
|
|
606
|
+
for (auto& [view, targets] : window->self->captures)
|
|
607
|
+
{
|
|
608
|
+
if (!view->window()) continue;
|
|
609
|
+
if (std::find(targets.begin(), targets.end(), pointer.id()) == targets.end())
|
|
610
|
+
continue;
|
|
611
|
+
|
|
612
|
+
Point pos = view->from_window(pointer.position());
|
|
613
|
+
if (Bounds(view->frame().size()).is_include(pos))
|
|
614
|
+
result->emplace_back(view);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
else
|
|
618
|
+
View_get_hovered_views(result, window->root(), pointer.position());
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
static WeakViewList*
|
|
622
|
+
get_prev_hovered_views (Window* window, const Pointer& pointer)
|
|
623
|
+
{
|
|
624
|
+
// a mouse pointer gets a fresh id on every click, so follow the prev()
|
|
625
|
+
// chain to keep tracking the same physical pointer across id changes.
|
|
626
|
+
auto& map = window->self->hovered_views;
|
|
627
|
+
|
|
628
|
+
auto it = map.find(pointer.id());
|
|
629
|
+
if (
|
|
630
|
+
it == map.end() &&
|
|
631
|
+
pointer.prev() && pointer.prev()->id() != pointer.id())
|
|
632
|
+
{
|
|
633
|
+
auto prev_it = map.find(pointer.prev()->id());
|
|
634
|
+
if (prev_it != map.end())
|
|
635
|
+
{
|
|
636
|
+
it = map.emplace(pointer.id(), std::move(prev_it->second)).first;
|
|
637
|
+
map.erase(prev_it);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
return it != map.end() ? &it->second : NULL;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
static void
|
|
645
|
+
call_pointer_boundary_event (
|
|
646
|
+
View* view, const Pointer& pointer, Pointer::Action action)
|
|
647
|
+
{
|
|
648
|
+
if (!view->window()) return;
|
|
649
|
+
|
|
650
|
+
Pointer p = pointer;
|
|
651
|
+
Pointer_set_action(&p, action);
|
|
652
|
+
|
|
653
|
+
PointerEvent event(&p, 1);
|
|
654
|
+
PointerEvent_to_view_coord(&event, view);
|
|
655
|
+
View_call_pointer_event(view, &event);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
static void
|
|
659
|
+
call_pointer_boundary_events (
|
|
660
|
+
Window* window, const Pointer& pointer, ViewList* news)
|
|
661
|
+
{
|
|
662
|
+
ViewList olds;
|
|
663
|
+
if (auto* weak_views = get_prev_hovered_views(window, pointer))
|
|
664
|
+
{
|
|
665
|
+
for (auto& view : *weak_views)
|
|
666
|
+
if (view) olds.emplace_back(view.get());
|
|
667
|
+
|
|
668
|
+
for (auto it = olds.rbegin(); it != olds.rend(); ++it)
|
|
669
|
+
{
|
|
670
|
+
if (std::find(news->begin(), news->end(), it->get()) != news->end())
|
|
671
|
+
continue;
|
|
672
|
+
call_pointer_boundary_event(it->get(), pointer, Pointer::LEAVE);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
for (auto& view : *news)
|
|
677
|
+
{
|
|
678
|
+
if (std::find(olds.begin(), olds.end(), view.get()) != olds.end())
|
|
679
|
+
continue;
|
|
680
|
+
call_pointer_boundary_event(view.get(), pointer, Pointer::ENTER);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
auto& map = window->self->hovered_views;
|
|
684
|
+
if (news->empty())
|
|
685
|
+
map.erase(pointer.id());
|
|
686
|
+
else
|
|
687
|
+
map[pointer.id()] = WeakViewList(news->begin(), news->end());
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
static void
|
|
691
|
+
call_pointer_enter_events (Window* window, const auto& pointers)
|
|
692
|
+
{
|
|
693
|
+
for (const auto& pointer : pointers)
|
|
694
|
+
{
|
|
695
|
+
auto a = pointer.action();
|
|
696
|
+
if (a == Pointer::DOWN || a == Pointer::MOVE || a == Pointer::ENTER)
|
|
697
|
+
{
|
|
698
|
+
ViewList views;
|
|
699
|
+
get_current_hovered_views(&views, window, pointer);
|
|
700
|
+
call_pointer_boundary_events(window, pointer, &views);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
static void
|
|
706
|
+
call_pointer_leave_events (Window* window, const auto& pointers)
|
|
707
|
+
{
|
|
708
|
+
for (const auto& pointer : pointers)
|
|
709
|
+
{
|
|
710
|
+
auto a = pointer.action();
|
|
711
|
+
if (a == Pointer::UP || a == Pointer::CANCEL || a == Pointer::LEAVE)
|
|
712
|
+
{
|
|
713
|
+
// a pointer that survives this event keeps hovering whatever is under
|
|
714
|
+
// it; a pointer that ends here hovers nothing and leaves every view.
|
|
715
|
+
ViewList views;
|
|
716
|
+
if (!is_last_pointer_event(pointer))
|
|
717
|
+
get_current_hovered_views(&views, window, pointer);
|
|
718
|
+
call_pointer_boundary_events(window, pointer, &views);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
static bool
|
|
724
|
+
is_boundary_action (Pointer::Action action)
|
|
725
|
+
{
|
|
726
|
+
return action == Pointer::ENTER || action == Pointer::LEAVE;
|
|
727
|
+
}
|
|
728
|
+
|
|
564
729
|
void
|
|
565
730
|
Window_call_pointer_event (Window* window, PointerEvent* event)
|
|
566
731
|
{
|
|
@@ -571,6 +736,10 @@ namespace Reflex
|
|
|
571
736
|
|
|
572
737
|
setup_pointer_event(window, event);
|
|
573
738
|
|
|
739
|
+
bool boundary = !event->empty() && is_boundary_action((*event)[0].action());
|
|
740
|
+
std::vector<Pointer> pointers;
|
|
741
|
+
PointerEvent_each_pointer(event, [&](const auto& p) {pointers.emplace_back(p);});
|
|
742
|
+
|
|
574
743
|
if (!event->empty())
|
|
575
744
|
window->on_pointer(event);
|
|
576
745
|
|
|
@@ -582,18 +751,25 @@ namespace Reflex
|
|
|
582
751
|
case Pointer::UP: window->on_pointer_up(event); break;
|
|
583
752
|
case Pointer::MOVE: window->on_pointer_move(event); break;
|
|
584
753
|
case Pointer::CANCEL: window->on_pointer_cancel(event); break;
|
|
754
|
+
case Pointer::ENTER: window->on_pointer_enter(event); break;
|
|
755
|
+
case Pointer::LEAVE: window->on_pointer_leave(event); break;
|
|
585
756
|
default: break;
|
|
586
757
|
}
|
|
587
758
|
}
|
|
588
759
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
if (!event->empty() && !event->is_blocked())
|
|
760
|
+
call_pointer_enter_events(window, pointers);
|
|
761
|
+
if (!boundary)
|
|
593
762
|
{
|
|
594
|
-
|
|
595
|
-
|
|
763
|
+
if (!event->empty() && !event->is_blocked())
|
|
764
|
+
call_captured_pointer_events(window, event);
|
|
765
|
+
|
|
766
|
+
if (!event->empty() && !event->is_blocked())
|
|
767
|
+
{
|
|
768
|
+
PointerEvent_update_for_child_view(event, window->root());
|
|
769
|
+
View_call_pointer_event(window->root(), event);
|
|
770
|
+
}
|
|
596
771
|
}
|
|
772
|
+
call_pointer_leave_events(window, pointers);
|
|
597
773
|
|
|
598
774
|
cleanup_captures(window);
|
|
599
775
|
}
|
|
@@ -786,6 +962,8 @@ namespace Reflex
|
|
|
786
962
|
on_close(&e);
|
|
787
963
|
if (!force && e.is_blocked()) return;
|
|
788
964
|
|
|
965
|
+
self->hovered_views.clear();
|
|
966
|
+
|
|
789
967
|
View_set_window(self->root.get(), NULL);
|
|
790
968
|
|
|
791
969
|
Window_close(this);
|
|
@@ -809,6 +987,12 @@ namespace Reflex
|
|
|
809
987
|
return point + frame().position();
|
|
810
988
|
}
|
|
811
989
|
|
|
990
|
+
bool
|
|
991
|
+
Window::active () const
|
|
992
|
+
{
|
|
993
|
+
return Xot::has_flag(self->flags, Data::ACTIVE);
|
|
994
|
+
}
|
|
995
|
+
|
|
812
996
|
void
|
|
813
997
|
Window::set_title (const char* title)
|
|
814
998
|
{
|
|
@@ -839,6 +1023,25 @@ namespace Reflex
|
|
|
839
1023
|
return Window_get_frame(*this);
|
|
840
1024
|
}
|
|
841
1025
|
|
|
1026
|
+
void
|
|
1027
|
+
Window::set_menu (Menu* menu)
|
|
1028
|
+
{
|
|
1029
|
+
self->menu = menu;
|
|
1030
|
+
Window_set_menu(this, menu);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
Menu*
|
|
1034
|
+
Window::menu ()
|
|
1035
|
+
{
|
|
1036
|
+
return self->menu.get();
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
const Menu*
|
|
1040
|
+
Window::menu () const
|
|
1041
|
+
{
|
|
1042
|
+
return const_cast<Window*>(this)->menu();
|
|
1043
|
+
}
|
|
1044
|
+
|
|
842
1045
|
void
|
|
843
1046
|
Window::set_flag (uint flags)
|
|
844
1047
|
{
|
|
@@ -924,27 +1127,27 @@ namespace Reflex
|
|
|
924
1127
|
}
|
|
925
1128
|
|
|
926
1129
|
void
|
|
927
|
-
Window::
|
|
1130
|
+
Window::on_show (Event* e)
|
|
928
1131
|
{
|
|
929
1132
|
}
|
|
930
1133
|
|
|
931
1134
|
void
|
|
932
|
-
Window::
|
|
1135
|
+
Window::on_hide (Event* e)
|
|
933
1136
|
{
|
|
934
1137
|
}
|
|
935
1138
|
|
|
936
1139
|
void
|
|
937
|
-
Window::
|
|
1140
|
+
Window::on_close (Event* e)
|
|
938
1141
|
{
|
|
939
1142
|
}
|
|
940
1143
|
|
|
941
1144
|
void
|
|
942
|
-
Window::
|
|
1145
|
+
Window::on_activate (Event* e)
|
|
943
1146
|
{
|
|
944
1147
|
}
|
|
945
1148
|
|
|
946
1149
|
void
|
|
947
|
-
Window::
|
|
1150
|
+
Window::on_deactivate (Event* e)
|
|
948
1151
|
{
|
|
949
1152
|
}
|
|
950
1153
|
|
|
@@ -1008,6 +1211,16 @@ namespace Reflex
|
|
|
1008
1211
|
{
|
|
1009
1212
|
}
|
|
1010
1213
|
|
|
1214
|
+
void
|
|
1215
|
+
Window::on_pointer_enter (PointerEvent* e)
|
|
1216
|
+
{
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
void
|
|
1220
|
+
Window::on_pointer_leave (PointerEvent* e)
|
|
1221
|
+
{
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1011
1224
|
void
|
|
1012
1225
|
Window::on_wheel (WheelEvent* e)
|
|
1013
1226
|
{
|
data/src/window.h
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#include <rays/painter.h>
|
|
13
13
|
#include "reflex/window.h"
|
|
14
14
|
#include "reflex/view.h"
|
|
15
|
+
#include "reflex/menu.h"
|
|
15
16
|
#include "application.h"
|
|
16
17
|
#include "pointer.h"
|
|
17
18
|
|
|
@@ -33,6 +34,10 @@ namespace Reflex
|
|
|
33
34
|
|
|
34
35
|
typedef std::map<View::Ref, CaptureTargetIDList> CaptureMap;
|
|
35
36
|
|
|
37
|
+
typedef std::vector<Xot::WeakRef<View>> WeakViewList;
|
|
38
|
+
|
|
39
|
+
typedef std::map<Pointer::ID, WeakViewList> HoveredViewMap;
|
|
40
|
+
|
|
36
41
|
enum Flag
|
|
37
42
|
{
|
|
38
43
|
|
|
@@ -48,12 +53,12 @@ namespace Reflex
|
|
|
48
53
|
|
|
49
54
|
View::Ref root, focus;
|
|
50
55
|
|
|
56
|
+
Menu::Ref menu;
|
|
57
|
+
|
|
51
58
|
Point prev_position, prev_size;
|
|
52
59
|
|
|
53
60
|
double prev_time_update, prev_time_draw, prev_fps = 0;
|
|
54
61
|
|
|
55
|
-
CaptureMap captures;
|
|
56
|
-
|
|
57
62
|
int next_pointer_id = 1;
|
|
58
63
|
|
|
59
64
|
Pointer prev_mouse_pointer;
|
|
@@ -62,6 +67,10 @@ namespace Reflex
|
|
|
62
67
|
|
|
63
68
|
uint flags;
|
|
64
69
|
|
|
70
|
+
CaptureMap captures;
|
|
71
|
+
|
|
72
|
+
HoveredViewMap hovered_views;
|
|
73
|
+
|
|
65
74
|
Data ();
|
|
66
75
|
|
|
67
76
|
virtual ~Data ();
|
|
@@ -111,6 +120,8 @@ namespace Reflex
|
|
|
111
120
|
|
|
112
121
|
Bounds Window_get_frame (const Window& window);
|
|
113
122
|
|
|
123
|
+
void Window_set_menu (Window* window, Menu* menu);
|
|
124
|
+
|
|
114
125
|
Screen Window_get_screen (const Window& window);
|
|
115
126
|
|
|
116
127
|
void Window_set_flags (Window* window, uint flags);
|
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
|
|
|
@@ -274,12 +276,24 @@ namespace Reflex
|
|
|
274
276
|
|
|
275
277
|
bool stepping = false;
|
|
276
278
|
|
|
277
|
-
std::unique_ptr<DebugDraw> debug_draw;
|
|
278
|
-
|
|
279
279
|
// tracked to deliver contact-end events for shapes that Box2D has already
|
|
280
280
|
// forgotten on destruction
|
|
281
281
|
ShapePairMap touching_pairs;
|
|
282
282
|
|
|
283
|
+
std::vector<Xot::WeakRef<Constraint>> constraints;
|
|
284
|
+
|
|
285
|
+
// fixture-less static body for constraints that anchor to the world
|
|
286
|
+
// (e.g. chasing a target point) without affecting any collision
|
|
287
|
+
std::unique_ptr<Body> pground;
|
|
288
|
+
|
|
289
|
+
std::unique_ptr<DebugDraw> pdebug_draw;
|
|
290
|
+
|
|
291
|
+
Body* ground (World* world)
|
|
292
|
+
{
|
|
293
|
+
if (!pground) pground.reset(new Body(world));
|
|
294
|
+
return pground.get();
|
|
295
|
+
}
|
|
296
|
+
|
|
283
297
|
void begin_contact (b2ShapeId b2shape1, b2ShapeId b2shape2, bool is_sensor_event)
|
|
284
298
|
{
|
|
285
299
|
Shape* s1 = get_shape(b2shape1);
|
|
@@ -338,6 +352,25 @@ namespace Reflex
|
|
|
338
352
|
}
|
|
339
353
|
}
|
|
340
354
|
|
|
355
|
+
void update_constraints ()
|
|
356
|
+
{
|
|
357
|
+
for (auto& constraint : constraints)
|
|
358
|
+
{
|
|
359
|
+
if (constraint)
|
|
360
|
+
Constraint_on_world_update(constraint);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
void clear_constraints ()
|
|
365
|
+
{
|
|
366
|
+
for (auto& constraint : constraints)
|
|
367
|
+
{
|
|
368
|
+
if (constraint)
|
|
369
|
+
Constraint_on_world_destroyed(constraint);
|
|
370
|
+
}
|
|
371
|
+
constraints.clear();
|
|
372
|
+
}
|
|
373
|
+
|
|
341
374
|
};// World::Data
|
|
342
375
|
|
|
343
376
|
|
|
@@ -361,6 +394,8 @@ namespace Reflex
|
|
|
361
394
|
World::~World ()
|
|
362
395
|
{
|
|
363
396
|
self->touching_pairs.clear();
|
|
397
|
+
self->clear_constraints();
|
|
398
|
+
self->pground.reset();
|
|
364
399
|
|
|
365
400
|
b2DestroyWorld(self->b2world);
|
|
366
401
|
self->b2world = b2_nullWorldId;
|
|
@@ -377,6 +412,8 @@ namespace Reflex
|
|
|
377
412
|
|
|
378
413
|
for (int i = 0; i < count; ++i)
|
|
379
414
|
{
|
|
415
|
+
self->update_constraints();
|
|
416
|
+
|
|
380
417
|
self->stepping = true;
|
|
381
418
|
b2World_Step(self->b2world, dt, 4);
|
|
382
419
|
self->stepping = false;
|
|
@@ -426,19 +463,19 @@ namespace Reflex
|
|
|
426
463
|
if (state == debug()) return;
|
|
427
464
|
|
|
428
465
|
if (state)
|
|
429
|
-
self->
|
|
466
|
+
self->pdebug_draw.reset(new DebugDraw(self->ppm));
|
|
430
467
|
else
|
|
431
|
-
self->
|
|
468
|
+
self->pdebug_draw.reset();
|
|
432
469
|
}
|
|
433
470
|
|
|
434
471
|
bool
|
|
435
472
|
World::debug () const
|
|
436
473
|
{
|
|
437
|
-
return !!self->
|
|
474
|
+
return !!self->pdebug_draw;
|
|
438
475
|
}
|
|
439
476
|
|
|
440
477
|
void
|
|
441
|
-
World::on_update (
|
|
478
|
+
World::on_update ()
|
|
442
479
|
{
|
|
443
480
|
update(DELTA_TIME);
|
|
444
481
|
}
|
|
@@ -446,11 +483,11 @@ namespace Reflex
|
|
|
446
483
|
void
|
|
447
484
|
World::on_draw (Painter* painter)
|
|
448
485
|
{
|
|
449
|
-
if (!self->
|
|
486
|
+
if (!self->pdebug_draw) return;
|
|
450
487
|
|
|
451
|
-
self->
|
|
452
|
-
b2World_Draw(self->b2world, self->
|
|
453
|
-
self->
|
|
488
|
+
self->pdebug_draw->begin(painter);
|
|
489
|
+
b2World_Draw(self->b2world, self->pdebug_draw->b2ptr());
|
|
490
|
+
self->pdebug_draw->end();
|
|
454
491
|
}
|
|
455
492
|
|
|
456
493
|
|
|
@@ -460,10 +497,24 @@ namespace Reflex
|
|
|
460
497
|
return world ? world->self->b2world : b2_nullWorldId;
|
|
461
498
|
}
|
|
462
499
|
|
|
463
|
-
|
|
464
|
-
|
|
500
|
+
void
|
|
501
|
+
World_add_constraint (World* world, Constraint* constraint)
|
|
465
502
|
{
|
|
466
|
-
|
|
503
|
+
if (!world || !constraint)
|
|
504
|
+
argument_error(__FILE__, __LINE__);
|
|
505
|
+
|
|
506
|
+
world->self->constraints.emplace_back(constraint);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
void
|
|
510
|
+
World_remove_constraint (World* world, Constraint* constraint)
|
|
511
|
+
{
|
|
512
|
+
if (!world || !constraint)
|
|
513
|
+
argument_error(__FILE__, __LINE__);
|
|
514
|
+
|
|
515
|
+
std::erase_if(
|
|
516
|
+
world->self->constraints,
|
|
517
|
+
[=](auto& c) {return !c || c == constraint;});
|
|
467
518
|
}
|
|
468
519
|
|
|
469
520
|
void
|
|
@@ -490,6 +541,18 @@ namespace Reflex
|
|
|
490
541
|
call_contact_events(pair.first, pair.second, ContactEvent::END);
|
|
491
542
|
}
|
|
492
543
|
|
|
544
|
+
bool
|
|
545
|
+
World_is_stepping (const World* world)
|
|
546
|
+
{
|
|
547
|
+
return world ? world->self->stepping : false;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const Body*
|
|
551
|
+
World_get_ground (World* world)
|
|
552
|
+
{
|
|
553
|
+
return world ? world->self->ground(world) : NULL;
|
|
554
|
+
}
|
|
555
|
+
|
|
493
556
|
World*
|
|
494
557
|
World_get_temporary ()
|
|
495
558
|
{
|
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,10 @@ require 'reflex'
|
|
|
8
8
|
require 'test/unit'
|
|
9
9
|
|
|
10
10
|
include Xot::Test
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def assert_equal_point(expected, actual, delta = 0.01, *args)
|
|
14
|
+
assert_in_delta expected.x, actual.x, delta, *args
|
|
15
|
+
assert_in_delta expected.y, actual.y, delta, *args
|
|
16
|
+
assert_in_delta expected.z, actual.z, delta, *args
|
|
17
|
+
end
|