mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
add drag event type support (#10807) 2f4ec0a570
* add drag event type support Co-authored-by: hernan <hernan@rive.app>
This commit is contained in:
@@ -1 +1 @@
|
||||
c7a0379ab3bd3ec3fb9b2ed26d5b238b93a26976
|
||||
2f4ec0a57046df283b229974330b4f38bdcaaf70
|
||||
|
||||
@@ -16,6 +16,7 @@ enum class ListenerType : int
|
||||
dragStart = 9,
|
||||
dragEnd = 10,
|
||||
viewModel = 11,
|
||||
drag = 12,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -617,21 +617,24 @@ public:
|
||||
auto listenerType = m_listener->listenerType();
|
||||
return !(listenerType == ListenerType::enter ||
|
||||
listenerType == ListenerType::exit ||
|
||||
listenerType == ListenerType::move);
|
||||
listenerType == ListenerType::move ||
|
||||
listenerType == ListenerType::drag);
|
||||
}
|
||||
|
||||
virtual bool needsDownListener(Component* drawable)
|
||||
{
|
||||
auto listenerType = m_listener->listenerType();
|
||||
return listenerType == ListenerType::down ||
|
||||
listenerType == ListenerType::click;
|
||||
listenerType == ListenerType::click ||
|
||||
listenerType == ListenerType::drag;
|
||||
}
|
||||
|
||||
virtual bool needsUpListener(Component* drawable)
|
||||
{
|
||||
auto listenerType = m_listener->listenerType();
|
||||
return listenerType == ListenerType::up ||
|
||||
listenerType == ListenerType::click;
|
||||
listenerType == ListenerType::click ||
|
||||
listenerType == ListenerType::drag;
|
||||
}
|
||||
|
||||
virtual ProcessEventResult processEvent(
|
||||
@@ -651,6 +654,7 @@ public:
|
||||
// context. In this case, we unhover the group so it is not marked as
|
||||
// previously hovered.
|
||||
auto pointer = pointerData(pointerId);
|
||||
auto prevPhase = pointer->phase;
|
||||
if (!canHit && pointer->isHovered)
|
||||
{
|
||||
pointer->isHovered = false;
|
||||
@@ -690,6 +694,14 @@ public:
|
||||
pointer->phase = GestureClickPhase::out;
|
||||
}
|
||||
}
|
||||
if (prevPhase == GestureClickPhase::down &&
|
||||
(pointer->phase == GestureClickPhase::clicked ||
|
||||
pointer->phase == GestureClickPhase::out) &&
|
||||
m_hasDragged)
|
||||
{
|
||||
stateMachineInstance->dragEnd(position, timeStamp, pointerId);
|
||||
m_hasDragged = false;
|
||||
}
|
||||
auto _listener = listener();
|
||||
// Always update hover states regardless of which specific listener type
|
||||
// we're trying to trigger.
|
||||
@@ -723,6 +735,29 @@ public:
|
||||
stateMachineInstance->markNeedsAdvance();
|
||||
consume();
|
||||
}
|
||||
// Perform changes if:
|
||||
// - the listener type is drag
|
||||
// - the clickPhase is down
|
||||
// - the pointer type is move
|
||||
if (pointer->phase == GestureClickPhase::down &&
|
||||
_listener->listenerType() == ListenerType::drag &&
|
||||
hitEvent == ListenerType::move)
|
||||
{
|
||||
_listener->performChanges(
|
||||
stateMachineInstance,
|
||||
position,
|
||||
Vec2D(previousPosition->x, previousPosition->y));
|
||||
stateMachineInstance->markNeedsAdvance();
|
||||
if (!m_hasDragged)
|
||||
{
|
||||
stateMachineInstance->dragStart(position,
|
||||
timeStamp,
|
||||
false,
|
||||
pointerId);
|
||||
m_hasDragged = true;
|
||||
}
|
||||
consume();
|
||||
}
|
||||
previousPosition->x = position.x;
|
||||
previousPosition->y = position.y;
|
||||
return ProcessEventResult::pointer;
|
||||
@@ -733,6 +768,7 @@ public:
|
||||
private:
|
||||
// Consumed listeners aren't processed again in the current frame
|
||||
bool m_isConsumed = false;
|
||||
bool m_hasDragged = false;
|
||||
const StateMachineListener* m_listener;
|
||||
std::unordered_map<int, _PointerData*> m_pointers;
|
||||
std::vector<_PointerData*> m_pointersPool;
|
||||
@@ -1114,6 +1150,7 @@ public:
|
||||
case ListenerType::draggableConstraint:
|
||||
case ListenerType::textInput:
|
||||
case ListenerType::viewModel:
|
||||
case ListenerType::drag:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1136,6 +1173,7 @@ public:
|
||||
case ListenerType::draggableConstraint:
|
||||
case ListenerType::textInput:
|
||||
case ListenerType::viewModel:
|
||||
case ListenerType::drag:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1246,6 +1284,7 @@ public:
|
||||
case ListenerType::draggableConstraint:
|
||||
case ListenerType::textInput:
|
||||
case ListenerType::viewModel:
|
||||
case ListenerType::drag:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1267,6 +1306,7 @@ public:
|
||||
case ListenerType::draggableConstraint:
|
||||
case ListenerType::textInput:
|
||||
case ListenerType::viewModel:
|
||||
case ListenerType::drag:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
tests/unit_tests/assets/drag_event.riv
Normal file
BIN
tests/unit_tests/assets/drag_event.riv
Normal file
Binary file not shown.
@@ -1388,4 +1388,63 @@ TEST_CASE("Replace view model instance in nested list", "[silver]")
|
||||
}
|
||||
|
||||
CHECK(silver.matches("replace_vm_instance-double-nest"));
|
||||
}
|
||||
|
||||
TEST_CASE("Pointer drag event", "[silver]")
|
||||
{
|
||||
SerializingFactory silver;
|
||||
auto file = ReadRiveFile("assets/drag_event.riv", &silver);
|
||||
|
||||
auto artboard = file->artboardDefault();
|
||||
REQUIRE(artboard != nullptr);
|
||||
|
||||
silver.frameSize(artboard->width(), artboard->height());
|
||||
|
||||
auto stateMachine = artboard->stateMachineAt(0);
|
||||
auto vmi = file->createViewModelInstance(artboard.get()->viewModelId(), 0);
|
||||
|
||||
stateMachine->bindViewModelInstance(vmi);
|
||||
stateMachine->advanceAndApply(0.1f);
|
||||
auto renderer = silver.makeRenderer();
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
silver.addFrame();
|
||||
|
||||
// Clicking on a square without moving will trigger the click on the nested
|
||||
// artboard
|
||||
stateMachine->pointerDown(rive::Vec2D(250, 250));
|
||||
stateMachine->pointerUp(rive::Vec2D(250, 250));
|
||||
stateMachine->advanceAndApply(0.1f);
|
||||
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
silver.addFrame();
|
||||
|
||||
auto coord = 250.0f;
|
||||
stateMachine->pointerDown(rive::Vec2D(coord, coord));
|
||||
stateMachine->advanceAndApply(0.1f);
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
// Drag gesture works and click is cancelled
|
||||
while (coord > 50)
|
||||
{
|
||||
silver.addFrame();
|
||||
stateMachine->pointerMove(rive::Vec2D(coord, coord));
|
||||
stateMachine->advanceAndApply(0.1f);
|
||||
artboard->draw(renderer.get());
|
||||
coord -= 10;
|
||||
}
|
||||
stateMachine->pointerUp(rive::Vec2D(coord, coord));
|
||||
|
||||
silver.addFrame();
|
||||
// Clicking again on a square without moving will trigger the click on the
|
||||
// nested artboard
|
||||
stateMachine->pointerDown(rive::Vec2D(coord, coord));
|
||||
stateMachine->advanceAndApply(0.1f);
|
||||
stateMachine->pointerUp(rive::Vec2D(coord, coord));
|
||||
stateMachine->advanceAndApply(0.1f);
|
||||
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
CHECK(silver.matches("drag_event"));
|
||||
}
|
||||
BIN
tests/unit_tests/silvers/drag_event.sriv
Normal file
BIN
tests/unit_tests/silvers/drag_event.sriv
Normal file
Binary file not shown.
Reference in New Issue
Block a user