From fb1d55101e3f00e15f05c4683c58b70bfc48569c Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 08:56:57 +0200 Subject: [PATCH] Made the EventHandler class tree a bit more branchy. Now disallowing creation of Static* via EventHandler.Create. --- src/events.cpp | 120 +++++++++++++++++++------------ src/events.h | 44 ++++++++---- src/g_level.cpp | 2 + src/gl/scene/gl_sprite.cpp | 2 +- src/p_spec.cpp | 3 + src/r_things.cpp | 2 +- wadsrc/static/zscript/events.txt | 25 ++++--- 7 files changed, 128 insertions(+), 70 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index 4516f32c9f..dc563692ac 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -2,24 +2,29 @@ #include "virtual.h" #include "r_utility.h" -DEventHandler* E_FirstEventHandler = nullptr; +DStaticEventHandler* E_FirstEventHandler = nullptr; -void E_RegisterHandler(DEventHandler* handler) +bool E_RegisterHandler(DStaticEventHandler* handler) { if (handler == nullptr || handler->ObjectFlags & OF_EuthanizeMe) - return; + return false; + if (E_CheckHandler(handler)) + return false; // link into normal list handler->prev = nullptr; handler->next = E_FirstEventHandler; if (handler->next) handler->next->prev = handler; E_FirstEventHandler = handler; + return true; } -void E_UnregisterHandler(DEventHandler* handler) +bool E_UnregisterHandler(DStaticEventHandler* handler) { if (handler == nullptr || handler->ObjectFlags & OF_EuthanizeMe) - return; + return false; + if (!E_CheckHandler(handler)) + return false; // link out of normal list if (handler->prev) handler->prev->next = handler->next; @@ -27,60 +32,78 @@ void E_UnregisterHandler(DEventHandler* handler) handler->next->prev = handler->prev; if (handler == E_FirstEventHandler) E_FirstEventHandler = handler->next; + return true; +} + +bool E_CheckHandler(DStaticEventHandler* handler) +{ + for (DStaticEventHandler* lhandler = E_FirstEventHandler; lhandler; lhandler = lhandler->next) + if (handler == lhandler) return true; + return false; } void E_MapLoaded() { - for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->MapLoaded(); } void E_MapUnloading() { - for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->MapUnloading(); } void E_RenderFrame() { - for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->RenderFrame(); } void E_RenderCamera() { - for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->RenderCamera(); } void E_RenderBeforeThing(AActor* thing) { - for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->RenderBeforeThing(thing); } void E_RenderAfterThing(AActor* thing) { - for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->RenderAfterThing(thing); } // declarations +IMPLEMENT_CLASS(DStaticEventHandler, false, false); +IMPLEMENT_CLASS(DStaticRenderEventHandler, false, false); IMPLEMENT_CLASS(DEventHandler, false, false); IMPLEMENT_CLASS(DRenderEventHandler, false, false); -DEFINE_FIELD_X(RenderEventHandler, DRenderEventHandler, ViewPos); -DEFINE_FIELD_X(RenderEventHandler, DRenderEventHandler, ViewAngle); -DEFINE_FIELD_X(RenderEventHandler, DRenderEventHandler, ViewPitch); -DEFINE_FIELD_X(RenderEventHandler, DRenderEventHandler, ViewRoll); -DEFINE_FIELD_X(RenderEventHandler, DRenderEventHandler, FracTic); -DEFINE_FIELD_X(RenderEventHandler, DRenderEventHandler, Camera); -DEFINE_FIELD_X(RenderEventHandler, DRenderEventHandler, CurrentThing); +DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewPos); +DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewAngle); +DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewPitch); +DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewRoll); +DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, FracTic); +DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, Camera); +DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, CurrentThing); + DEFINE_ACTION_FUNCTION(DEventHandler, Create) { PARAM_PROLOGUE; - PARAM_CLASS(t, DEventHandler); + PARAM_CLASS(t, DStaticEventHandler); + // check if type inherits dynamic handlers + if (!t->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && + !t->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))) + { + // disallow static types creation with Create() + ACTION_RETURN_OBJECT(nullptr); + } // generate a new object of this type. ACTION_RETURN_OBJECT(t->CreateNew()); } @@ -88,9 +111,16 @@ DEFINE_ACTION_FUNCTION(DEventHandler, Create) DEFINE_ACTION_FUNCTION(DEventHandler, CreateOnce) { PARAM_PROLOGUE; - PARAM_CLASS(t, DEventHandler); + PARAM_CLASS(t, DStaticEventHandler); + // check if type inherits dynamic handlers + if (!t->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && + !t->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))) + { + // disallow static types creation with Create() + ACTION_RETURN_OBJECT(nullptr); + } // check if there are already registered handlers of this type. - for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) if (handler->GetClass() == t) // check precise class ACTION_RETURN_OBJECT(nullptr); // generate a new object of this type. @@ -100,8 +130,8 @@ DEFINE_ACTION_FUNCTION(DEventHandler, CreateOnce) DEFINE_ACTION_FUNCTION(DEventHandler, Find) { PARAM_PROLOGUE; - PARAM_CLASS(t, DEventHandler); - for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + PARAM_CLASS(t, DStaticEventHandler); + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) if (handler->GetClass() == t) // check precise class ACTION_RETURN_OBJECT(handler); ACTION_RETURN_OBJECT(nullptr); @@ -110,17 +140,17 @@ DEFINE_ACTION_FUNCTION(DEventHandler, Find) DEFINE_ACTION_FUNCTION(DEventHandler, Register) { PARAM_PROLOGUE; - PARAM_OBJECT(handler, DEventHandler); - E_RegisterHandler(handler); - return 0; + PARAM_OBJECT(handler, DStaticEventHandler); + if (handler->IsStatic()) ACTION_RETURN_BOOL(false); + ACTION_RETURN_BOOL(E_RegisterHandler(handler)); } DEFINE_ACTION_FUNCTION(DEventHandler, Unregister) { PARAM_PROLOGUE; - PARAM_OBJECT(handler, DEventHandler); - E_UnregisterHandler(handler); - return 0; + PARAM_OBJECT(handler, DStaticEventHandler); + if (handler->IsStatic()) ACTION_RETURN_BOOL(false); + ACTION_RETURN_BOOL(E_UnregisterHandler(handler)); } #define DEFINE_EVENT_HANDLER(cls, funcname, args) DEFINE_ACTION_FUNCTION(cls, funcname) \ @@ -139,21 +169,21 @@ void cls::funcname(args) \ } \ } -DEFINE_EVENT_HANDLER(DEventHandler, MapLoaded,) -DEFINE_EVENT_HANDLER(DEventHandler, MapUnloading,) -DEFINE_EVENT_HANDLER(DEventHandler, RenderFrame,) -DEFINE_EVENT_HANDLER(DEventHandler, RenderCamera,) -DEFINE_EVENT_HANDLER(DEventHandler, RenderBeforeThing, AActor*) -DEFINE_EVENT_HANDLER(DEventHandler, RenderAfterThing, AActor*) +DEFINE_EVENT_HANDLER(DStaticEventHandler, MapLoaded,) +DEFINE_EVENT_HANDLER(DStaticEventHandler, MapUnloading,) +DEFINE_EVENT_HANDLER(DStaticEventHandler, RenderFrame,) +DEFINE_EVENT_HANDLER(DStaticEventHandler, RenderCamera,) +DEFINE_EVENT_HANDLER(DStaticEventHandler, RenderBeforeThing, AActor*) +DEFINE_EVENT_HANDLER(DStaticEventHandler, RenderAfterThing, AActor*) // -void DEventHandler::OnDestroy() +void DStaticEventHandler::OnDestroy() { E_UnregisterHandler(this); DObject::OnDestroy(); } -void DRenderEventHandler::Setup() +void DStaticRenderEventHandler::Setup() { ViewPos = ::ViewPos; ViewAngle = ::ViewAngle; @@ -163,26 +193,26 @@ void DRenderEventHandler::Setup() Camera = ::camera; } -void DRenderEventHandler::RenderFrame() +void DStaticRenderEventHandler::RenderFrame() { Setup(); - DEventHandler::RenderFrame(); + DStaticEventHandler::RenderFrame(); } -void DRenderEventHandler::RenderCamera() +void DStaticRenderEventHandler::RenderCamera() { Setup(); - DEventHandler::RenderCamera(); + DStaticEventHandler::RenderCamera(); } -void DRenderEventHandler::RenderBeforeThing(AActor* thing) +void DStaticRenderEventHandler::RenderBeforeThing(AActor* thing) { CurrentThing = thing; - DEventHandler::RenderBeforeThing(thing); + DStaticEventHandler::RenderBeforeThing(thing); } -void DRenderEventHandler::RenderAfterThing(AActor* thing) +void DStaticRenderEventHandler::RenderAfterThing(AActor* thing) { CurrentThing = thing; - DEventHandler::RenderAfterThing(thing); + DStaticEventHandler::RenderAfterThing(thing); } \ No newline at end of file diff --git a/src/events.h b/src/events.h index d8e647432b..b6a8588347 100755 --- a/src/events.h +++ b/src/events.h @@ -3,12 +3,14 @@ #include "dobject.h" -class DEventHandler; +class DStaticEventHandler; // register -void E_RegisterHandler(DEventHandler* handler); +bool E_RegisterHandler(DStaticEventHandler* handler); // unregister -void E_UnregisterHandler(DEventHandler* handler); +bool E_UnregisterHandler(DStaticEventHandler* handler); +// find +bool E_CheckHandler(DStaticEventHandler* handler); // called right after the map has loaded (approximately same time as OPEN ACS scripts) void E_MapLoaded(); @@ -23,18 +25,22 @@ void E_RenderBeforeThing(AActor* thing); // called after adding each actor to the render list void E_RenderAfterThing(AActor* thing); -class DEventHandler : public DObject // make it a part of normal GC process +class DStaticEventHandler : public DObject // make it a part of normal GC process { - DECLARE_CLASS(DEventHandler, DObject) + DECLARE_CLASS(DStaticEventHandler, DObject) public: - DEventHandler* prev; - DEventHandler* next; - DEventHandler* unregPrev; - DEventHandler* unregNext; + DStaticEventHandler* prev; + DStaticEventHandler* next; + DStaticEventHandler* unregPrev; + DStaticEventHandler* unregNext; + virtual bool IsStatic() { return true; } // destroy handler. this unlinks EventHandler from the list automatically. void OnDestroy() override; + // this checks if we are /actually/ static, using DObject dynamic typing system. + static bool IsActuallyStatic(PClass* type); + // called right after the map has loaded (approximately same time as OPEN ACS scripts) virtual void MapLoaded(); // called when the map is about to unload (approximately same time as UNLOADING ACS scripts) @@ -48,11 +54,17 @@ public: // called after adding each actor to the render list virtual void RenderAfterThing(AActor* thing); }; -extern DEventHandler* E_FirstEventHandler; - -class DRenderEventHandler : public DEventHandler +class DEventHandler : public DStaticEventHandler { - DECLARE_CLASS(DRenderEventHandler, DEventHandler) + DECLARE_CLASS(DEventHandler, DStaticEventHandler) // TODO: make sure this does not horribly break anything +public: + bool IsStatic() override { return false; } +}; +extern DStaticEventHandler* E_FirstEventHandler; + +class DStaticRenderEventHandler : public DStaticEventHandler +{ + DECLARE_CLASS(DStaticRenderEventHandler, DStaticEventHandler) public: // these are for all render events DVector3 ViewPos; @@ -91,5 +103,11 @@ public: private: void Setup(); }; +class DRenderEventHandler : public DStaticRenderEventHandler +{ + DECLARE_CLASS(DRenderEventHandler, DStaticRenderEventHandler) // TODO: make sure this does not horribly break anythings +public: + bool IsStatic() override { return false; } +}; #endif \ No newline at end of file diff --git a/src/g_level.cpp b/src/g_level.cpp index a71b481c93..e92642d002 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -85,6 +85,7 @@ #include "p_spec.h" #include "serializer.h" #include "virtual.h" +#include "events.h" #include "gi.h" @@ -655,6 +656,7 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill // [RH] Give scripts a chance to do something unloading = true; FBehavior::StaticStartTypedScripts (SCRIPT_Unloading, NULL, false, 0, true); + E_MapUnloading(); unloading = false; STAT_ChangeLevel(nextlevel); diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index fcf56fa7d8..e2dc6feff9 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -650,7 +650,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) if (thing == nullptr) return; - DRenderEventHandler::AutoThing autoRenderThingEvent(thing); + DStaticRenderEventHandler::AutoThing autoRenderThingEvent(thing); // [ZZ] allow CustomSprite-style direct picnum specification bool isPicnumOverride = thing->picnum.isValid(); diff --git a/src/p_spec.cpp b/src/p_spec.cpp index e5a1178d87..89f920b2f0 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -39,6 +39,7 @@ #include "d_event.h" #include "g_level.h" #include "gstrings.h" +#include "events.h" #include "i_system.h" #include "m_argv.h" @@ -1442,6 +1443,8 @@ void P_SpawnSpecials (void) break; } } + // [ZZ] Loading event hook + E_MapLoaded(); // [RH] Start running any open scripts on this map FBehavior::StaticStartTypedScripts (SCRIPT_Open, NULL, false); } diff --git a/src/r_things.cpp b/src/r_things.cpp index 6a4bf0d1ad..65e33c5b1e 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1245,7 +1245,7 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) if (thing->validcount == validcount) continue; thing->validcount = validcount; - DRenderEventHandler::AutoThing autoRenderThingEvent(thing); + DStaticRenderEventHandler::AutoThing autoRenderThingEvent(thing); FIntCVar *cvar = thing->GetClass()->distancecheck; if (cvar != NULL && *cvar >= 0) diff --git a/wadsrc/static/zscript/events.txt b/wadsrc/static/zscript/events.txt index 8f091e4f52..6d0be8cf5b 100755 --- a/wadsrc/static/zscript/events.txt +++ b/wadsrc/static/zscript/events.txt @@ -1,12 +1,5 @@ -class EventHandler : Object native +class StaticEventHandler : Object native { - static native EventHandler Create(class type); - static native EventHandler CreateOnce(class type); - static native EventHandler Find(class type); - - static native bool Register(EventHandler handler); - static native bool Unregister(EventHandler handler); - virtual native void MapLoaded(); virtual native void MapUnloading(); @@ -16,7 +9,7 @@ class EventHandler : Object native virtual native void RenderAfterThing(); } -class RenderEventHandler : EventHandler native +class StaticRenderEventHandler : StaticEventHandler native { // for frame and camera native readonly Vector3 ViewPos; @@ -28,4 +21,16 @@ class RenderEventHandler : EventHandler native native readonly Actor Camera; // for thing native readonly Actor CurrentThing; -} \ No newline at end of file +} + +class EventHandler : StaticEventHandler native +{ + static native StaticEventHandler Create(class type); + static native StaticEventHandler CreateOnce(class type); + static native StaticEventHandler Find(class type); + + static native bool Register(StaticEventHandler handler); + static native bool Unregister(StaticEventHandler handler); +} + +class RenderEventHandler : StaticRenderEventHandler native { }