MTROPOLIS: Handle show/hide events, stub out element transition modifier.

This commit is contained in:
elasota
2022-06-16 21:58:09 +02:00
committed by Eugene Sandulenko
parent a3f5b993e0
commit d00a058d3e
4 changed files with 126 additions and 2 deletions
+80 -1
View File
@@ -885,14 +885,93 @@ bool ElementTransitionModifier::load(ModifierLoaderContext &context, const Data:
return true;
}
bool ElementTransitionModifier::respondsToEvent(const Event &evt) const {
return _enableWhen.respondsTo(evt) || _disableWhen.respondsTo(evt);
}
VThreadState ElementTransitionModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
// How element transition modifiers work:
// - When activated, if Reveal, then Show is sent (regardless of whether element is visible or not).
// - Then, for both reveal and conceal, Transition Started is sent by the modifier.
// - When a conceal transition completes, Hide is sent to the element.
// - Then, for both reveal and conceal, Transition Ended is sent by the modifier.
// - If a transition is active and the Disable signal is called, then the transition completes immediately.
//
// Q. Does that mean if an element has a Revealer followed by a Concealer and they take opposing messages,
// that the element will be hidden if a reveal interrupts the concealer due to its hide message happening
// second, but that won't happen if they're in Concealer-Revealer order?
// A. Yes.
if (_enableWhen.respondsTo(msg->getEvent())) {
if (_scheduledEvent) {
_scheduledEvent->cancel();
_scheduledEvent.reset();
}
_scheduledEvent = runtime->getScheduler().scheduleMethod<ElementTransitionModifier, &ElementTransitionModifier::continueTransition>(runtime->getPlayTime() + 1, this);
// Pushed tasks, so these are executed in reverse order (Show -> Transition Started)
{
Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kTransitionStarted, 0), DynamicValue(), getSelfReference()));
Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, findStructuralOwner(), false, true, false));
runtime->sendMessageOnVThread(dispatch);
}
if (_revealType == kRevealTypeReveal)
{
Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kElementShow, 0), DynamicValue(), getSelfReference()));
Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, findStructuralOwner(), false, false, true));
runtime->sendMessageOnVThread(dispatch);
}
return kVThreadReturn;
}
if (_disableWhen.respondsTo(msg->getEvent())) {
if (_scheduledEvent) {
_scheduledEvent->cancel();
completeTransition(runtime);
}
return kVThreadReturn;
}
return Modifier::consumeMessage(runtime, msg);
}
Common::SharedPtr<Modifier> ElementTransitionModifier::shallowClone() const {
return Common::SharedPtr<Modifier>(new ElementTransitionModifier(*this));
Common::SharedPtr<ElementTransitionModifier> clone(new ElementTransitionModifier(*this));
clone->_scheduledEvent.reset();
return clone;
}
const char *ElementTransitionModifier::getDefaultName() const {
return "Element Transition Modifier";
}
void ElementTransitionModifier::continueTransition(Runtime *runtime) {
// TODO: Make this functional
completeTransition(runtime);
}
void ElementTransitionModifier::completeTransition(Runtime *runtime) {
_scheduledEvent.reset();
// Pushed tasks, so these are executed in reverse order (Hide -> Transition Ended)
{
Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kTransitionEnded, 0), DynamicValue(), getSelfReference()));
Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, findStructuralOwner(), false, true, false));
runtime->sendMessageOnVThread(dispatch);
}
if (_revealType == kRevealTypeConceal) {
Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kElementHide, 0), DynamicValue(), getSelfReference()));
Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, findStructuralOwner(), false, false, true));
runtime->sendMessageOnVThread(dispatch);
}
}
bool IfMessengerModifier::load(ModifierLoaderContext &context, const Data::IfMessengerModifier &data) {
if (!loadTypicalHeader(data.modHeader))
return false;
+9
View File
@@ -368,6 +368,9 @@ class ElementTransitionModifier : public Modifier {
public:
bool load(ModifierLoaderContext &context, const Data::ElementTransitionModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
enum TransitionType {
kTransitionTypeRectangularIris = 0x03e8,
kTransitionTypeOvalIris = 0x03f2,
@@ -382,12 +385,16 @@ public:
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Element Transition Modifier"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusPartial; }
#endif
private:
Common::SharedPtr<Modifier> shallowClone() const override;
const char *getDefaultName() const override;
void continueTransition(Runtime *runtime);
void completeTransition(Runtime *runtime);
Event _enableWhen;
Event _disableWhen;
@@ -395,6 +402,8 @@ private:
uint16 _steps;
TransitionType _transitionType;
RevealType _revealType;
Common::SharedPtr<ScheduledEvent> _scheduledEvent;
};
class IfMessengerModifier : public Modifier {
+35 -1
View File
@@ -6418,6 +6418,36 @@ uint16 VisualElement::getLayer() const {
return _layer;
}
VThreadState VisualElement::consumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
if (Event::create(EventIDs::kElementShow, 0).respondsTo(msg->getEvent())) {
if (!_visible) {
_visible = true;
runtime->setSceneGraphDirty();
}
Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kElementShow, 0), DynamicValue(), getSelfReference()));
Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
runtime->sendMessageOnVThread(dispatch);
return kVThreadReturn;
}
if (Event::create(EventIDs::kElementHide, 0).respondsTo(msg->getEvent())) {
if (_visible) {
_visible = false;
runtime->setSceneGraphDirty();
}
Common::SharedPtr<MessageProperties> msgProps(new MessageProperties(Event::create(EventIDs::kElementHide, 0), DynamicValue(), getSelfReference()));
Common::SharedPtr<MessageDispatch> dispatch(new MessageDispatch(msgProps, this, false, true, false));
runtime->sendMessageOnVThread(dispatch);
return kVThreadReturn;
}
return Element::consumeCommand(runtime, msg);
}
bool VisualElement::isMouseInsideBox(int32 relativeX, int32 relativeY) const {
return relativeX >= _rect.left && relativeX < _rect.right && relativeY >= _rect.top && relativeY < _rect.bottom;
}
@@ -6593,7 +6623,11 @@ void VisualElement::finalizeRender() {
MiniscriptInstructionOutcome VisualElement::scriptSetVisibility(MiniscriptThread *thread, const DynamicValue &result) {
// FIXME: Need to make this fire Show/Hide events!
if (result.getType() == DynamicValueTypes::kBoolean) {
_visible = result.getBool();
const bool targetValue = result.getBool();
if (_visible != targetValue) {
_visible = targetValue;
thread->getRuntime()->setSceneGraphDirty();
}
return kMiniscriptInstructionOutcomeContinue;
}
+2
View File
@@ -2417,6 +2417,8 @@ public:
bool isVisual() const override;
virtual bool isTextLabel() const;
VThreadState consumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg);
bool isVisible() const;
bool isDirectToScreen() const;
uint16 getLayer() const;