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.

This commit is contained in:
ZZYZX 2017-01-31 01:28:47 +02:00
parent 5751f84350
commit 27c8140c46
3 changed files with 145 additions and 97 deletions

View file

@ -58,8 +58,7 @@ bool E_CheckHandler(DStaticEventHandler* handler)
bool E_IsStaticType(PClass* type) bool E_IsStaticType(PClass* type)
{ {
return (type->IsDescendantOf(RUNTIME_CLASS(DStaticEventHandler)) && // make sure it's from our hierarchy at all. return (type->IsDescendantOf(RUNTIME_CLASS(DStaticEventHandler)) && // make sure it's from our hierarchy at all.
!type->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && !type->IsDescendantOf(RUNTIME_CLASS(DEventHandler)));
!type->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler)));
} }
void E_SerializeEvents(FSerializer& arc) void E_SerializeEvents(FSerializer& arc)
@ -245,21 +244,20 @@ DEFINE_EVENT_LOOPER(RenderFrame)
// declarations // declarations
IMPLEMENT_CLASS(DStaticEventHandler, false, false); IMPLEMENT_CLASS(DStaticEventHandler, false, false);
IMPLEMENT_CLASS(DStaticRenderEventHandler, false, false);
IMPLEMENT_CLASS(DStaticWorldEventHandler, false, false);
IMPLEMENT_CLASS(DEventHandler, false, false); IMPLEMENT_CLASS(DEventHandler, false, false);
IMPLEMENT_CLASS(DRenderEventHandler, false, false); IMPLEMENT_CLASS(DBaseEvent, false, false)
IMPLEMENT_CLASS(DWorldEventHandler, false, false); IMPLEMENT_CLASS(DRenderEvent, false, false)
IMPLEMENT_CLASS(DWorldEvent, false, false)
DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewPos); DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewPos);
DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewAngle); DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewAngle);
DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewPitch); DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewPitch);
DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewRoll); DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewRoll);
DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, FracTic); DEFINE_FIELD_X(RenderEvent, DRenderEvent, FracTic);
DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, Camera); DEFINE_FIELD_X(RenderEvent, DRenderEvent, Camera);
DEFINE_FIELD_X(StaticWorldEventHandler, DStaticWorldEventHandler, IsSaveGame); DEFINE_FIELD_X(WorldEvent, DWorldEvent, IsSaveGame);
DEFINE_FIELD_X(StaticWorldEventHandler, DStaticWorldEventHandler, Thing); DEFINE_FIELD_X(WorldEvent, DWorldEvent, Thing);
DEFINE_ACTION_FUNCTION(DEventHandler, Create) DEFINE_ACTION_FUNCTION(DEventHandler, Create)
@ -368,19 +366,91 @@ DEFINE_ACTION_FUNCTION(DStaticEventHandler, Unregister)
ACTION_RETURN_BOOL(E_UnregisterHandler(handler)); 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) \ PARAM_SELF_PROLOGUE(cls); \
{ \ return 0; \
VMValue params[1] = { (cls*)this }; \
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); \
} \
} }
DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldLoaded,) DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLoaded)
DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldUnloaded,) DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldUnloaded)
DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldThingSpawned, AActor*) DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingSpawned)
DEFINE_EVENT_HANDLER(DStaticEventHandler, RenderFrame, ) 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() void DStaticEventHandler::OnDestroy()
@ -388,7 +458,7 @@ void DStaticEventHandler::OnDestroy()
E_UnregisterHandler(this); E_UnregisterHandler(this);
Super::OnDestroy(); Super::OnDestroy();
} }
/*
void DStaticRenderEventHandler::Setup() void DStaticRenderEventHandler::Setup()
{ {
ViewPos = ::ViewPos; ViewPos = ::ViewPos;
@ -428,4 +498,4 @@ void DStaticWorldEventHandler::WorldThingSpawned(AActor* actor)
Setup(); Setup();
Thing = actor; Thing = actor;
Super::WorldThingSpawned(actor); Super::WorldThingSpawned(actor);
} }*/

View file

@ -87,16 +87,24 @@ public:
}; };
extern DStaticEventHandler* E_FirstEventHandler; extern DStaticEventHandler* E_FirstEventHandler;
// we cannot call this DEvent because in ZScript, 'event' is a keyword
// ============================================== class DBaseEvent : public DObject
//
// RenderEventHandler - for renderer events
//
// ==============================================
class DStaticRenderEventHandler : public DStaticEventHandler
{ {
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: public:
// these are for all render events // these are for all render events
DVector3 ViewPos; DVector3 ViewPos;
@ -106,7 +114,7 @@ public:
double FracTic; // 0..1 value that describes where we are inside the current gametic, render-wise. double FracTic; // 0..1 value that describes where we are inside the current gametic, render-wise.
AActor* Camera; AActor* Camera;
DStaticRenderEventHandler() DRenderEvent()
{ {
FracTic = 0; FracTic = 0;
Camera = nullptr; Camera = nullptr;
@ -123,34 +131,18 @@ public:
arc("FracTic", FracTic); arc("FracTic", FracTic);
arc("Camera", Camera); 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; }
}; };
// ============================================== class DWorldEvent : public DBaseEvent
//
// WorldEventHandler - for world events
//
// ==============================================
class DStaticWorldEventHandler : public DStaticEventHandler
{ {
DECLARE_CLASS(DStaticWorldEventHandler, DStaticEventHandler) DECLARE_CLASS(DWorldEvent, DBaseEvent)
public: public:
// for WorldLoaded, WorldUnloaded. // for loaded/unloaded
bool IsSaveGame; // this will be true if world event was triggered during savegame loading. bool IsSaveGame;
// for WorldThingSpawned // for thingspawned, thingdied, thingdestroyed
AActor* Thing; AActor* Thing;
DStaticWorldEventHandler() DWorldEvent()
{ {
IsSaveGame = false; IsSaveGame = false;
Thing = nullptr; Thing = nullptr;
@ -162,20 +154,6 @@ public:
arc("IsSaveGame", IsSaveGame); arc("IsSaveGame", IsSaveGame);
arc("Thing", Thing); 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 #endif

View file

@ -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 class StaticEventHandler : Object native
{ {
// static event handlers CAN register other static event handlers. // 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 Register(StaticEventHandler handler);
protected static native bool Unregister(StaticEventHandler handler); protected static native bool Unregister(StaticEventHandler handler);
// world stuff // actual handlers are here
virtual void WorldLoaded() {} virtual native void WorldLoaded(WorldEvent e);
virtual void WorldUnloaded() {} virtual native void WorldUnloaded(WorldEvent e);
virtual void WorldThingSpawned() {} virtual native void WorldThingSpawned(WorldEvent e);
// render stuff
virtual void RenderFrame() {}
}
class StaticRenderEventHandler : StaticEventHandler native virtual native void RenderFrame(RenderEvent e);
{
// 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
} }
class EventHandler : StaticEventHandler native class EventHandler : StaticEventHandler native
@ -44,5 +46,3 @@ class EventHandler : StaticEventHandler native
static native bool Register(StaticEventHandler handler); static native bool Register(StaticEventHandler handler);
static native bool Unregister(StaticEventHandler handler); static native bool Unregister(StaticEventHandler handler);
} }
class RenderEventHandler : StaticRenderEventHandler native { }