From 60406a3cb621c079b45cd64668fd5091b5c18d63 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 02:33:53 +0200 Subject: [PATCH 01/12] Added: prototype event system --- src/CMakeLists.txt | 1 + src/d_main.cpp | 4 + src/events.cpp | 184 ++++++++++++++++++++++++++++++++++++++ src/events.h | 60 +++++++++++++ src/gl/scene/gl_scene.cpp | 4 + src/r_main.cpp | 4 + wadsrc/static/zscript.txt | 1 + 7 files changed, 258 insertions(+) create mode 100755 src/events.cpp create mode 100755 src/events.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 870275324..50d873ffd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1214,6 +1214,7 @@ set (PCH_SOURCES scripting/zscript/zcc_expr.cpp scripting/zscript/zcc_parser.cpp sfmt/SFMT.cpp + events.cpp ) enable_precompiled_headers( g_pch.h PCH_SOURCES ) diff --git a/src/d_main.cpp b/src/d_main.cpp index 971e0ece0..6760195db 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -110,6 +110,7 @@ #include "autosegs.h" #include "fragglescript/t_fs.h" #include "g_levellocals.h" +#include "events.h" EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); @@ -775,6 +776,9 @@ void D_Display () screen->SetBlendingRect(viewwindowx, viewwindowy, viewwindowx + viewwidth, viewwindowy + viewheight); + // [ZZ] execute event hook that we just started the frame + E_RenderFrame(); + // Renderer->RenderView(&players[consoleplayer]); if ((hw2d = screen->Begin2D(viewactive))) diff --git a/src/events.cpp b/src/events.cpp new file mode 100755 index 000000000..9de70eb03 --- /dev/null +++ b/src/events.cpp @@ -0,0 +1,184 @@ +#include "events.h" +#include "virtual.h" +#include "r_utility.h" + +DEventHandler* E_FirstDEventHandler = nullptr; + +void E_RegisterHandler(DEventHandler* handler) +{ + if (handler == nullptr || handler->ObjectFlags & OF_EuthanizeMe) + return; + // link into normal list + handler->prev = nullptr; + handler->next = E_FirstDEventHandler; + if (handler->next) + handler->next->prev = handler; + E_FirstDEventHandler = handler; +} + +void E_UnregisterHandler(DEventHandler* handler) +{ + if (handler == nullptr || handler->ObjectFlags & OF_EuthanizeMe) + return; + // link out of normal list + if (handler->prev) + handler->prev->next = handler->next; + if (handler->next) + handler->next->prev = handler->prev; + if (handler == E_FirstDEventHandler) + E_FirstDEventHandler = handler->next; +} + +void E_MapLoaded() +{ + for (DEventHandler* handler = E_FirstDEventHandler; handler; handler = handler->next) + handler->MapLoaded(); +} + +void E_MapUnloading() +{ + for (DEventHandler* handler = E_FirstDEventHandler; handler; handler = handler->next) + handler->MapUnloading(); +} + +void E_RenderFrame() +{ + for (DEventHandler* handler = E_FirstDEventHandler; handler; handler = handler->next) + handler->RenderFrame(); +} + +void E_RenderCamera() +{ + for (DEventHandler* handler = E_FirstDEventHandler; handler; handler = handler->next) + handler->RenderCamera(); +} + +// declarations +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_ACTION_FUNCTION(DEventHandler, Create) +{ + PARAM_PROLOGUE; + PARAM_CLASS(t, DEventHandler); + // generate a new object of this type. + ACTION_RETURN_OBJECT(t->CreateNew()); +} + +DEFINE_ACTION_FUNCTION(DEventHandler, Register) +{ + PARAM_PROLOGUE; + PARAM_OBJECT(handler, DEventHandler); + E_RegisterHandler(handler); + return 0; +} + +DEFINE_ACTION_FUNCTION(DEventHandler, Unregister) +{ + PARAM_PROLOGUE; + PARAM_OBJECT(handler, DEventHandler); + E_UnregisterHandler(handler); + return 0; +} + +DEFINE_ACTION_FUNCTION(DEventHandler, MapLoaded) +{ + PARAM_SELF_PROLOGUE(DEventHandler); + // do nothing + return 0; +} + +DEFINE_ACTION_FUNCTION(DEventHandler, MapUnloading) +{ + PARAM_SELF_PROLOGUE(DEventHandler); + // do nothing + return 0; +} + +DEFINE_ACTION_FUNCTION(DEventHandler, RenderFrame) +{ + PARAM_SELF_PROLOGUE(DEventHandler); + // do nothing + return 0; +} + +DEFINE_ACTION_FUNCTION(DEventHandler, RenderCamera) +{ + PARAM_SELF_PROLOGUE(DEventHandler); + // do nothing + return 0; +} + +// +void DEventHandler::OnDestroy() +{ + E_UnregisterHandler(this); + DObject::OnDestroy(); +} + +void DEventHandler::MapLoaded() +{ + IFVIRTUAL(DEventHandler, MapLoaded) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DEventHandler*)this }; + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + } +} + +void DEventHandler::MapUnloading() +{ + IFVIRTUAL(DEventHandler, MapUnloading) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DEventHandler*)this }; + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + } +} + +void DEventHandler::RenderFrame() +{ + IFVIRTUAL(DEventHandler, RenderFrame) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DEventHandler*)this }; + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + } +} + +void DEventHandler::RenderCamera() +{ + IFVIRTUAL(DEventHandler, RenderCamera) + { + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DEventHandler*)this }; + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + } +} + +void DRenderEventHandler::Setup() +{ + ViewPos = ::ViewPos; + ViewAngle = ::ViewAngle; + ViewPitch = ::ViewPitch; + ViewRoll = ::ViewRoll; + FracTic = ::r_TicFracF; +} + +void DRenderEventHandler::RenderFrame() +{ + Setup(); + DEventHandler::RenderFrame(); +} + +void DRenderEventHandler::RenderCamera() +{ + Setup(); + DEventHandler::RenderCamera(); +} diff --git a/src/events.h b/src/events.h new file mode 100755 index 000000000..b254ddfaf --- /dev/null +++ b/src/events.h @@ -0,0 +1,60 @@ +#ifndef EVENTS_H +#define EVENTS_H + +#include "dobject.h" + +class DEventHandler : public DObject // make it a part of normal GC process +{ + DECLARE_CLASS(DEventHandler, DObject) +public: + DEventHandler* prev; + DEventHandler* next; + DEventHandler* unregPrev; + DEventHandler* unregNext; + + // destroy handler. this unlinks EventHandler from the list automatically. + void OnDestroy() override; + + // 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) + virtual void MapUnloading(); + // called on each render frame once. + virtual void RenderFrame(); + // called before entering each actor's view (including RenderFrame) + virtual void RenderCamera(); +}; +extern DEventHandler* E_FirstEventHandler; + +class DRenderEventHandler : public DEventHandler +{ + DECLARE_CLASS(DRenderEventHandler, DEventHandler) +public: + DVector3 ViewPos; + DAngle ViewAngle; + DAngle ViewPitch; + DAngle ViewRoll; + double FracTic; // 0..1 value that describes where we are inside the current gametic, render-wise. + + void RenderFrame() override; + void RenderCamera() override; + +private: + void Setup(); +}; + +// register +void E_RegisterHandler(DEventHandler* handler); +// unregister +void E_UnregisterHandler(DEventHandler* handler); + +// called right after the map has loaded (approximately same time as OPEN ACS scripts) +void E_MapLoaded(); +// called when the map is about to unload (approximately same time as UNLOADING ACS scripts) +void E_MapUnloading(); +// called on each render frame once. +void E_RenderFrame(); +// called before entering each actor's view (including RenderFrame) +void E_RenderCamera(); + +#endif \ No newline at end of file diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index b67cf810e..f3b37ffb5 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -44,6 +44,7 @@ #include "gl/gl_functions.h" #include "serializer.h" #include "g_levellocals.h" +#include "events.h" #include "gl/dynlights/gl_lightbuffer.h" #include "gl/system/gl_interface.h" @@ -477,6 +478,9 @@ void FGLRenderer::RenderTranslucent() void FGLRenderer::DrawScene(int drawmode) { + // [ZZ] call event hook + E_RenderCamera(); + static int recursion=0; static int ssao_portals_available = 0; diff --git a/src/r_main.cpp b/src/r_main.cpp index 7030339c7..11e7cfc09 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -59,6 +59,7 @@ #include "r_data/colormaps.h" #include "p_maputl.h" #include "r_thread.h" +#include "events.h" CVAR (String, r_viewsize, "", CVAR_NOSET) CVAR (Bool, r_shadercolormaps, true, CVAR_ARCHIVE) @@ -840,6 +841,9 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) R_SetupBuffer (); R_SetupFrame (actor); + // [ZZ] call event hook + E_RenderCamera(); + // Clear buffers. R_ClearClipSegs (0, viewwidth); R_ClearDrawSegs (); diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 7cd9722bc..9f1033b17 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -5,6 +5,7 @@ #include "zscript/constants.txt" #include "zscript/actor.txt" #include "zscript/actor_checks.txt" +#include "zscript/events.txt" #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" From 4c082d968edea3375dcd2c057148d49072394ccb Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 02:56:15 +0200 Subject: [PATCH 02/12] Added EventHandler.CreateOnce and EventHandler.Find to refer to handlers after they are created --- src/events.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index 9de70eb03..93973bd6f 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -2,7 +2,7 @@ #include "virtual.h" #include "r_utility.h" -DEventHandler* E_FirstDEventHandler = nullptr; +DEventHandler* E_FirstEventHandler = nullptr; void E_RegisterHandler(DEventHandler* handler) { @@ -10,10 +10,10 @@ void E_RegisterHandler(DEventHandler* handler) return; // link into normal list handler->prev = nullptr; - handler->next = E_FirstDEventHandler; + handler->next = E_FirstEventHandler; if (handler->next) handler->next->prev = handler; - E_FirstDEventHandler = handler; + E_FirstEventHandler = handler; } void E_UnregisterHandler(DEventHandler* handler) @@ -25,31 +25,31 @@ void E_UnregisterHandler(DEventHandler* handler) handler->prev->next = handler->next; if (handler->next) handler->next->prev = handler->prev; - if (handler == E_FirstDEventHandler) - E_FirstDEventHandler = handler->next; + if (handler == E_FirstEventHandler) + E_FirstEventHandler = handler->next; } void E_MapLoaded() { - for (DEventHandler* handler = E_FirstDEventHandler; handler; handler = handler->next) + for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->MapLoaded(); } void E_MapUnloading() { - for (DEventHandler* handler = E_FirstDEventHandler; handler; handler = handler->next) + for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->MapUnloading(); } void E_RenderFrame() { - for (DEventHandler* handler = E_FirstDEventHandler; handler; handler = handler->next) + for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->RenderFrame(); } void E_RenderCamera() { - for (DEventHandler* handler = E_FirstDEventHandler; handler; handler = handler->next) + for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) handler->RenderCamera(); } @@ -71,6 +71,28 @@ DEFINE_ACTION_FUNCTION(DEventHandler, Create) ACTION_RETURN_OBJECT(t->CreateNew()); } +DEFINE_ACTION_FUNCTION(DEventHandler, CreateOnce) +{ + PARAM_PROLOGUE; + PARAM_CLASS(t, DEventHandler); + // check if there are already registered handlers of this type. + for (DEventHandler* 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. + ACTION_RETURN_OBJECT(t->CreateNew()); +} + +DEFINE_ACTION_FUNCTION(DEventHandler, Find) +{ + PARAM_PROLOGUE; + PARAM_CLASS(t, DEventHandler); + for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + if (handler->GetClass() == t) // check precise class + ACTION_RETURN_OBJECT(handler); + ACTION_RETURN_OBJECT(nullptr); +} + DEFINE_ACTION_FUNCTION(DEventHandler, Register) { PARAM_PROLOGUE; From f5c29ec3e2bb37410747f9b5022ff449eca65be0 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 04:15:30 +0200 Subject: [PATCH 03/12] Forgot to add events.txt --- wadsrc/static/zscript/events.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100755 wadsrc/static/zscript/events.txt diff --git a/wadsrc/static/zscript/events.txt b/wadsrc/static/zscript/events.txt new file mode 100755 index 000000000..080dfe3cf --- /dev/null +++ b/wadsrc/static/zscript/events.txt @@ -0,0 +1,24 @@ +class EventHandler : 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(); + + virtual native void RenderFrame(); + virtual native void RenderCamera(); +} + +class RenderEventHandler : EventHandler native +{ + native readonly Vector3 ViewPos; + native readonly double ViewAngle; + native readonly double ViewPitch; + native readonly double ViewRoll; + native readonly double FracTic; +} \ No newline at end of file From 841c7c9712243efd7516a5ae88f28686f6aafe5b Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 06:23:44 +0200 Subject: [PATCH 04/12] Generalized event handler definition; removed excessive VM calls when we don't have override defined. --- src/events.cpp | 83 +++++++++++--------------------------------------- 1 file changed, 18 insertions(+), 65 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index 93973bd6f..1767ac333 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -109,33 +109,26 @@ DEFINE_ACTION_FUNCTION(DEventHandler, Unregister) return 0; } -DEFINE_ACTION_FUNCTION(DEventHandler, MapLoaded) -{ - PARAM_SELF_PROLOGUE(DEventHandler); - // do nothing - return 0; +#define DEFINE_EVENT_HANDLER(cls, funcname) DEFINE_ACTION_FUNCTION(cls, funcname) \ +{ \ + PARAM_SELF_PROLOGUE(cls); \ + return 0; \ +} \ +void cls::funcname() \ +{ \ + IFVIRTUAL(cls, funcname) \ + { \ + if (func == cls##_##funcname##_VMPtr) \ + return; \ + VMValue params[1] = { (cls*)this }; \ + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); \ + } \ } -DEFINE_ACTION_FUNCTION(DEventHandler, MapUnloading) -{ - PARAM_SELF_PROLOGUE(DEventHandler); - // do nothing - return 0; -} - -DEFINE_ACTION_FUNCTION(DEventHandler, RenderFrame) -{ - PARAM_SELF_PROLOGUE(DEventHandler); - // do nothing - return 0; -} - -DEFINE_ACTION_FUNCTION(DEventHandler, RenderCamera) -{ - PARAM_SELF_PROLOGUE(DEventHandler); - // do nothing - return 0; -} +DEFINE_EVENT_HANDLER(DEventHandler, MapLoaded) +DEFINE_EVENT_HANDLER(DEventHandler, MapUnloading) +DEFINE_EVENT_HANDLER(DEventHandler, RenderFrame) +DEFINE_EVENT_HANDLER(DEventHandler, RenderCamera) // void DEventHandler::OnDestroy() @@ -144,46 +137,6 @@ void DEventHandler::OnDestroy() DObject::OnDestroy(); } -void DEventHandler::MapLoaded() -{ - IFVIRTUAL(DEventHandler, MapLoaded) - { - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DEventHandler*)this }; - GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); - } -} - -void DEventHandler::MapUnloading() -{ - IFVIRTUAL(DEventHandler, MapUnloading) - { - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DEventHandler*)this }; - GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); - } -} - -void DEventHandler::RenderFrame() -{ - IFVIRTUAL(DEventHandler, RenderFrame) - { - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DEventHandler*)this }; - GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); - } -} - -void DEventHandler::RenderCamera() -{ - IFVIRTUAL(DEventHandler, RenderCamera) - { - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DEventHandler*)this }; - GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); - } -} - void DRenderEventHandler::Setup() { ViewPos = ::ViewPos; From 9c1c7129c18d671b487f358933e2482990599537 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 07:04:35 +0200 Subject: [PATCH 05/12] Added per-thing render hooks --- src/events.cpp | 41 ++++++++++++++++++--- src/events.h | 63 +++++++++++++++++++++++++------- src/gl/scene/gl_sprite.cpp | 3 ++ src/r_things.cpp | 3 ++ wadsrc/static/zscript/events.txt | 7 ++++ 5 files changed, 97 insertions(+), 20 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index 1767ac333..4516f32c9 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -53,6 +53,18 @@ void E_RenderCamera() handler->RenderCamera(); } +void E_RenderBeforeThing(AActor* thing) +{ + for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + handler->RenderBeforeThing(thing); +} + +void E_RenderAfterThing(AActor* thing) +{ + for (DEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + handler->RenderAfterThing(thing); +} + // declarations IMPLEMENT_CLASS(DEventHandler, false, false); IMPLEMENT_CLASS(DRenderEventHandler, false, false); @@ -62,6 +74,8 @@ 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_ACTION_FUNCTION(DEventHandler, Create) { @@ -109,12 +123,12 @@ DEFINE_ACTION_FUNCTION(DEventHandler, Unregister) return 0; } -#define DEFINE_EVENT_HANDLER(cls, funcname) DEFINE_ACTION_FUNCTION(cls, funcname) \ +#define DEFINE_EVENT_HANDLER(cls, funcname, args) DEFINE_ACTION_FUNCTION(cls, funcname) \ { \ PARAM_SELF_PROLOGUE(cls); \ return 0; \ } \ -void cls::funcname() \ +void cls::funcname(args) \ { \ IFVIRTUAL(cls, funcname) \ { \ @@ -125,10 +139,12 @@ void cls::funcname() \ } \ } -DEFINE_EVENT_HANDLER(DEventHandler, MapLoaded) -DEFINE_EVENT_HANDLER(DEventHandler, MapUnloading) -DEFINE_EVENT_HANDLER(DEventHandler, RenderFrame) -DEFINE_EVENT_HANDLER(DEventHandler, RenderCamera) +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*) // void DEventHandler::OnDestroy() @@ -144,6 +160,7 @@ void DRenderEventHandler::Setup() ViewPitch = ::ViewPitch; ViewRoll = ::ViewRoll; FracTic = ::r_TicFracF; + Camera = ::camera; } void DRenderEventHandler::RenderFrame() @@ -157,3 +174,15 @@ void DRenderEventHandler::RenderCamera() Setup(); DEventHandler::RenderCamera(); } + +void DRenderEventHandler::RenderBeforeThing(AActor* thing) +{ + CurrentThing = thing; + DEventHandler::RenderBeforeThing(thing); +} + +void DRenderEventHandler::RenderAfterThing(AActor* thing) +{ + CurrentThing = thing; + DEventHandler::RenderAfterThing(thing); +} \ No newline at end of file diff --git a/src/events.h b/src/events.h index b254ddfaf..d8e647432 100755 --- a/src/events.h +++ b/src/events.h @@ -3,6 +3,26 @@ #include "dobject.h" +class DEventHandler; + +// register +void E_RegisterHandler(DEventHandler* handler); +// unregister +void E_UnregisterHandler(DEventHandler* handler); + +// called right after the map has loaded (approximately same time as OPEN ACS scripts) +void E_MapLoaded(); +// called when the map is about to unload (approximately same time as UNLOADING ACS scripts) +void E_MapUnloading(); +// called on each render frame once. +void E_RenderFrame(); +// called before entering each actor's view (including RenderFrame) +void E_RenderCamera(); +// called before adding each actor to the render list +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 { DECLARE_CLASS(DEventHandler, DObject) @@ -23,6 +43,10 @@ public: virtual void RenderFrame(); // called before entering each actor's view (including RenderFrame) virtual void RenderCamera(); + // called before adding each actor to the render list + virtual void RenderBeforeThing(AActor* thing); + // called after adding each actor to the render list + virtual void RenderAfterThing(AActor* thing); }; extern DEventHandler* E_FirstEventHandler; @@ -30,31 +54,42 @@ class DRenderEventHandler : public DEventHandler { DECLARE_CLASS(DRenderEventHandler, DEventHandler) public: + // these are for all render events DVector3 ViewPos; DAngle ViewAngle; DAngle ViewPitch; DAngle ViewRoll; double FracTic; // 0..1 value that describes where we are inside the current gametic, render-wise. + // this makes sense in RenderCamera + AActor* Camera; + // this is for RenderBeforeThing and RenderAfterThing + AActor* CurrentThing; void RenderFrame() override; void RenderCamera() override; + void RenderBeforeThing(AActor* thing) override; + void RenderAfterThing(AActor* thing) override; + + // this is a class that I use to automatically call RenderAfterThing. + // C++ is really horrible for not providing try-finally statement. + struct AutoThing + { + AActor* thing; + + AutoThing(AActor* thing) + { + this->thing = thing; + E_RenderBeforeThing(this->thing); + } + + ~AutoThing() + { + E_RenderAfterThing(this->thing); + } + }; private: void Setup(); }; -// register -void E_RegisterHandler(DEventHandler* handler); -// unregister -void E_UnregisterHandler(DEventHandler* handler); - -// called right after the map has loaded (approximately same time as OPEN ACS scripts) -void E_MapLoaded(); -// called when the map is about to unload (approximately same time as UNLOADING ACS scripts) -void E_MapUnloading(); -// called on each render frame once. -void E_RenderFrame(); -// called before entering each actor's view (including RenderFrame) -void E_RenderCamera(); - #endif \ No newline at end of file diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index adbc626ed..fcf56fa7d 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -37,6 +37,7 @@ #include "a_pickups.h" #include "d_player.h" #include "g_levellocals.h" +#include "events.h" #include "gl/system/gl_interface.h" #include "gl/system/gl_framebuffer.h" @@ -649,6 +650,8 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) if (thing == nullptr) return; + DRenderEventHandler::AutoThing autoRenderThingEvent(thing); + // [ZZ] allow CustomSprite-style direct picnum specification bool isPicnumOverride = thing->picnum.isValid(); diff --git a/src/r_things.cpp b/src/r_things.cpp index b6b4a472a..6a4bf0d1a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -66,6 +66,7 @@ #include "p_maputl.h" #include "g_levellocals.h" #include "r_thread.h" +#include "events.h" EXTERN_CVAR(Bool, st_scale) EXTERN_CVAR(Bool, r_shadercolormaps) @@ -1244,6 +1245,8 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) if (thing->validcount == validcount) continue; thing->validcount = validcount; + DRenderEventHandler::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 080dfe3cf..8f091e4f5 100755 --- a/wadsrc/static/zscript/events.txt +++ b/wadsrc/static/zscript/events.txt @@ -12,13 +12,20 @@ class EventHandler : Object native virtual native void RenderFrame(); virtual native void RenderCamera(); + virtual native void RenderBeforeThing(); + virtual native void RenderAfterThing(); } class RenderEventHandler : EventHandler native { + // for frame and camera native readonly Vector3 ViewPos; native readonly double ViewAngle; native readonly double ViewPitch; native readonly double ViewRoll; native readonly double FracTic; + // for camera + native readonly Actor Camera; + // for thing + native readonly Actor CurrentThing; } \ No newline at end of file From 578ae9b62ae0a2a3b2dcff7f051f115990c7a0fc Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 07:29:18 +0200 Subject: [PATCH 06/12] Fixed RenderCamera event in software renderer --- src/r_main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/r_main.cpp b/src/r_main.cpp index 11e7cfc09..25e3021f0 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -618,6 +618,9 @@ void R_HighlightPortal (PortalDrawseg* pds) void R_EnterPortal (PortalDrawseg* pds, int depth) { + // [ZZ] portal hook + E_RenderCamera(); + // [ZZ] check depth. fill portal with black if it's exceeding the visual recursion limit, and continue like nothing happened. if (depth >= r_portal_recursions) { From 5e53b73d604cbddaaa210936120770489524a3e2 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 07:50:18 +0200 Subject: [PATCH 07/12] More portal fixing in software renderer --- src/r_main.cpp | 6 +++--- src/r_plane.cpp | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 25e3021f0..1ae22ba3f 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -618,9 +618,6 @@ void R_HighlightPortal (PortalDrawseg* pds) void R_EnterPortal (PortalDrawseg* pds, int depth) { - // [ZZ] portal hook - E_RenderCamera(); - // [ZZ] check depth. fill portal with black if it's exceeding the visual recursion limit, and continue like nothing happened. if (depth >= r_portal_recursions) { @@ -723,6 +720,9 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) R_CopyStackedViewParameters(); + // [ZZ] portal hook + E_RenderCamera(); + validcount++; PortalDrawseg* prevpds = CurrentPortal; CurrentPortal = pds; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 29f852ece..b452d97a0 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -59,6 +59,7 @@ #include "v_palette.h" #include "r_data/colormaps.h" #include "g_levellocals.h" +#include "events.h" #ifdef _MSC_VER #pragma warning(disable:4244) @@ -1178,6 +1179,8 @@ void R_DrawPortals () R_SetViewAngle (); validcount++; // Make sure we see all sprites + E_RenderCamera(); + R_ClearPlanes (false); R_ClearClipSegs (pl->left, pl->right); WindowLeft = pl->left; From fb1d55101e3f00e15f05c4683c58b70bfc48569c Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 08:56:57 +0200 Subject: [PATCH 08/12] 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 4516f32c9..dc563692a 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 d8e647432..b6a858834 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 a71b481c9..e92642d00 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 fcf56fa7d..e2dc6feff 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 e5a1178d8..89f920b2f 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 6a4bf0d1a..65e33c5b1 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 8f091e4f5..6d0be8cf5 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 { } From 2de98c2dd3a04bf4527e87f57fad84d1abdb95db Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 08:58:59 +0200 Subject: [PATCH 09/12] Hopefully I'm using OF_Fixed correctly --- src/events.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/events.cpp b/src/events.cpp index dc563692a..29647fa6a 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -16,6 +16,7 @@ bool E_RegisterHandler(DStaticEventHandler* handler) if (handler->next) handler->next->prev = handler; E_FirstEventHandler = handler; + if (handler->IsStatic()) handler->ObjectFlags |= OF_Fixed; return true; } @@ -32,6 +33,11 @@ bool E_UnregisterHandler(DStaticEventHandler* handler) handler->next->prev = handler->prev; if (handler == E_FirstEventHandler) E_FirstEventHandler = handler->next; + if (handler->IsStatic()) + { + handler->ObjectFlags |= OF_YesReallyDelete; + delete handler; + } return true; } From 9b3b21c7352589d3ea4d82ff54f09bb4ac59b14b Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 09:36:39 +0200 Subject: [PATCH 10/12] Added EventHandlers in Map section of MAPINFO --- src/events.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++---- src/events.h | 5 ++++ src/g_level.cpp | 2 ++ src/g_level.h | 2 ++ src/g_mapinfo.cpp | 12 ++++++++ 5 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index 29647fa6a..97b32df41 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -1,6 +1,8 @@ #include "events.h" #include "virtual.h" #include "r_utility.h" +#include "g_levellocals.h" +#include "v_text.h" DStaticEventHandler* E_FirstEventHandler = nullptr; @@ -16,7 +18,7 @@ bool E_RegisterHandler(DStaticEventHandler* handler) if (handler->next) handler->next->prev = handler; E_FirstEventHandler = handler; - if (handler->IsStatic()) handler->ObjectFlags |= OF_Fixed; + if (handler->IsStatic() && handler->isMapScope) handler->ObjectFlags |= OF_Fixed; return true; } @@ -33,7 +35,7 @@ bool E_UnregisterHandler(DStaticEventHandler* handler) handler->next->prev = handler->prev; if (handler == E_FirstEventHandler) E_FirstEventHandler = handler->next; - if (handler->IsStatic()) + if (handler->IsStatic() && handler->isMapScope) { handler->ObjectFlags |= OF_YesReallyDelete; delete handler; @@ -48,6 +50,64 @@ bool E_CheckHandler(DStaticEventHandler* handler) return false; } +bool E_IsStaticType(PClass* type) +{ + return (!type->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && + !type->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))); +} + +void E_InitStaticHandlers(bool map) +{ + // remove existing + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + { + if (handler->IsStatic() && handler->isMapScope == map) + handler->Destroy(); + } + + // add new + if (map) + { + for (unsigned int i = 0; i < level.info->EventHandlers.Size(); i++) + { + FString typestring = level.info->EventHandlers[i]; + PClass* type = PClass::FindClass(typestring); + + if (type == nullptr) + { + Printf("%cGWarning: unknown event handler class %s in MAPINFO!", TEXTCOLOR_ESCAPE, typestring.GetChars()); + continue; + } + + if (!E_IsStaticType(type)) + { + Printf("%cGWarning: invalid event handler class %s in MAPINFO!\nMAPINFO event handlers should inherit Static* directly!", TEXTCOLOR_ESCAPE, typestring.GetChars()); + continue; + } + + // check if type already exists, don't add twice. + bool typeExists = false; + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + { + if (handler->IsA(type)) + { + typeExists = true; + break; + } + } + + if (typeExists) continue; + DStaticEventHandler* handler = (DStaticEventHandler*)type->CreateNew(); + handler->isMapScope = true; + E_RegisterHandler(handler); + } + } + else + { + + } +} + void E_MapLoaded() { for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) @@ -104,8 +164,7 @@ DEFINE_ACTION_FUNCTION(DEventHandler, Create) PARAM_PROLOGUE; PARAM_CLASS(t, DStaticEventHandler); // check if type inherits dynamic handlers - if (!t->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && - !t->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))) + if (E_IsStaticType(t)) { // disallow static types creation with Create() ACTION_RETURN_OBJECT(nullptr); @@ -119,8 +178,7 @@ DEFINE_ACTION_FUNCTION(DEventHandler, CreateOnce) PARAM_PROLOGUE; PARAM_CLASS(t, DStaticEventHandler); // check if type inherits dynamic handlers - if (!t->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && - !t->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))) + if (E_IsStaticType(t)) { // disallow static types creation with Create() ACTION_RETURN_OBJECT(nullptr); diff --git a/src/events.h b/src/events.h index b6a858834..8be072735 100755 --- a/src/events.h +++ b/src/events.h @@ -11,6 +11,10 @@ bool E_RegisterHandler(DStaticEventHandler* handler); bool E_UnregisterHandler(DStaticEventHandler* handler); // find bool E_CheckHandler(DStaticEventHandler* handler); +// check type +bool E_IsStaticType(PClass* type); +// init static handlers +void E_InitStaticHandlers(bool map); // called right after the map has loaded (approximately same time as OPEN ACS scripts) void E_MapLoaded(); @@ -33,6 +37,7 @@ public: DStaticEventHandler* next; DStaticEventHandler* unregPrev; DStaticEventHandler* unregNext; + bool isMapScope; // this is only used with IsStatic=true virtual bool IsStatic() { return true; } // destroy handler. this unlinks EventHandler from the list automatically. diff --git a/src/g_level.cpp b/src/g_level.cpp index e92642d00..8ab1f2d48 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1066,6 +1066,8 @@ void G_DoLoadLevel (int position, bool autosave) } } StatusBar->AttachToPlayer (&players[consoleplayer]); + // [ZZ] init per-map static handlers + E_InitStaticHandlers(true); P_DoDeferedScripts (); // [RH] Do script actions that were triggered on another map. if (demoplayback || oldgs == GS_STARTUP || oldgs == GS_TITLELEVEL) diff --git a/src/g_level.h b/src/g_level.h index 1fadcee3a..d59a4fc09 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -338,6 +338,8 @@ struct level_info_t TArray PrecacheSounds; TArray PrecacheTextures; TArray PrecacheClasses; + + TArray EventHandlers; level_info_t() { diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index bb641b23b..a33872ff4 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -52,6 +52,7 @@ #include "version.h" #include "v_text.h" #include "g_levellocals.h" +#include "events.h" TArray wadclusterinfos; TArray wadlevelinfos; @@ -1046,6 +1047,17 @@ DEFINE_MAP_OPTION(PrecacheSounds, true) } while (parse.sc.CheckString(",")); } +DEFINE_MAP_OPTION(EventHandlers, true) +{ + parse.ParseAssign(); + + do + { + parse.sc.MustGetString(); + info->EventHandlers.Push(parse.sc.String); + } while (parse.sc.CheckString(",")); +} + DEFINE_MAP_OPTION(PrecacheTextures, true) { parse.ParseAssign(); From e33a320544e6d51eae769ac2a941bb97c63caee7 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 09:39:33 +0200 Subject: [PATCH 11/12] Fixed static handlers being OF_Fixed: only global (non-map) static handlers should be fixed. --- src/events.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index 97b32df41..8927649f4 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -18,7 +18,7 @@ bool E_RegisterHandler(DStaticEventHandler* handler) if (handler->next) handler->next->prev = handler; E_FirstEventHandler = handler; - if (handler->IsStatic() && handler->isMapScope) handler->ObjectFlags |= OF_Fixed; + if (handler->IsStatic() && !handler->isMapScope) handler->ObjectFlags |= OF_Fixed; return true; } @@ -35,7 +35,7 @@ bool E_UnregisterHandler(DStaticEventHandler* handler) handler->next->prev = handler->prev; if (handler == E_FirstEventHandler) E_FirstEventHandler = handler->next; - if (handler->IsStatic() && handler->isMapScope) + if (handler->IsStatic() && !handler->isMapScope) { handler->ObjectFlags |= OF_YesReallyDelete; delete handler; From d5a0c29a6813df1f5cfd79c2f3e54cb2057d13bd Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Sun, 22 Jan 2017 09:58:48 +0200 Subject: [PATCH 12/12] Implemented global EventHandlers in MAPINFO --- src/events.cpp | 68 ++++++++++++++++++++++++++++--------------------- src/g_level.cpp | 2 ++ src/gi.cpp | 1 + src/gi.h | 1 + src/info.cpp | 4 +++ src/p_spec.cpp | 2 -- 6 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index 8927649f4..504b2667f 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -2,6 +2,7 @@ #include "virtual.h" #include "r_utility.h" #include "g_levellocals.h" +#include "gi.h" #include "v_text.h" DStaticEventHandler* E_FirstEventHandler = nullptr; @@ -56,6 +57,37 @@ bool E_IsStaticType(PClass* type) !type->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))); } +static void E_InitStaticHandler(PClass* type, FString typestring, bool map) +{ + if (type == nullptr) + { + Printf("%cGWarning: unknown event handler class %s in MAPINFO!", TEXTCOLOR_ESCAPE, typestring.GetChars()); + return; + } + + if (!E_IsStaticType(type)) + { + Printf("%cGWarning: invalid event handler class %s in MAPINFO!\nMAPINFO event handlers should inherit Static* directly!", TEXTCOLOR_ESCAPE, typestring.GetChars()); + return; + } + + // check if type already exists, don't add twice. + bool typeExists = false; + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + { + if (handler->IsA(type)) + { + typeExists = true; + break; + } + } + + if (typeExists) return; + DStaticEventHandler* handler = (DStaticEventHandler*)type->CreateNew(); + handler->isMapScope = map; + E_RegisterHandler(handler); +} + void E_InitStaticHandlers(bool map) { // remove existing @@ -72,39 +104,17 @@ void E_InitStaticHandlers(bool map) { FString typestring = level.info->EventHandlers[i]; PClass* type = PClass::FindClass(typestring); - - if (type == nullptr) - { - Printf("%cGWarning: unknown event handler class %s in MAPINFO!", TEXTCOLOR_ESCAPE, typestring.GetChars()); - continue; - } - - if (!E_IsStaticType(type)) - { - Printf("%cGWarning: invalid event handler class %s in MAPINFO!\nMAPINFO event handlers should inherit Static* directly!", TEXTCOLOR_ESCAPE, typestring.GetChars()); - continue; - } - - // check if type already exists, don't add twice. - bool typeExists = false; - for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) - { - if (handler->IsA(type)) - { - typeExists = true; - break; - } - } - - if (typeExists) continue; - DStaticEventHandler* handler = (DStaticEventHandler*)type->CreateNew(); - handler->isMapScope = true; - E_RegisterHandler(handler); + E_InitStaticHandler(type, typestring, true); } } else { - + for (unsigned int i = 0; i < gameinfo.EventHandlers.Size(); i++) + { + FString typestring = gameinfo.EventHandlers[i]; + PClass* type = PClass::FindClass(typestring); + E_InitStaticHandler(type, typestring, false); + } } } diff --git a/src/g_level.cpp b/src/g_level.cpp index 8ab1f2d48..ec4e3049e 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1068,6 +1068,8 @@ void G_DoLoadLevel (int position, bool autosave) StatusBar->AttachToPlayer (&players[consoleplayer]); // [ZZ] init per-map static handlers E_InitStaticHandlers(true); + // call map load hook + E_MapLoaded(); P_DoDeferedScripts (); // [RH] Do script actions that were triggered on another map. if (demoplayback || oldgs == GS_STARTUP || oldgs == GS_TITLELEVEL) diff --git a/src/gi.cpp b/src/gi.cpp index 8d8ff9da7..b1e0b1cf2 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -317,6 +317,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRINGARRAY(PrecachedClasses, "precacheclasses", 0, false) GAMEINFOKEY_STRINGARRAY(PrecachedTextures, "precachetextures", 0, false) GAMEINFOKEY_STRINGARRAY(PrecachedSounds, "precachesounds", 0, false) + GAMEINFOKEY_STRINGARRAY(EventHandlers, "eventhandlers", 0, false) GAMEINFOKEY_STRING(PauseSign, "pausesign") GAMEINFOKEY_STRING(quitSound, "quitSound") GAMEINFOKEY_STRING(BorderFlat, "borderFlat") diff --git a/src/gi.h b/src/gi.h index bd5e84363..1bab4e9a7 100644 --- a/src/gi.h +++ b/src/gi.h @@ -124,6 +124,7 @@ struct gameinfo_t TArray PrecachedClasses; TArray PrecachedTextures; TArray PrecachedSounds; + TArray EventHandlers; FString titleMusic; int titleOrder; diff --git a/src/info.cpp b/src/info.cpp index a424c890f..4167eea04 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -54,6 +54,7 @@ #include "thingdef.h" #include "d_player.h" #include "doomerrors.h" +#include "events.h" extern void LoadActors (); extern void InitBotStuff(); @@ -214,6 +215,9 @@ void PClassActor::StaticInit() ClearStrifeTypes(); LoadActors (); InitBotStuff(); + + // reinit GLOBAL static stuff from gameinfo, once classes are loaded. + E_InitStaticHandlers(false); } //========================================================================== diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 89f920b2f..0eb619723 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -1443,8 +1443,6 @@ 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); }