From a23ed8b519e87db42d2cdf847a3c3e3d919275d0 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Sun, 6 Aug 2023 22:51:17 +0300 Subject: [PATCH] reworking tracking; will not build --- include/tracking/Tracking.hpp | 838 ++-------------- src/tracking/DispatchTracking.cpp | 97 +- src/tracking/Tracking.cpp | 1488 +---------------------------- 3 files changed, 135 insertions(+), 2288 deletions(-) diff --git a/include/tracking/Tracking.hpp b/include/tracking/Tracking.hpp index 757d3090..d6455e0e 100644 --- a/include/tracking/Tracking.hpp +++ b/include/tracking/Tracking.hpp @@ -9,757 +9,99 @@ #include namespace better_edit { - using ObjRefs = std::vector>; - template - using ObjRefTuples = std::vector, T...>>; - - template - struct Transform { - T from, to; - Transform(T const& from, T const& to) : from(from), to(to) {} - static Transform zero() { - return { T(), T() }; - } - - T delta() const { - return to - from; - } - bool isZero() const { - return to == from; - } - }; - - template - using OptTransform = std::optional>; - - struct BE_DLL ColorState { - cocos2d::ccColor3B color; - float opacity; - bool blending; - int playerColor; - int copyColorID; - cocos2d::ccHSVValue copyHSV; - - static ColorState from(ColorAction* action); - void to(ColorAction* action) const; - bool operator==(ColorState const& other) const = default; - }; - - struct BE_DLL ObjColorState { - int base; - cocos2d::ccHSVValue baseHSV; - int detail; - cocos2d::ccHSVValue detailHSV; - bool glow; - - static ObjColorState from(GameObject* obj); - void to(GameObject* obj) const; - bool operator==(ObjColorState const& other) const = default; - }; - - struct BE_DLL ObjState { - std::vector groups; - int editorLayer1; - int editorLayer2; - int zOrder; - ZLayer zLayer; - bool dontFade; - bool dontEnter; - bool groupParent; - bool highDetail; - - static ObjState from(GameObject* obj); - void to(GameObject* obj) const; - bool operator==(ObjState const& other) const = default; - }; - - struct BE_DLL SpecialState { - struct BE_DLL CollisionBlock { - int id; - bool dynamic; - bool operator==(CollisionBlock const&) const = default; - }; - - struct BE_DLL Counter { - int id; - bool operator==(Counter const&) const = default; - }; - - struct BE_DLL Saw { - int degrees; // 0 is default - bool disable; - bool operator==(Saw const&) const = default; - }; - - struct BE_DLL OrbPadPortal { - bool multiActivate; - bool operator==(OrbPadPortal const&) const = default; - }; - - struct BE_DLL ToggleOrb { - int targetGroupID; - bool activateGroup; - bool multiActivate; - bool operator==(ToggleOrb const&) const = default; - }; - - struct BE_DLL Collectible { - int pickupMode; - int itemID; - bool subtractCount; - int groupID; - bool enableGroup; - bool operator==(Collectible const&) const = default; - }; - - struct BE_DLL Pulse { - bool randomizeStart; - float speed; - bool operator==(Pulse const&) const = default; - }; - - std::variant< - CollisionBlock, Counter, Saw, OrbPadPortal, - ToggleOrb, Collectible, Pulse - > props; - - static std::optional from(GameObject* obj); - void to(GameObject* obj) const; - bool operator==(SpecialState const&) const = default; - }; - - struct BE_DLL TriggerState { - struct BE_DLL Color { - int channel; - float fadeTime; - cocos2d::ccColor3B color; - float opacity; - bool blending; - bool playerColor1; - bool playerColor2; - int copyID; - cocos2d::ccHSVValue copyHSV; - bool copyOpacity; - // for some reason default doesn't work for this one - inline bool operator==(Color const& other) const { - return channel == other.channel && - fadeTime == other.fadeTime && - color == other.color && - opacity == other.opacity && - blending == other.blending && - playerColor1 == other.playerColor1 && - playerColor2 == other.playerColor2 && - copyID == other.copyID && - copyHSV == other.copyHSV && - copyOpacity == other.copyOpacity; - } - }; - - struct BE_DLL Move { - float x; - float y; - bool lockToPlayerX; - bool lockToPlayerY; - EasingType easing; - float easingRate; - float time; - int targetGroupID; - bool useTarget; - int followGroupID; - MoveTargetType followType; - bool operator==(Move const&) const = default; - }; - - struct BE_DLL Stop { - int targetGroupID; - bool operator==(Stop const&) const = default; - }; - - struct BE_DLL Pulse { - int targetID; - bool targetGroup; - bool mainOnly; - bool detailOnly; - cocos2d::ccColor3B color; - bool pulseHSV; - int copyID; - cocos2d::ccHSVValue copyHSV; - float fadeIn; - float hold; - float fadeOut; - bool exclusive; - bool operator==(Pulse const&) const = default; - }; - - struct BE_DLL Alpha { - int targetGroupID; - float time; - float opacity; - bool operator==(Alpha const&) const = default; - }; - - struct BE_DLL Toggle { - int targetGroupID; - bool activateGroup; - bool operator==(Toggle const&) const = default; - }; - - struct BE_DLL Spawn { - int targetGroupID; - float delayTime; - bool editorDisable; - bool operator==(Spawn const&) const = default; - }; - - struct BE_DLL Rotate { - int targetGroupID; - int centerGroupID; - int degrees; - int times360; - bool lockObjectRotation; - EasingType easing; - float easingRate; - float time; - bool operator==(Rotate const&) const = default; - }; - - struct BE_DLL Follow { - int targetGroupID; - int followGroupID; - float xMod; - float yMod; - float time; - bool operator==(Follow const&) const = default; - }; - - struct BE_DLL Shake { - float strength; - float interval; - float duration; - bool operator==(Shake const&) const = default; - }; - - struct BE_DLL Animation { - int targetGroupID; - int animationID; - bool operator==(Animation const&) const = default; - }; - - struct BE_DLL FollowPlayerY { - int targetGroupID; - float speed; - float delay; - int offset; - float maxSpeed; - float time; - bool operator==(FollowPlayerY const&) const = default; - }; - - struct BE_DLL Touch { - int targetGroupID; - bool dualMode; - bool holdMode; - TouchToggleMode toggleMode; - bool operator==(Touch const&) const = default; - }; - - struct BE_DLL Count { - int itemID; - int targetGroupID; - int targetCount; - bool activateGroup; - bool multiActivate; - bool operator==(Count const&) const = default; - }; - - struct BE_DLL InstantCount { - int itemID; - int targetGroupID; - int targetCount; - bool activateGroup; - ComparisonType comparisonType; - bool operator==(InstantCount const&) const = default; - }; - - struct BE_DLL Pickup { - int itemID; - int count; - bool operator==(Pickup const&) const = default; - }; - - struct BE_DLL Collision { - int blockAID; - int blockBID; - int targetID; - bool activateGroup; - bool triggerOnExit; - bool operator==(Collision const&) const = default; - }; - - struct BE_DLL OnDeath { - int targetGroupID; - bool activateGroup; - bool operator==(OnDeath const&) const = default; - }; - - std::variant< - Color, Move, Stop, Pulse, Alpha, Toggle, Spawn, Rotate, - Follow, Shake, Animation, FollowPlayerY, - Touch, Count, InstantCount, Pickup, Collision, OnDeath - > props; - - // shared - bool touchTrigger; - bool spawnTrigger; - bool multiTrigger; - - static std::optional from(EffectGameObject* obj); - void to(EffectGameObject* obj) const; - bool operator==(TriggerState const&) const = default; - }; - - struct BE_DLL LevelSettingsState { - Speed speed; - int mode; - bool flipGravity; - bool mini; - bool dual; - bool twoPlayer; - float songOffset; - bool fadeIn; - bool fadeOut; - int bg; - int ground; - int groundLine; - int font; - - static LevelSettingsState from(LevelSettingsObject* obj); - void to(LevelSettingsObject* obj) const; - bool operator==(LevelSettingsState const& other) const = default; - }; - - struct BE_DLL BlockAll { - static inline BlockAll* s_current = nullptr; - static bool blocked(); - BlockAll(); - ~BlockAll(); - }; - - BE_DLL std::string toDiffString(geode::Ref obj); - BE_DLL std::string toDiffString(cocos2d::CCPoint const& point); - BE_DLL std::string toDiffString(bool value); - BE_DLL std::string toDiffString(ZLayer const& value); - BE_DLL std::string toDiffString(cocos2d::ccHSVValue const& value); - BE_DLL std::string toDiffString(cocos2d::ccColor3B const& value); - BE_DLL std::string toDiffString(cocos2d::ccColor4B const& value); - BE_DLL std::string toDiffString(ColorState const& value); - BE_DLL std::string toDiffString(ObjColorState const& value); - BE_DLL std::string toDiffString(ObjState const& value); - BE_DLL std::string toDiffString(LevelSettingsState const& value); - BE_DLL std::string toDiffString(TriggerState const& value); - BE_DLL std::string toDiffString(SpecialState const& value); - BE_DLL std::string toDiffString(std::vector const& value); - - template - std::string toDiffString(T const& value) { - if constexpr (std::is_enum_v) { - return fmt::format("{}", static_cast(value)); - } - else { - return fmt::format("{}", value); - } - } - - template - std::string toDiffString(Transform const& value) { - return toDiffString(value.from) + "," + toDiffString(value.to); - } - - template - std::string toDiffString(OptTransform const& value) { - return value ? toDiffString(value.value()) : "_"; - } - - template - std::string toDiffString(std::tuple const& tuple, std::index_sequence) { - std::string ret = ""; - ((ret += (Is == 0 ? "" : ",") + toDiffString(std::get(tuple))), ...); - return ret; - } - - template - std::string toDiffString(std::tuple const& tuple) { - return toDiffString(tuple, std::index_sequence_for {}); - } - - template - std::string toDiffString(std::vector const& objs) { - std::string res = ""; - bool first = true; - for (auto& obj : objs) { - if (!first) { - res += ";"; - } - first = false; - res += toDiffString(obj); - } - return res; - } - - template - std::string toDiffStringImpl2(std::index_sequence, T&&... value) { - std::string ret = ""; - ((ret += (Is == 0 ? "" : ",") + toDiffString(value)), ...); - return ret; - } - - template - std::string toDiffStringImpl(T&&... value) { - return toDiffStringImpl2(std::index_sequence_for {}, std::forward(value)...); - } - - template - std::string toDiffString(A&& a, B&& b, T&&... value) { - return toDiffStringImpl( - std::forward(a), std::forward(b), std::forward(value)... - ); - } - - template - std::string fmtDiffStringImpl(std::string_view const& str, Args&&... args, std::index_sequence) { - std::string ret { str }; - ret.push_back(' '); - ((ret += (Is == 0 ? "" : ":") + toDiffString(args)), ...); - return ret; - } - - template - std::string fmtDiffString(std::string_view const& str, Args&&... args) { - return fmtDiffStringImpl(str, std::forward(args)..., std::index_sequence_for {}); - } - - struct BE_DLL Detail { - std::string info; - std::optional icon; - - bool operator==(Detail const& other) const; - }; - - struct BE_DLL EditorEventData { - virtual std::string toDiffString() const = 0; - virtual void undo() const = 0; - virtual void redo() const = 0; - virtual EditorEventData* clone() const = 0; - virtual std::vector details() const = 0; - virtual ~EditorEventData() = default; - }; - - struct BE_DLL ObjEventData : public EditorEventData { - geode::Ref obj; - ObjEventData(geode::Ref obj); - - virtual std::string getIconName() const = 0; - virtual std::string getDescFmt() const = 0; - }; - - struct BE_DLL ObjPlaced : public ObjEventData { - cocos2d::CCPoint pos; - inline ObjPlaced(geode::Ref obj, cocos2d::CCPoint const& pos) - : ObjEventData(obj), pos(pos) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL ObjRemoved : public ObjEventData { - inline ObjRemoved(geode::Ref obj) - : ObjEventData(obj) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL ObjPasted : public ObjEventData { - geode::Ref src; - inline ObjPasted(geode::Ref obj, geode::Ref src) - : ObjEventData(obj), src(src) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL ObjTransformed : public ObjEventData { - Transform pos; - Transform angle; - Transform scale; - Transform flipX; - Transform flipY; - - inline ObjTransformed( - geode::Ref obj, - Transform const& pos, - Transform const& angle, - Transform const& scale, - Transform const& flipX, - Transform const& flipY - ) : ObjEventData(obj), - pos(pos), angle(angle), scale(scale), - flipX(flipX), flipY(flipY) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL ObjColored : public ObjEventData { - Transform color; - inline ObjColored(geode::Ref obj, Transform const& color) - : ObjEventData(obj), color(color) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL ObjPropsChanged : public ObjEventData { - Transform state; - - inline ObjPropsChanged(geode::Ref obj, Transform const& state) - : ObjEventData(obj), state(state) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL ObjSelected : public ObjEventData { - inline ObjSelected(geode::Ref obj) - : ObjEventData(obj) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL ObjDeselected : public ObjEventData { - inline ObjDeselected(geode::Ref obj) - : ObjEventData(obj) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL StartPosChanged : public ObjEventData { - Transform state; - - inline StartPosChanged(geode::Ref obj, Transform const& state) - : ObjEventData(obj.data()), state(state) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL TriggerPropsChanged : public ObjEventData { - Transform state; - - inline TriggerPropsChanged(geode::Ref obj, Transform const& state) - : ObjEventData(obj.data()), state(state) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL SpecialPropsChanged : public ObjEventData { - Transform state; - - inline SpecialPropsChanged(geode::Ref obj, Transform const& state) - : ObjEventData(obj.data()), state(state) {} - - std::string toDiffString() const override; - EditorEventData* clone() const override; - void undo() const override; - void redo() const override; - std::vector details() const override; - - std::string getIconName() const override; - std::string getDescFmt() const override; - }; - - struct BE_DLL EditorEvent : public geode::Event, public EditorEventData { - virtual std::string desc() const = 0; - virtual cocos2d::CCNode* icon() const = 0; - std::unique_ptr unique() const; - }; - - struct BE_DLL ColorChannelEvent : public EditorEvent { - int channel; - Transform state; - - inline ColorChannelEvent(int channel, Transform const& state) - : channel(channel), state(state) {} - - std::string toDiffString() const override; - void undo() const override; - void redo() const override; - EditorEventData* clone() const override; - std::vector details() const override; - - cocos2d::CCNode* icon() const override; - std::string desc() const override; - }; - - struct BE_DLL LevelSettingsChanged : public EditorEvent { - Transform state; - - inline LevelSettingsChanged(Transform const& state) - : state(state) {} - - std::string toDiffString() const override; - void undo() const override; - void redo() const override; - EditorEventData* clone() const override; - std::vector details() const override; - - cocos2d::CCNode* icon() const override; - std::string desc() const override; - }; - - template - requires std::is_base_of_v - struct MultiObjEvent : public EditorEvent { - std::vector events; - MultiObjEvent(std::vector const& events) : events(events) {} - std::string toDiffString() const override { - std::string res = ""; - bool first = true; - for (auto& ev : events) { - if (!first) { - res += "&"; - } - first = false; - res += ev.toDiffString(); - } - return res; - } - - EditorEventData* clone() const override { - return new MultiObjEvent(events); - } - - void undo() const override { - for (auto& ev : events) { - ev.undo(); - } - } - - void redo() const override { - for (auto& ev : events) { - ev.redo(); - } - } - - std::vector details() const override { - std::vector res; - for (auto& ev : events) { - for (auto& detail : ev.details()) { - if (!geode::utils::ranges::contains(res, detail)) { - res.push_back(detail); - } - if (res.size() > 6) break; - } - if (res.size() > 6) break; - } - return res; - } - - cocos2d::CCNode* icon() const override { - if (events.empty()) { - return nullptr; - } - auto base = cocos2d::CCSprite::createWithSpriteFrameName("square_01_001.png"); - auto top = cocos2d::CCSprite::createWithSpriteFrameName(events.at(0).getIconName().c_str()); - top->setPosition({ base->getContentSize().width - 5.f, 5.f }); - base->addChild(top); - base->setScale(.5f); - return base; - } + // based on https://github.com/Wyliemaster/gddocs/blob/master/docs/resources/client/level-components/level-object.md + enum class ObjectKey { + ID = 1, + X = 2, + Y = 3, + FlipX = 4, + FlipY = 5, + Angle = 6, + ColorTriggerRed = 7, + ColorTriggerGreen = 8, + ColorTriggerBlue = 9, + TriggerDuration = 10, + TriggerTouchTrigger = 11, + // SecretCoinID = 12, + Checked = 13, + BGColorTriggerTintGround= 14, + ColorTriggerP1 = 15, + ColorTriggerP2 = 16, + ColorTriggerBlending = 17, + ColorChannelIDLegacy = 19, + }; + + template + concept IsOneOf = (std::is_same_v || ...); + + struct StateValue { + using Value = std::variant< + bool, + float, + int, + cocos2d::ccColor3B, + cocos2d::ccHSVValue, + ZLayer, + EasingType, + MoveTargetType, + TouchToggleMode, + ComparisonType, + Speed, + cocos2d::CCPoint, + std::vector, // groups + >; + Value value; + + static StateValue from(GameObject* obj, ObjectKey key); + }; + + struct BE_DLL ChangedState { + StateValue from, to; + ChangedState(StateValue const& from, StateValue const& to); + }; + + struct BE_DLL BlockEventsHandle final { + BlockEventsHandle(); + ~BlockEventsHandle(); + BlockEventsHandle(BlockEventsHandle const&) = delete; + BlockEventsHandle(BlockEventsHandle&&) = delete; + }; + + // todo: use a vector for smaller memory footprint + using ObjectKeyMap = std::unordered_map; + + class BE_DLL EditorEvent : public geode::Event { + public: + using ObjectPlaced = std::pair, cocos2d::CCPoint>; + using ObjectRemoved = geode::Ref; + using ObjectSelected = std::pair, bool>; + using ObjectEdited = std::pair, ObjectKeyMap>; + + using Type = std::variant< + std::vector, + std::vector, + std::vector, + std::vector, + >; + + protected: + Type m_event; + static bool s_blockEvents; + + EditorEvent(Type const& type); + + friend struct BlockEventsHandle; - std::string desc() const override { - if (events.empty()) { - return "Invalid Event"; - } - auto& event = events.at(0); - const char* ty; - if (typeinfo_cast(event.obj.data())) { - ty = "Start Pos"; - } - else if (typeinfo_cast(event.obj.data())) { - ty = "Trigger"; - } - else { - ty = "Object"; + public: + static void post(Type const& type); + template + requires requires(T const& v) { + Type(std::vector { v }); } - return fmt::format( - fmt::runtime(event.getDescFmt()), - (events.size() == 1 ? ty : fmt::format("{} {}s", events.size(), ty)) - ); + static void post(T const& event) { + return EditorEvent::post({ event }); } + static BlockEventsHandle block(); }; struct BE_DLL EditorFilter : public geode::EventFilter { diff --git a/src/tracking/DispatchTracking.cpp b/src/tracking/DispatchTracking.cpp index 0d2554db..6d0c5cd7 100644 --- a/src/tracking/DispatchTracking.cpp +++ b/src/tracking/DispatchTracking.cpp @@ -24,78 +24,27 @@ using namespace better_edit; static int TRACKING_HOOK_PRIORITY = 999; -#define BLOCKED_CALL(...) \ - {\ - auto block = BlockAll();\ - __VA_ARGS__;\ - } - -#define BLOCKED_CALL_TO(var_, ...) \ - {\ - auto block = BlockAll();\ - var_ = __VA_ARGS__;\ - } - -template -struct Bubble { - std::vector events; - static inline Bubble* s_current = nullptr; - Bubble() { - if (!s_current) { - s_current = this; - } - } - ~Bubble() { - if (s_current == this) { - s_current = nullptr; - if (events.size()) { - post(MultiObjEvent(std::move(events))); - } - } - } - void cancel() { - if (s_current == this) { - s_current = nullptr; - } - } - template - static void push(Args&&... args) { - if (BlockAll::blocked()) return; - if (s_current) { - s_current->events.emplace_back(std::forward(args)...); - } - else { - post(MultiObjEvent({ T(std::forward(args)...) })); - } - } -private: - template - static void post(E&& t) { - if (EditorUI::get() && !BlockAll::blocked()) { - t.post(); - } - } -}; - class $modify(EditorPauseLayer) { void saveLevel() { - BLOCKED_CALL(EditorPauseLayer::saveLevel()); + auto _ = EditorEvent::block(); + EditorPauseLayer::saveLevel(); } void onSaveAndPlay(CCObject* sender) { - BLOCKED_CALL(EditorPauseLayer::onSaveAndPlay(sender)); + auto _ = EditorEvent::block(); + EditorPauseLayer::onSaveAndPlay(sender); } void onExitEditor(CCObject* sender) { - BLOCKED_CALL(EditorPauseLayer::onExitEditor(sender)); + auto _ = EditorEvent::block(); + EditorPauseLayer::onExitEditor(sender); } }; class $modify(PlayLayer) { bool init(GJGameLevel* level) { - bool ret; - BLOCKED_CALL_TO(ret, PlayLayer::init(level)); - return ret; + auto _ = EditorEvent::block(); + return PlayLayer::init(level); } }; @@ -110,24 +59,38 @@ class $modify(LevelEditorLayer) { } void addSpecial(GameObject* obj) { - BLOCKED_CALL(LevelEditorLayer::addSpecial(obj)); - Bubble::push(obj, obj->getPosition()); + { + auto _ = EditorEvent::block(); + LevelEditorLayer::addSpecial(obj); + } + EditorEvent::post(EditorEvent::ObjectPlaced { obj, obj->getPosition() }); } CCArray* createObjectsFromString(gd::string str, bool undo) { - auto bubble = Bubble(); - return LevelEditorLayer::createObjectsFromString(str, undo); + CCArray* objs; + { + auto _ = EditorEvent::block(); + objs = LevelEditorLayer::createObjectsFromString(str, undo); + } + std::vector events = {}; + for (auto& obj : CCArrayExt(objs)) { + events.push_back(EditorEvent::ObjectPlaced { obj, obj->getPosition() }); + } + EditorEvent::post(events); + return objs; } void createObjectsFromSetup(gd::string str) { - auto bubble = Bubble(); + auto _ = EditorEvent::block(); LevelEditorLayer::createObjectsFromSetup(str); - bubble.cancel(); } void removeSpecial(GameObject* obj) { - BLOCKED_CALL(LevelEditorLayer::removeSpecial(obj)); - Bubble::push(obj); + { + auto _ = EditorEvent::block(); + LevelEditorLayer::removeSpecial(obj); + } + EditorEvent::post(EditorEvent::ObjectRemoved { obj }); } void pasteAtributeState(GameObject* target, CCArray* targets) { diff --git a/src/tracking/Tracking.cpp b/src/tracking/Tracking.cpp index 7e284809..0fb55e45 100644 --- a/src/tracking/Tracking.cpp +++ b/src/tracking/Tracking.cpp @@ -19,1489 +19,31 @@ using namespace geode::prelude; using namespace better_edit; -std::string better_edit::toDiffString(Ref obj) { - return fmt::format( - "{}_{}_{}_{}_{}_{}_{}", - obj->m_objectID, - obj->getPosition().x, - obj->getPosition().y, - obj->getRotation(), - obj->getScale(), - obj->m_baseColorID, - obj->m_detailColorID - ); -} - -std::string better_edit::toDiffString(CCPoint const& point) { - return fmt::format("({},{})", point.x, point.y); -} - -std::string better_edit::toDiffString(ccHSVValue const& value) { - return fmt::format( - "({},{},{},{},{})", - value.h, value.s, value.v, - value.absoluteSaturation, value.absoluteBrightness - ); -} - -std::string better_edit::toDiffString(ccColor3B const& value) { - return fmt::format("({},{},{})", value.r, value.g, value.b); -} - -std::string better_edit::toDiffString(ccColor4B const& value) { - return fmt::format("({},{},{},{})", value.r, value.g, value.b, value.a); -} - -std::string better_edit::toDiffString(ColorState const& value) { - return toDiffString( - value.color, value.opacity, value.blending, - value.playerColor, value.copyColorID, value.copyHSV - ); -} - -std::string better_edit::toDiffString(ObjColorState const& value) { - return toDiffString( - value.base, value.baseHSV, - value.detail, value.detailHSV, - value.glow - ); -} - -std::string better_edit::toDiffString(ObjState const& value) { - return toDiffString( - value.groups, value.editorLayer1, value.editorLayer2, value.zOrder, - value.zLayer, value.dontFade, value.dontEnter, value.groupParent, - value.highDetail - ); -} - -std::string better_edit::toDiffString(LevelSettingsState const& value) { - return toDiffString( - value.speed, value.mode, value.flipGravity, value.mini, - value.dual, value.twoPlayer, value.songOffset, value.fadeIn, - value.fadeOut, value.bg, value.ground, value.groundLine, value.font - ); -} - -std::string better_edit::toDiffString(TriggerState const& value) { - return std::visit(makeVisitor { - [](TriggerState::Color const& color) { - return toDiffString( - color.channel, - color.fadeTime, - color.color, - color.opacity, - color.blending, - color.playerColor1, - color.playerColor2, - color.copyID, - color.copyHSV, - color.copyOpacity - ); - }, - [](TriggerState::Move const& move) { - return toDiffString( - move.x, - move.y, - move.lockToPlayerX, - move.lockToPlayerY, - move.easing, - move.easingRate, - move.time, - move.targetGroupID, - move.useTarget, - move.followGroupID, - move.followType - ); - }, - [](TriggerState::Stop const& stop) { - return toDiffString(stop.targetGroupID); - }, - [](TriggerState::Pulse const& pulse) { - return toDiffString( - pulse.targetID, - pulse.targetGroup, - pulse.mainOnly, - pulse.detailOnly, - pulse.color, - pulse.pulseHSV, - pulse.copyID, - pulse.copyHSV, - pulse.fadeIn, - pulse.hold, - pulse.fadeOut, - pulse.exclusive - ); - }, - [](TriggerState::Alpha const& alpha) { - return toDiffString( - alpha.targetGroupID, - alpha.time, - alpha.opacity - ); - }, - [](TriggerState::Toggle const& toggle) { - return toDiffString( - toggle.targetGroupID, - toggle.activateGroup - ); - }, - [](TriggerState::Spawn const& spawn) { - return toDiffString( - spawn.targetGroupID, - spawn.delayTime, - spawn.editorDisable - ); - }, - [](TriggerState::Rotate const& rotate) { - return toDiffString( - rotate.targetGroupID, - rotate.centerGroupID, - rotate.degrees, - rotate.times360, - rotate.lockObjectRotation, - rotate.easing, - rotate.easingRate, - rotate.time - ); - }, - [](TriggerState::Follow const& follow) { - return toDiffString( - follow.targetGroupID, - follow.followGroupID, - follow.xMod, - follow.yMod, - follow.time - ); - }, - [](TriggerState::Shake const& shake) { - return toDiffString( - shake.strength, shake.interval, shake.duration - ); - }, - [](TriggerState::Animation const& animation) { - return toDiffString( - animation.targetGroupID, animation.animationID - ); - }, - [](TriggerState::FollowPlayerY const& followPlayerY) { - return toDiffString( - followPlayerY.targetGroupID, - followPlayerY.speed, - followPlayerY.delay, - followPlayerY.offset, - followPlayerY.maxSpeed, - followPlayerY.time - ); - }, - [](TriggerState::Touch const& touch) { - return toDiffString( - touch.targetGroupID, - touch.dualMode, - touch.holdMode, - touch.toggleMode - ); - }, - [](TriggerState::Count const& count) { - return toDiffString( - count.itemID, - count.targetGroupID, - count.targetCount, - count.activateGroup, - count.multiActivate - ); - }, - [](TriggerState::InstantCount const& instantCount) { - return toDiffString( - instantCount.itemID, - instantCount.targetGroupID, - instantCount.targetCount, - instantCount.activateGroup, - instantCount.comparisonType - ); - }, - [](TriggerState::Pickup const& pickup) { - return toDiffString(pickup.itemID, pickup.count); - }, - [](TriggerState::Collision const& collision) { - return toDiffString(collision.blockAID, collision.blockBID); - }, - [](TriggerState::OnDeath const& onDeath) { - return toDiffString(onDeath.targetGroupID, onDeath.activateGroup); - }, - }, value.props) + "," + toDiffString(value.touchTrigger, value.spawnTrigger, value.multiTrigger); -} - -std::string better_edit::toDiffString(SpecialState const& value) { - return std::visit(makeVisitor { - [](SpecialState::CollisionBlock const& value) { - return toDiffString(value.id, value.dynamic); - }, - [](SpecialState::Counter const& value) { - return toDiffString(value.id); - }, - [](SpecialState::Saw const& value) { - return toDiffString(value.degrees, value.disable); - }, - [](SpecialState::OrbPadPortal const& value) { - return toDiffString(value.multiActivate); - }, - [](SpecialState::ToggleOrb const& value) { - return toDiffString(value.targetGroupID, value.activateGroup, value.multiActivate); - }, - [](SpecialState::Collectible const& value) { - return toDiffString( - value.pickupMode, value.itemID, - value.subtractCount, value.groupID, - value.enableGroup - ); - }, - [](SpecialState::Pulse const& value) { - return toDiffString(value.randomizeStart, value.speed); - }, - }, value.props); -} - -std::string better_edit::toDiffString(std::vector const& value) { - std::string res = "["; - for (auto& c : value) { - res += std::to_string(c) + ","; - } - return res + "]"; -} - -std::string better_edit::toDiffString(bool value) { - return value ? "t" : "f"; -} - -std::string better_edit::toDiffString(ZLayer const& value) { - return std::to_string(static_cast(value)); -} - -bool BlockAll::blocked() { - return s_current; -} - -BlockAll::BlockAll() { - if (!s_current) { - s_current = this; - } -} - -BlockAll::~BlockAll() { - if (s_current == this) { - s_current = nullptr; - } -} - -bool Detail::operator==(Detail const& other) const { - return info == other.info && icon == other.icon; -} - -ColorState ColorState::from(ColorAction* action) { - return ColorState { - .color = action->m_color, - .opacity = action->m_opacity, - .blending = action->m_blending, - .playerColor = action->m_playerColor, - .copyColorID = action->m_copyID, - .copyHSV = action->m_copyHSV, - }; -} - -void ColorState::to(ColorAction* action) const { - action->m_color = color; - action->m_opacity = opacity; - action->m_blending = blending; - action->m_playerColor = playerColor; - action->m_copyID = copyColorID; - action->m_copyHSV = copyHSV; -} - -ObjColorState ObjColorState::from(GameObject* obj) { - return ObjColorState { - .base = obj->m_baseColor ? obj->m_baseColor->m_colorID : 0, - .baseHSV = obj->m_baseColor ? obj->m_baseColor->m_hsv : ccHSVValue(), - .detail = obj->m_detailColor ? obj->m_detailColor->m_colorID : 0, - .detailHSV = obj->m_detailColor ? obj->m_detailColor->m_hsv : ccHSVValue(), - .glow = !obj->m_isGlowDisabled, - }; -} - -void ObjColorState::to(GameObject* obj) const { - if (obj->m_baseColor) { - obj->m_baseColor->m_colorID = base; - obj->m_baseColor->m_hsv = baseHSV; - } - if (obj->m_detailColor) { - obj->m_detailColor->m_colorID = detail; - obj->m_detailColor->m_hsv = detailHSV; - } - obj->m_isGlowDisabled = !glow; - obj->m_shouldUpdateColorSprite = true; -} - -ObjState ObjState::from(GameObject* obj) { - return ObjState { - .groups = obj->getGroupIDs(), - .editorLayer1 = obj->m_editorLayer, - .editorLayer2 = obj->m_editorLayer2, - .zOrder = obj->m_gameZOrder, - .zLayer = obj->m_zLayer, - .dontFade = obj->m_isDontFade, - .dontEnter = obj->m_isDontEnter, - .groupParent = obj->m_isGroupParent, - .highDetail = obj->m_highDetail, - }; -} - -void ObjState::to(GameObject* obj) const { - auto _ = BlockAll(); - obj->m_groupCount = 0; - for (auto& group : this->groups) { - obj->addToGroup(group); - } - obj->m_editorLayer = this->editorLayer1; - obj->m_editorLayer2 = this->editorLayer2; - obj->m_gameZOrder = this->zOrder; - obj->m_zLayer = this->zLayer; - obj->m_isDontFade = this->dontFade; - obj->m_isDontEnter = this->dontEnter; - obj->m_isGroupParent = this->groupParent; - obj->m_highDetail = this->highDetail; -} - -LevelSettingsState LevelSettingsState::from(LevelSettingsObject* obj) { - return LevelSettingsState { - .speed = obj->m_startSpeed, - .mode = obj->m_startMode, - .flipGravity = obj->m_isFlipped, - .mini = obj->m_startMini, - .dual = obj->m_startDual, - .twoPlayer = obj->m_twoPlayerMode, - .songOffset = obj->m_songOffset, - .fadeIn = obj->m_fadeIn, - .fadeOut = obj->m_fadeOut, - .bg = obj->m_backgroundIndex, - .ground = obj->m_groundIndex, - .groundLine = obj->m_groundLineIndex, - .font = obj->m_fontIndex, - }; -} - -void LevelSettingsState::to(LevelSettingsObject* obj) const { - // needs to be updated first - if (obj == LevelEditorLayer::get()->m_levelSettings) { - LevelEditorLayer::get()->updateLevelFont(font); - } - obj->m_startSpeed = speed; - obj->m_startMode = mode; - obj->m_isFlipped = flipGravity; - obj->m_startMini = mini; - obj->m_startDual = dual; - obj->m_twoPlayerMode = twoPlayer; - obj->m_songOffset = songOffset; - obj->m_fadeIn = fadeIn; - obj->m_fadeOut = fadeOut; - obj->m_backgroundIndex = bg; - obj->m_groundIndex = ground; - obj->m_groundLineIndex = groundLine; - obj->m_fontIndex = font; -} - -std::optional SpecialState::from(GameObject* robj) { - if (auto obj = typeinfo_cast(robj)) { - if (obj->m_objectID == ObjectProps::COUNTER_ITEM_ID) { - return SpecialState { - .props = {SpecialState::Counter { - .id = obj->m_itemBlockAID, - }}, - }; - } - if (obj->m_objectID == ObjectProps::TOGGLE_ORB_ID) { - return SpecialState { - .props = {SpecialState::ToggleOrb { - .targetGroupID = obj->m_targetGroupID, - .activateGroup = obj->m_activateGroup, - .multiActivate = obj->m_multiActivate, - }}, - }; - } - if (obj->m_objectType == GameObjectType::Collectible) { - return SpecialState { - .props = {SpecialState::Collectible { - .pickupMode = obj->m_pickupMode, - .itemID = obj->m_itemBlockAID, - .subtractCount = obj->m_subtractCount, - .groupID = obj->m_targetGroupID, - .enableGroup = obj->m_activateGroup, - }}, - }; - } - if (obj->m_objectID == ObjectProps::COLLISION_BLOCK_ID) { - return SpecialState { - .props = {SpecialState::CollisionBlock { - .id = obj->m_itemBlockAID, - .dynamic = obj->m_dynamicBlock, - }}, - }; - } - if (obj->canAllowMultiActivate()) { - return SpecialState { - .props = {SpecialState::OrbPadPortal { - .multiActivate = obj->m_orbMultiActivate, - }}, - }; - } - } - if (robj->m_isSaw) { - return SpecialState { - .props = {SpecialState::Saw { - .degrees = robj->m_customRotateSpeed, - .disable = robj->m_sawIsDisabled, - }}, - }; - } - if (robj->m_isEffectObject) { - return SpecialState { - .props = {SpecialState::Pulse { - .randomizeStart = robj->m_randomisedAnimStart, - .speed = robj->m_animSpeed, - }}, - }; - } - return std::nullopt; -} - -void SpecialState::to(GameObject* robj) const { - auto obj = typeinfo_cast(robj); - std::visit(makeVisitor { - [&](SpecialState::CollisionBlock const& value) { - obj->m_itemBlockAID = value.id; - obj->m_dynamicBlock = value.dynamic; - }, - [&](SpecialState::Counter const& value) { - obj->m_itemBlockAID = value.id; - }, - [&](SpecialState::Saw const& value) { - robj->m_customRotateSpeed = value.degrees; - robj->m_sawIsDisabled = value.disable; - }, - [&](SpecialState::OrbPadPortal const& value) { - obj->m_orbMultiActivate = value.multiActivate; - }, - [&](SpecialState::ToggleOrb const& value) { - obj->m_targetGroupID = value.targetGroupID; - obj->m_activateGroup = value.activateGroup; - obj->m_multiActivate = value.multiActivate; - }, - [&](SpecialState::Collectible const& value) { - obj->m_pickupMode = value.pickupMode; - obj->m_itemBlockAID = value.itemID; - obj->m_subtractCount = value.subtractCount; - obj->m_targetGroupID = value.groupID; - obj->m_activateGroup = value.enableGroup; - }, - [&](SpecialState::Pulse const& value) { - robj->m_randomisedAnimStart = value.randomizeStart; - robj->m_animSpeed = value.speed; - }, - }, props); -} - -std::optional TriggerState::from(EffectGameObject* obj) { - switch (obj->m_objectID) { - case ObjectProps::COLOR_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Color { - .channel = obj->m_targetColorID, - .fadeTime = obj->m_duration, - .color = obj->m_colColor, - .opacity = obj->m_opacity, - .blending = obj->m_blending, - .playerColor1 = obj->m_playerColor1, - .playerColor2 = obj->m_playerColor2, - .copyID = obj->m_copyColorID, - .copyHSV = obj->m_hsvValue, - .copyOpacity = obj->m_copyOpacity, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::MOVE_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Move { - .x = obj->m_move.x, - .y = obj->m_move.y, - .lockToPlayerX = obj->m_lockToPlayerX, - .lockToPlayerY = obj->m_lockToPlayerY, - .easing = obj->m_easingType, - .easingRate = obj->m_easingRate, - .time = obj->m_duration, - .targetGroupID = obj->m_targetGroupID, - .useTarget = obj->m_useTarget, - .followGroupID = obj->m_centerGroupID, - .followType = obj->m_moveTargetType, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::STOP_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Stop { - .targetGroupID = obj->m_targetGroupID, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::PULSE_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Pulse { - .targetID = obj->m_targetGroupID, - .targetGroup = obj->m_pulseGroupMode == 1, - .mainOnly = obj->m_pulseMainOnly, - .detailOnly = obj->m_pulseDetailOnly, - .color = obj->m_colColor, - .pulseHSV = obj->m_pulseHSVMode == 1, - .copyID = obj->m_copyColorID, - .copyHSV = obj->m_hsvValue, - .fadeIn = obj->m_fadeInTime, - .hold = obj->m_holdTime, - .fadeOut = obj->m_fadeOutTime, - .exclusive = obj->m_pulseExclusive, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::ALPHA_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Alpha { - .targetGroupID = obj->m_targetGroupID, - .time = obj->m_duration, - .opacity = obj->m_opacity, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::TOGGLE_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Toggle { - .targetGroupID = obj->m_targetGroupID, - .activateGroup = obj->m_activateGroup, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::SPAWN_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Spawn { - .targetGroupID = obj->m_targetGroupID, - .delayTime = obj->m_spawnDelay, - .editorDisable = obj->m_editorDisabled, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::ROTATE_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Rotate { - .targetGroupID = obj->m_targetGroupID, - .centerGroupID = obj->m_centerGroupID, - .degrees = obj->m_rotateDegrees, - .times360 = obj->m_times360, - .lockObjectRotation = obj->m_lockObjectRotation, - .easing = obj->m_easingType, - .easingRate = obj->m_easingRate, - .time = obj->m_duration, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::FOLLOW_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Follow { - .targetGroupID = obj->m_targetGroupID, - .followGroupID = obj->m_centerGroupID, - .xMod = obj->m_followMod.x, - .yMod = obj->m_followMod.y, - .time = obj->m_duration, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::SHAKE_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Shake { - .strength = obj->m_shakeStrength, - .interval = obj->m_shakeInterval, - .duration = obj->m_duration, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::ANIMATION_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Animation { - .targetGroupID = obj->m_targetGroupID, - .animationID = obj->m_animationID, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::FOLLOW_PLAYER_Y_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::FollowPlayerY { - .targetGroupID = obj->m_targetGroupID, - .speed = obj->m_followYSpeed, - .delay = obj->m_followYDelay, - .offset = obj->m_followYOffset, - .maxSpeed = obj->m_followYMaxSpeed, - .time = obj->m_duration, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::TOUCH_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Touch { - .targetGroupID = obj->m_targetGroupID, - .dualMode = obj->m_touchDualMode, - .holdMode = obj->m_touchHoldMode, - .toggleMode = obj->m_touchToggleMode, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::COUNT_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Count { - .itemID = obj->m_itemBlockAID, - .targetGroupID = obj->m_targetGroupID, - .targetCount = obj->m_targetCount, - .activateGroup = obj->m_activateGroup, - .multiActivate = obj->m_multiActivate, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::INSTANT_COUNT_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::InstantCount { - .itemID = obj->m_itemBlockAID, - .targetGroupID = obj->m_targetGroupID, - .targetCount = obj->m_targetCount, - .activateGroup = obj->m_activateGroup, - .comparisonType = obj->m_comparisonType, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::PICKUP_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Pickup { - .itemID = obj->m_itemBlockAID, - .count = obj->m_targetCount, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::COLLISION_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::Collision { - .blockAID = obj->m_itemBlockAID, - .blockBID = obj->m_blockBID, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - case ObjectProps::ON_DEATH_TRIGGER_ID: { - return TriggerState { - .props = {TriggerState::OnDeath { - .targetGroupID = obj->m_targetGroupID, - .activateGroup = obj->m_activateGroup, - }}, - .touchTrigger = obj->m_touchTriggered, - .spawnTrigger = obj->m_spawnTriggered, - .multiTrigger = obj->m_multiTrigger, - }; - } break; - - default: { - return std::nullopt; - } break; - } -} - -void TriggerState::to(EffectGameObject* obj) const { - std::visit(makeVisitor { - [&](TriggerState::Color const& color) { - obj->m_targetColorID = color.channel; - obj->m_duration = color.fadeTime; - obj->m_colColor = color.color; - obj->m_opacity = color.opacity; - obj->m_blending = color.blending; - obj->m_playerColor1 = color.playerColor1; - obj->m_playerColor2 = color.playerColor2; - obj->m_copyColorID = color.copyID; - obj->m_hsvValue = color.copyHSV; - obj->m_copyOpacity = color.copyOpacity; - }, - [&](TriggerState::Move const& move) { - obj->m_move.x = move.x; - obj->m_move.y = move.y; - obj->m_lockToPlayerX = move.lockToPlayerX; - obj->m_lockToPlayerY = move.lockToPlayerY; - obj->m_easingType = move.easing; - obj->m_easingRate = move.easingRate; - obj->m_duration = move.time; - obj->m_targetGroupID = move.targetGroupID; - obj->m_useTarget = move.useTarget; - obj->m_centerGroupID = move.followGroupID; - obj->m_moveTargetType = move.followType; - }, - [&](TriggerState::Stop const& stop) { - obj->m_targetGroupID = stop.targetGroupID; - }, - [&](TriggerState::Pulse const& pulse) { - obj->m_targetGroupID = pulse.targetID; - obj->m_pulseGroupMode = pulse.targetGroup; - obj->m_pulseMainOnly = pulse.mainOnly; - obj->m_pulseDetailOnly = pulse.detailOnly; - obj->m_colColor = pulse.color; - obj->m_pulseHSVMode = pulse.pulseHSV; - obj->m_copyColorID = pulse.copyID; - obj->m_hsvValue = pulse.copyHSV; - obj->m_fadeInTime = pulse.fadeIn; - obj->m_holdTime = pulse.hold; - obj->m_fadeOutTime = pulse.fadeOut; - obj->m_pulseExclusive = pulse.exclusive; - }, - [&](TriggerState::Alpha const& alpha) { - obj->m_targetGroupID = alpha.targetGroupID; - obj->m_duration = alpha.time; - obj->m_opacity = alpha.opacity; - }, - [&](TriggerState::Toggle const& toggle) { - obj->m_targetGroupID = toggle.targetGroupID; - obj->m_activateGroup = toggle.activateGroup; - }, - [&](TriggerState::Spawn const& spawn) { - obj->m_targetGroupID = spawn.targetGroupID; - obj->m_spawnDelay = spawn.delayTime; - obj->m_editorDisabled = spawn.editorDisable; - }, - [&](TriggerState::Rotate const& rotate) { - obj->m_targetGroupID = rotate.targetGroupID; - obj->m_centerGroupID = rotate.centerGroupID; - obj->m_rotateDegrees = rotate.degrees; - obj->m_times360 = rotate.times360; - obj->m_lockObjectRotation = rotate.lockObjectRotation; - obj->m_easingType = rotate.easing; - obj->m_easingRate = rotate.easingRate; - obj->m_duration = rotate.time; - }, - [&](TriggerState::Follow const& follow) { - obj->m_targetGroupID = follow.targetGroupID; - obj->m_centerGroupID = follow.followGroupID; - obj->m_followMod.x = follow.xMod; - obj->m_followMod.y = follow.yMod; - obj->m_duration = follow.time; - }, - [&](TriggerState::Shake const& shake) { - obj->m_shakeStrength = shake.strength; - obj->m_shakeInterval = shake.interval; - obj->m_duration = shake.duration; - }, - [&](TriggerState::Animation const& animation) { - obj->m_targetGroupID = animation.targetGroupID; - obj->m_animationID = animation.animationID; - }, - [&](TriggerState::FollowPlayerY const& followPlayerY) { - obj->m_targetGroupID = followPlayerY.targetGroupID; - obj->m_followYSpeed = followPlayerY.speed; - obj->m_followYDelay = followPlayerY.delay; - obj->m_followYOffset = followPlayerY.offset; - obj->m_followYMaxSpeed = followPlayerY.maxSpeed; - obj->m_duration = followPlayerY.time; - }, - [&](TriggerState::Touch const& touch) { - obj->m_targetGroupID = touch.targetGroupID; - obj->m_touchDualMode = touch.dualMode; - obj->m_touchHoldMode = touch.holdMode; - obj->m_touchToggleMode = touch.toggleMode; - }, - [&](TriggerState::Count const& count) { - obj->m_itemBlockAID = count.itemID; - obj->m_targetGroupID = count.targetGroupID; - obj->m_targetCount = count.targetCount; - obj->m_activateGroup = count.activateGroup; - obj->m_multiActivate = count.multiActivate; - }, - [&](TriggerState::InstantCount const& instantCount) { - obj->m_itemBlockAID = instantCount.itemID; - obj->m_targetGroupID = instantCount.targetGroupID; - obj->m_targetCount = instantCount.targetCount; - obj->m_activateGroup = instantCount.activateGroup; - obj->m_comparisonType = instantCount.comparisonType; - }, - [&](TriggerState::Pickup const& pickup) { - obj->m_itemBlockAID = pickup.itemID; - obj->m_targetCount = pickup.count; - }, - [&](TriggerState::Collision const& collision) { - obj->m_itemBlockAID = collision.blockAID; - obj->m_blockBID = collision.blockBID; - }, - [&](TriggerState::OnDeath const& onDeath) { - obj->m_targetGroupID = onDeath.targetGroupID; - obj->m_activateGroup = onDeath.activateGroup; - }, - }, props); - - obj->m_touchTriggered = touchTrigger; - obj->m_spawnTriggered = spawnTrigger; - obj->m_multiTrigger = multiTrigger; - - obj->updateLabel(); - LevelEditorLayer::get()->resetEffectTriggerOptim(obj, nullptr); -} - -std::unique_ptr EditorEvent::unique() const { - return std::unique_ptr(static_cast(this->clone())); -} - -ObjEventData::ObjEventData(Ref obj) - : obj(obj) {} - -// ObjPlaced - -std::string ObjPlaced::toDiffString() const { - return fmtDiffString("add", obj->m_objectID, pos); -} - -EditorEventData* ObjPlaced::clone() const { - return new ObjPlaced(obj, pos); -} - -void ObjPlaced::undo() const { - auto _ = BlockAll(); - LevelEditorLayer::get()->removeObjectFromSection(obj); - LevelEditorLayer::get()->removeSpecial(obj); - EditorUI::get()->deselectObject(obj); - obj->deactivateObject(true); -} - -void ObjPlaced::redo() const { - auto _ = BlockAll(); - LevelEditorLayer::get()->addToSection(obj); - LevelEditorLayer::get()->addSpecial(obj); - EditorUI::get()->moveObject(obj, pos - obj->getPosition()); - EditorUI::get()->selectObject(obj, true); -} - -std::vector ObjPlaced::details() const { - return {{ .info = fmt::format("ID {}", obj->m_objectID) }}; -} - -std::string ObjPlaced::getIconName() const { - return "plus.png"_spr; -} - -std::string ObjPlaced::getDescFmt() const { - return "Added {}"; -} - -// ObjRemoved - -std::string ObjRemoved::toDiffString() const { - return fmtDiffString("rem", obj); -} - -EditorEventData* ObjRemoved::clone() const { - return new ObjRemoved(obj); -} - -void ObjRemoved::undo() const { - auto _ = BlockAll(); - LevelEditorLayer::get()->addToSection(obj); - LevelEditorLayer::get()->addSpecial(obj); - EditorUI::get()->selectObject(obj, true); -} - -void ObjRemoved::redo() const { - auto _ = BlockAll(); - LevelEditorLayer::get()->removeObjectFromSection(obj); - LevelEditorLayer::get()->removeSpecial(obj); - EditorUI::get()->deselectObject(obj); - obj->deactivateObject(true); -} - -std::vector ObjRemoved::details() const { - return {}; -} - -std::string ObjRemoved::getIconName() const { - return "neg.png"_spr; -} - -std::string ObjRemoved::getDescFmt() const { - return "Removed {}"; -} - -// ObjPasted - -std::string ObjPasted::toDiffString() const { - return fmtDiffString("pst", obj, src); -} - -EditorEventData* ObjPasted::clone() const { - return new ObjPasted(obj, src); -} - -void ObjPasted::undo() const { - auto _ = BlockAll(); - LevelEditorLayer::get()->removeObjectFromSection(obj); - LevelEditorLayer::get()->removeSpecial(obj); - EditorUI::get()->deselectObject(obj); - obj->deactivateObject(true); -} - -void ObjPasted::redo() const { - auto _ = BlockAll(); - LevelEditorLayer::get()->addToSection(obj); - LevelEditorLayer::get()->addSpecial(obj); - EditorUI::get()->selectObject(obj, true); -} - -std::vector ObjPasted::details() const { - return {}; -} - -std::string ObjPasted::getIconName() const { - return "plus.png"_spr; -} - -std::string ObjPasted::getDescFmt() const { - return "Copied {}"; -} - -// ObjTransformed - -std::string ObjTransformed::toDiffString() const { - return fmtDiffString("trf", obj, pos, angle, scale, flipX, flipY); -} - -EditorEventData* ObjTransformed::clone() const { - return new ObjTransformed(obj, pos, angle, scale, flipX, flipY); -} - -void ObjTransformed::undo() const { - auto _ = BlockAll(); - if (!flipX.isZero()) { - EditorUI::get()->flipObjectsX(CCArray::createWithObject(obj)); - } - if (!flipY.isZero()) { - EditorUI::get()->flipObjectsY(CCArray::createWithObject(obj)); - } - if (!angle.isZero()) { - EditorUI::get()->rotateObjects( - CCArray::createWithObject(obj), angle.from - obj->getRotation(), obj->getPosition() - ); - } - if (!scale.isZero()) { - EditorUI::get()->scaleObjects( - CCArray::createWithObject(obj), scale.from, obj->getPosition() - ); - } - if (!pos.isZero()) { - EditorUI::get()->moveObject(obj, pos.from - obj->getPosition()); - } -} - -void ObjTransformed::redo() const { - auto _ = BlockAll(); - if (!flipX.isZero()) { - EditorUI::get()->flipObjectsX(CCArray::createWithObject(obj)); - } - if (!flipY.isZero()) { - EditorUI::get()->flipObjectsY(CCArray::createWithObject(obj)); - } - if (!angle.isZero()) { - EditorUI::get()->rotateObjects( - CCArray::createWithObject(obj), angle.to - obj->getRotation(), obj->getPosition() - ); - } - if (!scale.isZero()) { - EditorUI::get()->scaleObjects( - CCArray::createWithObject(obj), scale.to, obj->getPosition() - ); - } - if (!pos.isZero()) { - EditorUI::get()->moveObject(obj, pos.to - obj->getPosition()); - } -} - -std::vector ObjTransformed::details() const { - std::vector res; - auto dx = pos.to.x - pos.from.x; - auto dy = pos.to.y - pos.from.y; - if (dx != 0.f) { - res.push_back({ - .info = numToString(std::fabsf(dx)), - .icon = dx > 0.f ? "edit_rightBtn2_001.png" : "edit_leftBtn2_001.png" - }); - } - if (dy != 0.f) { - res.push_back({ - .info = numToString(std::fabsf(dy)), - .icon = dy > 0.f ? "edit_upBtn2_001.png" : "edit_downBtn2_001.png" - }); - } - auto delta = angle.to - angle.from; - if (delta != 0.f) { - res.push_back({ - .info = fmt::format("{}°", std::fabsf(delta)), - .icon = delta > 0.f ? "edit_cwBtn_001.png" : "edit_ccwBtn_001.png" - }); - } - if (!scale.isZero()) { - res.push_back({ - .info = fmt::format("{}x", scale.to), - .icon = "scale.png"_spr - }); - } - return res; -} +bool EditorEvent::s_blockEvents = false; -std::string ObjTransformed::getIconName() const { - size_t tally = !pos.isZero() + !angle.isZero() + !scale.isZero() + - !flipX.isZero() + !flipY.isZero(); +ChangedState::ChangedState( + StateValue const& from, + StateValue const& to +) : from(from), to(to) {} - // Only one property was changed - if (tally == 1) { - if (!angle.isZero()) { - return "edit_ccwBtn_001.png"; - } - if (!scale.isZero()) { - return "scale.png"_spr; - } - if (!flipX.isZero()) { - return "edit_flipXBtn_001.png"; - } - if (!flipY.isZero()) { - return "edit_flipYBtn_001.png"; - } - } - // Default to move - return "move.png"_spr; -} - -std::string ObjTransformed::getDescFmt() const { - size_t tally = !pos.isZero() + !angle.isZero() + !scale.isZero() + - !flipX.isZero() + !flipY.isZero(); - - // Only one property was changed - if (tally == 1) { - if (!angle.isZero()) { - return "Rotated {}"; - } - if (!scale.isZero()) { - return "Scaled {}"; - } - if (!flipX.isZero()) { - return "Flipped {} on the X-axis"; - } - if (!flipY.isZero()) { - return "Flipped {} on the Y-axis"; - } - if (!pos.isZero()) { - return "Moved {}"; - } - } - return "Transformed {}"; +BlockEventsHandle::BlockEventsHandle() { + EditorEvent::s_blockEvents = true; } -// ObjColored - -std::string ObjColored::toDiffString() const { - return fmtDiffString("col", obj, color); +BlockEventsHandle::~BlockEventsHandle() { + EditorEvent::s_blockEvents = false; } -EditorEventData* ObjColored::clone() const { - return new ObjColored(obj, color); -} +EditorEvent::EditorEvent(Type const& type) : m_event(type) {} -void ObjColored::undo() const { - color.from.to(obj); +BlockEventsHandle EditorEvent::block() { + return BlockEventsHandle(); } -void ObjColored::redo() const { - color.to.to(obj); -} - -std::vector ObjColored::details() const { - return {}; -} - -std::string ObjColored::getIconName() const { - return "color.png"_spr; -} - -std::string ObjColored::getDescFmt() const { - return "Colored {}"; -} - -// ObjPropsChanged - -std::string ObjPropsChanged::toDiffString() const { - return fmtDiffString("prp", obj, state); -} - -EditorEventData* ObjPropsChanged::clone() const { - return new ObjPropsChanged(obj, state); -} - -void ObjPropsChanged::undo() const { - auto _ = BlockAll(); - state.from.to(obj); -} - -void ObjPropsChanged::redo() const { - auto _ = BlockAll(); - state.to.to(obj); -} - -std::vector ObjPropsChanged::details() const { - std::vector res; - if (state.from.groups != state.to.groups) { - std::string info = "Groups "; - bool first = true; - for (auto& grp : state.to.groups) { - if (!first) { - info += ", "; - } - first = false; - info += std::to_string(grp); - } - res.push_back({ .info = info }); - } - if (state.from.editorLayer1 != state.to.editorLayer1) { - res.push_back({ - .info = fmt::format("Layer 1 to {}", state.to.editorLayer1) - }); - } - if (state.from.editorLayer2 != state.to.editorLayer2) { - res.push_back({ - .info = fmt::format("Layer 2 to {}", state.to.editorLayer2) - }); - } - if (state.from.zOrder != state.to.zOrder) { - res.push_back({ - .info = fmt::format("Z Order to {}", state.to.zOrder) - }); - } - if (state.from.zLayer != state.to.zLayer) { - res.push_back({ - .info = fmt::format("Z Layer to {}", zLayerToString(state.to.zLayer)) - }); - } - if (state.to.dontEnter) { - res.push_back({ .info = "Don't Enter" }); +void EditorEvent::post(Type const& type) { + if (!s_blockEvents) { + EditorEvent(type).Event::post(); } - if (state.to.dontFade) { - res.push_back({ .info = "Don't Fade" }); - } - if (state.to.groupParent) { - res.push_back({ .info = "Group Parent" }); - } - if (state.to.highDetail) { - res.push_back({ .info = "High Detail" }); - } - return res; -} - -std::string ObjPropsChanged::getIconName() const { - return "GJ_hammerIcon_001.png"; -} - -std::string ObjPropsChanged::getDescFmt() const { - return "Changed {} Properties"; -} - -// ObjSelected - -std::string ObjSelected::toDiffString() const { - return fmtDiffString("sel", obj); -} - -EditorEventData* ObjSelected::clone() const { - return new ObjSelected(obj); -} - -void ObjSelected::undo() const { - auto _ = BlockAll(); - EditorUI::get()->deselectObject(obj); -} - -void ObjSelected::redo() const { - auto _ = BlockAll(); - auto arr = EditorUI::get()->getSelectedObjects(); - arr->addObject(obj); - EditorUI::get()->selectObjects(arr, false); -} - -std::vector ObjSelected::details() const { - return {}; -} - -std::string ObjSelected::getIconName() const { - return "select.png"_spr; -} - -std::string ObjSelected::getDescFmt() const { - return "Selected {}"; -} - -// ObjDeselected - -std::string ObjDeselected::toDiffString() const { - return fmtDiffString("dsl", obj); -} - -EditorEventData* ObjDeselected::clone() const { - return new ObjDeselected(obj); -} - -void ObjDeselected::undo() const { - auto _ = BlockAll(); - auto arr = EditorUI::get()->getSelectedObjects(); - arr->addObject(obj); - EditorUI::get()->selectObjects(arr, false); -} - -void ObjDeselected::redo() const { - auto _ = BlockAll(); - EditorUI::get()->deselectObject(obj); -} - -std::vector ObjDeselected::details() const { - return {}; -} - -std::string ObjDeselected::getIconName() const { - return "deselect.png"_spr; -} - -std::string ObjDeselected::getDescFmt() const { - return "Deselected {}"; -} - -// StartPosChanged - -std::string StartPosChanged::toDiffString() const { - return fmtDiffString("str", obj, state); -} - -EditorEventData* StartPosChanged::clone() const { - return new StartPosChanged(static_cast(obj.data()), state); -} - -void StartPosChanged::undo() const { - state.from.to(static_cast(obj.data())->m_levelSettings); -} - -void StartPosChanged::redo() const { - state.to.to(static_cast(obj.data())->m_levelSettings); -} - -std::vector StartPosChanged::details() const { - // todo - return {}; -} - -std::string StartPosChanged::getIconName() const { - return "edit_eStartPosBtn_001.png"; -} - -std::string StartPosChanged::getDescFmt() const { - return "Edited {}"; -} - -// TriggerPropsChanged - -std::string TriggerPropsChanged::toDiffString() const { - return fmtDiffString("trg", obj, state); -} - -EditorEventData* TriggerPropsChanged::clone() const { - return new TriggerPropsChanged(static_cast(obj.data()), state); -} - -void TriggerPropsChanged::undo() const { - state.from.to(static_cast(obj.data())); -} - -void TriggerPropsChanged::redo() const { - state.to.to(static_cast(obj.data())); -} - -std::vector TriggerPropsChanged::details() const { - // todo - return {}; -} - -std::string TriggerPropsChanged::getIconName() const { - return "GJ_hammerIcon_001.png"; -} - -std::string TriggerPropsChanged::getDescFmt() const { - return "Changed {} Properties"; -} - -// SpecialPropsChanged - -std::string SpecialPropsChanged::toDiffString() const { - return fmtDiffString("spp", obj, state); -} - -EditorEventData* SpecialPropsChanged::clone() const { - return new SpecialPropsChanged(obj, state); -} - -void SpecialPropsChanged::undo() const { - state.from.to(obj); -} - -void SpecialPropsChanged::redo() const { - state.to.to(obj); -} - -std::vector SpecialPropsChanged::details() const { - // todo - return {}; -} - -std::string SpecialPropsChanged::getIconName() const { - return "GJ_hammerIcon_001.png"; -} - -std::string SpecialPropsChanged::getDescFmt() const { - return "Changed {} Properties"; -} - -// ColorChannelEvent - -std::string ColorChannelEvent::toDiffString() const { - return fmtDiffString("chn", channel, state); -} - -EditorEventData* ColorChannelEvent::clone() const { - return new ColorChannelEvent(channel, state); -} - -void ColorChannelEvent::undo() const { - if (auto action = GJEffectManager::fromLevelSetting()->getColorAction(channel)) { - state.from.to(action); - } -} - -void ColorChannelEvent::redo() const { - if (auto action = GJEffectManager::fromLevelSetting()->getColorAction(channel)) { - state.to.to(action); - } -} - -std::vector ColorChannelEvent::details() const { - return {}; -} - -CCNode* ColorChannelEvent::icon() const { - return CCSprite::createWithSpriteFrameName("color.png"_spr); -} - -std::string ColorChannelEvent::desc() const { - return fmt::format("Channel {} Changed", channel); -} - -// LevelSettingsChanged - -std::string LevelSettingsChanged::toDiffString() const { - return fmtDiffString("set", state); -} - -EditorEventData* LevelSettingsChanged::clone() const { - return new LevelSettingsChanged(state); -} - -void LevelSettingsChanged::undo() const { - state.from.to(LevelEditorLayer::get()->m_levelSettings); -} - -void LevelSettingsChanged::redo() const { - state.to.to(LevelEditorLayer::get()->m_levelSettings); -} - -std::vector LevelSettingsChanged::details() const { - return {}; -} - -CCNode* LevelSettingsChanged::icon() const { - return CCSprite::createWithSpriteFrameName("GJ_hammerIcon_001.png"); -} - -std::string LevelSettingsChanged::desc() const { - return "Level Settings Changed"; } ListenerResult EditorFilter::handle(utils::MiniFunction fn, EditorEvent* event) {