From 27c8140c46a781d9ae88a41228a0e930f24ce2c9 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Tue, 31 Jan 2017 01:28:47 +0200 Subject: [PATCH] Replaced specialized event handlers with Event structure passed to a method; returned the check for virtual implementation to make sure that we don't waste time initializing the event data. --- src/events.cpp | 122 ++++++++++++++++++++++++------- src/events.h | 70 ++++++------------ wadsrc/static/zscript/events.txt | 50 ++++++------- 3 files changed, 145 insertions(+), 97 deletions(-) diff --git a/src/events.cpp b/src/events.cpp index c75abdf87..dc10827dd 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -58,8 +58,7 @@ bool E_CheckHandler(DStaticEventHandler* handler) bool E_IsStaticType(PClass* type) { return (type->IsDescendantOf(RUNTIME_CLASS(DStaticEventHandler)) && // make sure it's from our hierarchy at all. - !type->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && - !type->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))); + !type->IsDescendantOf(RUNTIME_CLASS(DEventHandler))); } void E_SerializeEvents(FSerializer& arc) @@ -245,21 +244,20 @@ DEFINE_EVENT_LOOPER(RenderFrame) // declarations IMPLEMENT_CLASS(DStaticEventHandler, false, false); -IMPLEMENT_CLASS(DStaticRenderEventHandler, false, false); -IMPLEMENT_CLASS(DStaticWorldEventHandler, false, false); IMPLEMENT_CLASS(DEventHandler, false, false); -IMPLEMENT_CLASS(DRenderEventHandler, false, false); -IMPLEMENT_CLASS(DWorldEventHandler, false, false); +IMPLEMENT_CLASS(DBaseEvent, false, false) +IMPLEMENT_CLASS(DRenderEvent, false, false) +IMPLEMENT_CLASS(DWorldEvent, false, false) -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(RenderEvent, DRenderEvent, ViewPos); +DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewAngle); +DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewPitch); +DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewRoll); +DEFINE_FIELD_X(RenderEvent, DRenderEvent, FracTic); +DEFINE_FIELD_X(RenderEvent, DRenderEvent, Camera); -DEFINE_FIELD_X(StaticWorldEventHandler, DStaticWorldEventHandler, IsSaveGame); -DEFINE_FIELD_X(StaticWorldEventHandler, DStaticWorldEventHandler, Thing); +DEFINE_FIELD_X(WorldEvent, DWorldEvent, IsSaveGame); +DEFINE_FIELD_X(WorldEvent, DWorldEvent, Thing); DEFINE_ACTION_FUNCTION(DEventHandler, Create) @@ -368,19 +366,91 @@ DEFINE_ACTION_FUNCTION(DStaticEventHandler, Unregister) ACTION_RETURN_BOOL(E_UnregisterHandler(handler)); } -#define DEFINE_EVENT_HANDLER(cls, funcname, args) void cls::funcname(args) \ +#define DEFINE_EMPTY_HANDLER(cls, funcname) DEFINE_ACTION_FUNCTION(cls, funcname) \ { \ - IFVIRTUAL(cls, funcname) \ - { \ - VMValue params[1] = { (cls*)this }; \ - GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); \ - } \ + PARAM_SELF_PROLOGUE(cls); \ + return 0; \ } -DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldLoaded,) -DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldUnloaded,) -DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldThingSpawned, AActor*) -DEFINE_EVENT_HANDLER(DStaticEventHandler, RenderFrame, ) +DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLoaded) +DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldUnloaded) +DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingSpawned) +DEFINE_EMPTY_HANDLER(DStaticEventHandler, RenderFrame) + +static DWorldEvent* E_SetupWorldEvent() +{ + static DWorldEvent* e = nullptr; + if (!e) e = (DWorldEvent*)RUNTIME_CLASS(DWorldEvent)->CreateNew(); + e->IsSaveGame = savegamerestore; + e->Thing = nullptr; + return e; +} + +void DStaticEventHandler::WorldLoaded() +{ + IFVIRTUAL(DStaticEventHandler, WorldLoaded) + { + // don't create excessive DObjects if not going to be processed anyway + if (func == DStaticEventHandler_WorldLoaded_VMPtr) + return; + DWorldEvent* e = E_SetupWorldEvent(); + VMValue params[2] = { (DStaticEventHandler*)this, e }; + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); + } +} + +void DStaticEventHandler::WorldUnloaded() +{ + IFVIRTUAL(DStaticEventHandler, WorldUnloaded) + { + // don't create excessive DObjects if not going to be processed anyway + if (func == DStaticEventHandler_WorldUnloaded_VMPtr) + return; + DWorldEvent* e = E_SetupWorldEvent(); + VMValue params[2] = { (DStaticEventHandler*)this, e }; + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); + } +} + +void DStaticEventHandler::WorldThingSpawned(AActor* actor) +{ + IFVIRTUAL(DStaticEventHandler, WorldThingSpawned) + { + // don't create excessive DObjects if not going to be processed anyway + if (func == DStaticEventHandler_WorldThingSpawned_VMPtr) + return; + DWorldEvent* e = E_SetupWorldEvent(); + e->Thing = actor; + VMValue params[2] = { (DStaticEventHandler*)this, e }; + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); + } +} + +static DRenderEvent* E_SetupRenderEvent() +{ + static DRenderEvent* e = nullptr; + if (!e) e = (DRenderEvent*)RUNTIME_CLASS(DRenderEvent)->CreateNew(); + e->ViewPos = ::ViewPos; + e->ViewAngle = ::ViewAngle; + e->ViewPitch = ::ViewPitch; + e->ViewRoll = ::ViewRoll; + e->FracTic = ::r_TicFracF; + e->Camera = ::camera; + return e; +} + +void DStaticEventHandler::RenderFrame() +{ + IFVIRTUAL(DStaticEventHandler, RenderFrame) + { + // don't create excessive DObjects if not going to be processed anyway + if (func == DStaticEventHandler_RenderFrame_VMPtr) + return; + DRenderEvent* e = E_SetupRenderEvent(); + VMValue params[2] = { (DStaticEventHandler*)this, e }; + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); + } +} // void DStaticEventHandler::OnDestroy() @@ -388,7 +458,7 @@ void DStaticEventHandler::OnDestroy() E_UnregisterHandler(this); Super::OnDestroy(); } - +/* void DStaticRenderEventHandler::Setup() { ViewPos = ::ViewPos; @@ -428,4 +498,4 @@ void DStaticWorldEventHandler::WorldThingSpawned(AActor* actor) Setup(); Thing = actor; Super::WorldThingSpawned(actor); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/events.h b/src/events.h index fa9b16c32..a012730e6 100755 --- a/src/events.h +++ b/src/events.h @@ -87,16 +87,24 @@ public: }; extern DStaticEventHandler* E_FirstEventHandler; - -// ============================================== -// -// RenderEventHandler - for renderer events -// -// ============================================== - -class DStaticRenderEventHandler : public DStaticEventHandler +// we cannot call this DEvent because in ZScript, 'event' is a keyword +class DBaseEvent : public DObject { - DECLARE_CLASS(DStaticRenderEventHandler, DStaticEventHandler) + DECLARE_CLASS(DBaseEvent, DObject) +public: + + DBaseEvent() + { + // each type of event is created only once to avoid new/delete hell + // since from what I remember object creation and deletion results in a lot of GC processing + // (and we aren't supposed to pass event objects around anyway) + this->ObjectFlags |= OF_Fixed; + } +}; + +class DRenderEvent : public DBaseEvent +{ + DECLARE_CLASS(DRenderEvent, DBaseEvent) public: // these are for all render events DVector3 ViewPos; @@ -106,7 +114,7 @@ public: double FracTic; // 0..1 value that describes where we are inside the current gametic, render-wise. AActor* Camera; - DStaticRenderEventHandler() + DRenderEvent() { FracTic = 0; Camera = nullptr; @@ -123,34 +131,18 @@ public: arc("FracTic", FracTic); arc("Camera", Camera); } - - void RenderFrame() override; - -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; } }; -// ============================================== -// -// WorldEventHandler - for world events -// -// ============================================== -class DStaticWorldEventHandler : public DStaticEventHandler +class DWorldEvent : public DBaseEvent { - DECLARE_CLASS(DStaticWorldEventHandler, DStaticEventHandler) + DECLARE_CLASS(DWorldEvent, DBaseEvent) public: - // for WorldLoaded, WorldUnloaded. - bool IsSaveGame; // this will be true if world event was triggered during savegame loading. - // for WorldThingSpawned + // for loaded/unloaded + bool IsSaveGame; + // for thingspawned, thingdied, thingdestroyed AActor* Thing; - DStaticWorldEventHandler() + DWorldEvent() { IsSaveGame = false; Thing = nullptr; @@ -162,20 +154,6 @@ public: arc("IsSaveGame", IsSaveGame); arc("Thing", Thing); } - - void WorldLoaded() override; - void WorldUnloaded() override; - void WorldThingSpawned(AActor*) override; - -private: - void Setup(); -}; -// not sure if anyone wants non-static world handler, but here it is, just in case. -class DWorldEventHandler : public DStaticWorldEventHandler -{ - DECLARE_CLASS(DWorldEventHandler, DStaticWorldEventHandler) -public: - bool IsStatic() override { return false; } }; #endif \ No newline at end of file diff --git a/wadsrc/static/zscript/events.txt b/wadsrc/static/zscript/events.txt index 8e6b1f682..3a0e8d5eb 100755 --- a/wadsrc/static/zscript/events.txt +++ b/wadsrc/static/zscript/events.txt @@ -1,3 +1,23 @@ +class BaseEvent native { } // just a base class. it doesn't inherit from Object on the scripting side so you can't call Destroy() on it and break everything. + +class RenderEvent : BaseEvent native +{ + native readonly Vector3 ViewPos; + native readonly double ViewAngle; + native readonly double ViewPitch; + native readonly double ViewRoll; + native readonly double FracTic; + native readonly Actor Camera; +} + +class WorldEvent : BaseEvent native +{ + // for loaded/unloaded + native readonly bool IsSaveGame; + // for thingspawned/thingdied/thingdestroyed + native readonly Actor Thing; +} + class StaticEventHandler : Object native { // static event handlers CAN register other static event handlers. @@ -9,30 +29,12 @@ class StaticEventHandler : Object native protected static native bool Register(StaticEventHandler handler); protected static native bool Unregister(StaticEventHandler handler); - // world stuff - virtual void WorldLoaded() {} - virtual void WorldUnloaded() {} - virtual void WorldThingSpawned() {} - // render stuff - virtual void RenderFrame() {} -} + // actual handlers are here + virtual native void WorldLoaded(WorldEvent e); + virtual native void WorldUnloaded(WorldEvent e); + virtual native void WorldThingSpawned(WorldEvent e); -class StaticRenderEventHandler : StaticEventHandler 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; - native readonly Actor Camera; -} - -class StaticWorldEventHandler : StaticEventHandler native -{ - // for world - native readonly bool IsSaveGame; // this is set to true if static WorldLoaded was triggered during savegame loading. - native readonly Actor Thing; // this is for WorldThingSpawned + virtual native void RenderFrame(RenderEvent e); } class EventHandler : StaticEventHandler native @@ -44,5 +46,3 @@ class EventHandler : StaticEventHandler native static native bool Register(StaticEventHandler handler); static native bool Unregister(StaticEventHandler handler); } - -class RenderEventHandler : StaticRenderEventHandler native { }