2017-01-22 00:33:53 +00:00
# include "events.h"
# include "virtual.h"
# include "r_utility.h"
2017-01-22 07:36:39 +00:00
# include "g_levellocals.h"
2017-01-22 07:58:48 +00:00
# include "gi.h"
2017-01-22 07:36:39 +00:00
# include "v_text.h"
2017-01-30 07:10:33 +00:00
# include "actor.h"
2017-01-22 00:33:53 +00:00
2017-01-22 06:56:57 +00:00
DStaticEventHandler * E_FirstEventHandler = nullptr ;
2017-01-22 00:33:53 +00:00
2017-01-22 06:56:57 +00:00
bool E_RegisterHandler ( DStaticEventHandler * handler )
2017-01-22 00:33:53 +00:00
{
if ( handler = = nullptr | | handler - > ObjectFlags & OF_EuthanizeMe )
2017-01-22 06:56:57 +00:00
return false ;
if ( E_CheckHandler ( handler ) )
return false ;
2017-01-22 00:33:53 +00:00
// link into normal list
handler - > prev = nullptr ;
2017-01-22 00:56:15 +00:00
handler - > next = E_FirstEventHandler ;
2017-01-22 00:33:53 +00:00
if ( handler - > next )
handler - > next - > prev = handler ;
2017-01-22 00:56:15 +00:00
E_FirstEventHandler = handler ;
2017-01-30 05:50:09 +00:00
if ( handler - > IsStatic ( ) )
{
handler - > ObjectFlags | = OF_Fixed ;
}
2017-01-22 06:56:57 +00:00
return true ;
2017-01-22 00:33:53 +00:00
}
2017-01-22 06:56:57 +00:00
bool E_UnregisterHandler ( DStaticEventHandler * handler )
2017-01-22 00:33:53 +00:00
{
if ( handler = = nullptr | | handler - > ObjectFlags & OF_EuthanizeMe )
2017-01-22 06:56:57 +00:00
return false ;
if ( ! E_CheckHandler ( handler ) )
return false ;
2017-01-22 00:33:53 +00:00
// link out of normal list
if ( handler - > prev )
handler - > prev - > next = handler - > next ;
if ( handler - > next )
handler - > next - > prev = handler - > prev ;
2017-01-22 00:56:15 +00:00
if ( handler = = E_FirstEventHandler )
E_FirstEventHandler = handler - > next ;
2017-01-30 05:50:09 +00:00
if ( handler - > IsStatic ( ) )
2017-01-22 06:58:59 +00:00
{
2017-01-30 05:50:09 +00:00
handler - > ObjectFlags & = ~ OF_Fixed ;
handler - > Destroy ( ) ;
2017-01-22 06:58:59 +00:00
}
2017-01-22 06:56:57 +00:00
return true ;
}
bool E_CheckHandler ( DStaticEventHandler * handler )
{
for ( DStaticEventHandler * lhandler = E_FirstEventHandler ; lhandler ; lhandler = lhandler - > next )
if ( handler = = lhandler ) return true ;
return false ;
2017-01-22 00:33:53 +00:00
}
2017-01-22 07:36:39 +00:00
bool E_IsStaticType ( PClass * type )
{
2017-01-23 21:05:51 +00:00
return ( type - > IsDescendantOf ( RUNTIME_CLASS ( DStaticEventHandler ) ) & & // make sure it's from our hierarchy at all.
2017-01-30 23:28:47 +00:00
! type - > IsDescendantOf ( RUNTIME_CLASS ( DEventHandler ) ) ) ;
2017-01-22 07:36:39 +00:00
}
2017-01-23 21:05:51 +00:00
void E_SerializeEvents ( FSerializer & arc )
{
// todo : stuff
2017-01-23 22:17:12 +00:00
if ( arc . BeginArray ( " eventhandlers " ) )
{
int numlocalhandlers = 0 ;
TArray < DStaticEventHandler * > handlers ;
if ( arc . isReading ( ) )
{
numlocalhandlers = arc . ArraySize ( ) ;
// delete all current local handlers, if any
for ( DStaticEventHandler * lhandler = E_FirstEventHandler ; lhandler ; lhandler = lhandler - > next )
if ( ! lhandler - > IsStatic ( ) ) lhandler - > Destroy ( ) ;
}
else
{
for ( DStaticEventHandler * lhandler = E_FirstEventHandler ; lhandler ; lhandler = lhandler - > next )
{
if ( lhandler - > IsStatic ( ) ) continue ;
numlocalhandlers + + ;
handlers . Push ( lhandler ) ;
}
}
for ( int i = 0 ; i < numlocalhandlers ; i + + )
{
// serialize the object properly.
if ( arc . isReading ( ) )
{
// get object and put it into the array
DStaticEventHandler * lhandler ;
arc ( nullptr , lhandler ) ;
if ( lhandler ! = nullptr )
handlers . Push ( lhandler ) ;
}
else
{
: : Serialize < DStaticEventHandler > ( arc , nullptr , handlers [ i ] , nullptr ) ;
}
}
if ( arc . isReading ( ) )
{
// add all newly deserialized handlers into the list
for ( int i = 0 ; i < numlocalhandlers ; i + + )
E_RegisterHandler ( handlers [ i ] ) ;
}
arc . EndArray ( ) ;
}
2017-01-23 21:05:51 +00:00
}
2017-01-22 07:58:48 +00:00
static void E_InitStaticHandler ( PClass * type , FString typestring , bool map )
{
if ( type = = nullptr )
{
2017-01-30 05:50:09 +00:00
Printf ( " %cGWarning: unknown event handler class %s in MAPINFO! \n " , TEXTCOLOR_ESCAPE , typestring . GetChars ( ) ) ;
2017-01-22 07:58:48 +00:00
return ;
}
2017-01-30 06:19:38 +00:00
if ( ! E_IsStaticType ( type ) )
2017-01-22 07:58:48 +00:00
{
2017-01-30 06:19:38 +00:00
Printf ( " %cGWarning: invalid event handler class %s in MAPINFO! \n MAPINFO event handlers should inherit Static* directly! \n " , TEXTCOLOR_ESCAPE , typestring . GetChars ( ) ) ;
2017-01-22 07:58:48 +00:00
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 ( ) ;
2017-01-30 06:19:38 +00:00
handler - > isMapScope = map ;
2017-01-22 07:58:48 +00:00
E_RegisterHandler ( handler ) ;
}
2017-01-22 07:36:39 +00:00
void E_InitStaticHandlers ( bool map )
{
2017-01-30 05:50:09 +00:00
if ( savegamerestore )
return ;
2017-01-22 07:36:39 +00:00
2017-01-30 05:50:09 +00:00
if ( map ) // don't initialize map handlers if restoring from savegame.
2017-01-22 07:36:39 +00:00
{
2017-01-30 06:19:38 +00:00
// delete old map static handlers if any.
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
if ( handler - > IsStatic ( ) & & handler - > isMapScope )
handler - > Destroy ( ) ;
}
2017-01-22 07:36:39 +00:00
for ( unsigned int i = 0 ; i < level . info - > EventHandlers . Size ( ) ; i + + )
{
FString typestring = level . info - > EventHandlers [ i ] ;
PClass * type = PClass : : FindClass ( typestring ) ;
2017-01-22 07:58:48 +00:00
E_InitStaticHandler ( type , typestring , true ) ;
2017-01-22 07:36:39 +00:00
}
}
else
{
2017-01-30 05:50:09 +00:00
// delete old static handlers if any.
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
2017-01-30 06:19:38 +00:00
if ( handler - > IsStatic ( ) & & ! handler - > isMapScope )
2017-01-30 05:50:09 +00:00
handler - > Destroy ( ) ;
}
2017-01-22 07:58:48 +00:00
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 ) ;
}
2017-01-22 07:36:39 +00:00
}
}
2017-01-23 22:17:12 +00:00
# define DEFINE_EVENT_LOOPER(name) void E_##name() \
{ \
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next ) \
handler - > name ( ) ; \
2017-01-22 00:33:53 +00:00
}
2017-01-30 05:50:09 +00:00
// note for the functions below.
// *Unsafe is executed on EVERY map load/close, including savegame loading, etc.
// There is no point in allowing non-static handlers to receive unsafe event separately, as there is no point in having static handlers receive safe event.
// Because the main point of safe WorldLoaded/Unloading is that it will be preserved in savegames.
void E_WorldLoaded ( )
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
2017-01-30 06:19:38 +00:00
if ( handler - > IsStatic ( ) & & ! handler - > isMapScope ) continue ;
if ( handler - > isMapScope & & savegamerestore ) continue ; // don't execute WorldLoaded for handlers loaded from the savegame.
2017-01-30 05:50:09 +00:00
handler - > WorldLoaded ( ) ;
}
}
2017-01-30 06:47:15 +00:00
void E_WorldUnloaded ( )
2017-01-30 05:50:09 +00:00
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
2017-01-30 06:19:38 +00:00
if ( handler - > IsStatic ( ) & & ! handler - > isMapScope ) continue ;
2017-01-30 06:47:15 +00:00
handler - > WorldUnloaded ( ) ;
2017-01-30 05:50:09 +00:00
}
}
void E_WorldLoadedUnsafe ( )
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
2017-01-30 06:19:38 +00:00
if ( ! handler - > IsStatic ( ) | | handler - > isMapScope ) continue ;
2017-01-30 05:50:09 +00:00
handler - > WorldLoaded ( ) ;
}
}
2017-01-30 06:47:15 +00:00
void E_WorldUnloadedUnsafe ( )
2017-01-30 05:50:09 +00:00
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
2017-01-30 06:19:38 +00:00
if ( ! handler - > IsStatic ( ) | | handler - > isMapScope ) continue ;
2017-01-30 06:47:15 +00:00
handler - > WorldUnloaded ( ) ;
2017-01-30 05:50:09 +00:00
}
}
2017-01-30 06:47:15 +00:00
void E_WorldThingSpawned ( AActor * actor )
{
2017-01-30 07:10:33 +00:00
// don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever.
if ( actor - > ObjectFlags & OF_EuthanizeMe )
return ;
2017-01-30 06:47:15 +00:00
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
handler - > WorldThingSpawned ( actor ) ;
}
// normal event loopers (non-special, argument-less)
2017-01-23 22:17:12 +00:00
DEFINE_EVENT_LOOPER ( RenderFrame )
2017-01-22 00:33:53 +00:00
// declarations
2017-01-22 06:56:57 +00:00
IMPLEMENT_CLASS ( DStaticEventHandler , false , false ) ;
2017-01-22 00:33:53 +00:00
IMPLEMENT_CLASS ( DEventHandler , false , false ) ;
2017-01-30 23:28:47 +00:00
IMPLEMENT_CLASS ( DBaseEvent , false , false )
IMPLEMENT_CLASS ( DRenderEvent , false , false )
IMPLEMENT_CLASS ( DWorldEvent , false , false )
2017-01-22 00:33:53 +00:00
2017-01-30 23:28:47 +00:00
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 ) ;
2017-01-22 06:56:57 +00:00
2017-01-30 23:28:47 +00:00
DEFINE_FIELD_X ( WorldEvent , DWorldEvent , IsSaveGame ) ;
DEFINE_FIELD_X ( WorldEvent , DWorldEvent , Thing ) ;
2017-01-30 06:47:15 +00:00
2017-01-22 00:33:53 +00:00
DEFINE_ACTION_FUNCTION ( DEventHandler , Create )
{
PARAM_PROLOGUE ;
2017-01-22 06:56:57 +00:00
PARAM_CLASS ( t , DStaticEventHandler ) ;
// check if type inherits dynamic handlers
2017-01-22 07:36:39 +00:00
if ( E_IsStaticType ( t ) )
2017-01-22 06:56:57 +00:00
{
// disallow static types creation with Create()
ACTION_RETURN_OBJECT ( nullptr ) ;
}
2017-01-22 00:33:53 +00:00
// generate a new object of this type.
ACTION_RETURN_OBJECT ( t - > CreateNew ( ) ) ;
}
2017-01-22 00:56:15 +00:00
DEFINE_ACTION_FUNCTION ( DEventHandler , CreateOnce )
{
PARAM_PROLOGUE ;
2017-01-22 06:56:57 +00:00
PARAM_CLASS ( t , DStaticEventHandler ) ;
// check if type inherits dynamic handlers
2017-01-22 07:36:39 +00:00
if ( E_IsStaticType ( t ) )
2017-01-22 06:56:57 +00:00
{
// disallow static types creation with Create()
ACTION_RETURN_OBJECT ( nullptr ) ;
}
2017-01-22 00:56:15 +00:00
// check if there are already registered handlers of this type.
2017-01-22 06:56:57 +00:00
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
2017-01-22 00:56:15 +00:00
if ( handler - > GetClass ( ) = = t ) // check precise class
2017-01-30 07:28:27 +00:00
ACTION_RETURN_OBJECT ( handler ) ;
// generate a new object of this type.
ACTION_RETURN_OBJECT ( t - > CreateNew ( ) ) ;
}
2017-01-30 07:33:06 +00:00
DEFINE_ACTION_FUNCTION ( DEventHandler , Find )
{
PARAM_PROLOGUE ;
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 ) ;
}
DEFINE_ACTION_FUNCTION ( DEventHandler , Register )
{
PARAM_PROLOGUE ;
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 , DStaticEventHandler ) ;
if ( handler - > IsStatic ( ) ) ACTION_RETURN_BOOL ( false ) ;
ACTION_RETURN_BOOL ( E_UnregisterHandler ( handler ) ) ;
}
2017-01-30 07:28:27 +00:00
// for static
DEFINE_ACTION_FUNCTION ( DStaticEventHandler , Create )
{
PARAM_PROLOGUE ;
PARAM_CLASS ( t , DStaticEventHandler ) ;
// static handlers can create any type of object.
// generate a new object of this type.
ACTION_RETURN_OBJECT ( t - > CreateNew ( ) ) ;
}
DEFINE_ACTION_FUNCTION ( DStaticEventHandler , CreateOnce )
{
PARAM_PROLOGUE ;
PARAM_CLASS ( t , DStaticEventHandler ) ;
// static handlers can create any type of object.
// check if there are already registered handlers of this type.
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
if ( handler - > GetClass ( ) = = t ) // check precise class
ACTION_RETURN_OBJECT ( handler ) ;
2017-01-22 00:56:15 +00:00
// generate a new object of this type.
ACTION_RETURN_OBJECT ( t - > CreateNew ( ) ) ;
}
2017-01-30 07:33:06 +00:00
// we might later want to change this
DEFINE_ACTION_FUNCTION ( DStaticEventHandler , Find )
2017-01-22 00:56:15 +00:00
{
PARAM_PROLOGUE ;
2017-01-22 06:56:57 +00:00
PARAM_CLASS ( t , DStaticEventHandler ) ;
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
2017-01-22 00:56:15 +00:00
if ( handler - > GetClass ( ) = = t ) // check precise class
ACTION_RETURN_OBJECT ( handler ) ;
ACTION_RETURN_OBJECT ( nullptr ) ;
}
2017-01-30 07:28:27 +00:00
DEFINE_ACTION_FUNCTION ( DStaticEventHandler , Register )
{
PARAM_PROLOGUE ;
PARAM_OBJECT ( handler , DStaticEventHandler ) ;
ACTION_RETURN_BOOL ( E_RegisterHandler ( handler ) ) ;
}
DEFINE_ACTION_FUNCTION ( DStaticEventHandler , Unregister )
{
PARAM_PROLOGUE ;
PARAM_OBJECT ( handler , DStaticEventHandler ) ;
ACTION_RETURN_BOOL ( E_UnregisterHandler ( handler ) ) ;
}
2017-01-30 23:28:47 +00:00
# define DEFINE_EMPTY_HANDLER(cls, funcname) DEFINE_ACTION_FUNCTION(cls, funcname) \
2017-01-22 04:23:44 +00:00
{ \
2017-01-30 23:28:47 +00:00
PARAM_SELF_PROLOGUE ( cls ) ; \
return 0 ; \
2017-01-22 04:23:44 +00:00
}
2017-01-30 23:28:47 +00:00
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 ) ;
}
}
2017-01-22 00:33:53 +00:00
//
2017-01-22 06:56:57 +00:00
void DStaticEventHandler : : OnDestroy ( )
2017-01-22 00:33:53 +00:00
{
E_UnregisterHandler ( this ) ;
2017-01-23 22:17:12 +00:00
Super : : OnDestroy ( ) ;
2017-01-22 00:33:53 +00:00
}
2017-01-30 23:28:47 +00:00
/*
2017-01-22 06:56:57 +00:00
void DStaticRenderEventHandler : : Setup ( )
2017-01-22 00:33:53 +00:00
{
ViewPos = : : ViewPos ;
ViewAngle = : : ViewAngle ;
ViewPitch = : : ViewPitch ;
ViewRoll = : : ViewRoll ;
FracTic = : : r_TicFracF ;
2017-01-22 05:04:35 +00:00
Camera = : : camera ;
2017-01-22 00:33:53 +00:00
}
2017-01-22 06:56:57 +00:00
void DStaticRenderEventHandler : : RenderFrame ( )
2017-01-22 00:33:53 +00:00
{
Setup ( ) ;
2017-01-23 22:17:12 +00:00
Super : : RenderFrame ( ) ;
2017-01-22 00:33:53 +00:00
}
2017-01-30 06:47:15 +00:00
void DStaticWorldEventHandler : : Setup ( )
{
IsSaveGame = savegamerestore ;
Thing = nullptr ;
}
void DStaticWorldEventHandler : : WorldLoaded ( )
{
Setup ( ) ;
Super : : WorldLoaded ( ) ;
}
void DStaticWorldEventHandler : : WorldUnloaded ( )
{
Setup ( ) ;
Super : : WorldUnloaded ( ) ;
}
void DStaticWorldEventHandler : : WorldThingSpawned ( AActor * actor )
{
Setup ( ) ;
Thing = actor ;
Super : : WorldThingSpawned ( actor ) ;
2017-01-30 23:28:47 +00:00
} */