diff --git a/src/events.cpp b/src/events.cpp index 1767ac3338..4516f32c9f 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 b254ddfaf4..d8e647432b 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 adbc626ed6..fcf56fa7d8 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 b6b4a472a9..6a4bf0d1ad 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 080dfe3cf1..8f091e4f52 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