mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
- User definable dynamic lights
This hasn't been tested yet!
This commit is contained in:
parent
1b1069dc78
commit
1dcbe43d95
7 changed files with 235 additions and 6 deletions
|
@ -56,6 +56,7 @@ class FLightDefaults;
|
|||
struct FSection;
|
||||
struct FLevelLocals;
|
||||
struct FDynamicLight;
|
||||
|
||||
//
|
||||
// NOTES: AActor
|
||||
//
|
||||
|
@ -1173,6 +1174,7 @@ public:
|
|||
DRotator PrevAngles;
|
||||
int PrevPortalGroup;
|
||||
TArray<FDynamicLight *> AttachedLights;
|
||||
TDeletingArray<FLightDefaults *> UserLights;
|
||||
|
||||
// When was this actor spawned?
|
||||
int SpawnTime;
|
||||
|
|
|
@ -804,6 +804,144 @@ void AActor::DeleteAttachedLights()
|
|||
AttachedLights.Clear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
extern TDeletingArray<FLightDefaults *> LightDefaults;
|
||||
|
||||
unsigned FindUserLight(AActor *self, FName id, bool create = false)
|
||||
{
|
||||
for (unsigned i = 0; i < self->UserLights.Size(); i++ )
|
||||
{
|
||||
if (self->UserLights[i]->GetName() == id) return i;
|
||||
}
|
||||
if (create)
|
||||
{
|
||||
auto li = new FLightDefaults(id);
|
||||
return self->UserLights.Push(li);
|
||||
}
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int AttachLightDef(AActor *self, int _lightid, int _lightname)
|
||||
{
|
||||
FName lightid = FName(ENamedName(_lightid));
|
||||
FName lightname = FName(ENamedName(_lightname));
|
||||
|
||||
// Todo: Optimize. This may be too slow.
|
||||
auto lightdef = LightDefaults.FindEx([=](const auto &a) {
|
||||
return a->GetName() == lightid;
|
||||
});
|
||||
if (lightdef < LightDefaults.Size())
|
||||
{
|
||||
auto userlight = self->UserLights[FindUserLight(self, lightid, true)];
|
||||
userlight->CopyFrom(*LightDefaults[lightdef]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_AttachLightDef, AttachLightDef)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_NAME(lightid);
|
||||
PARAM_NAME(lightname);
|
||||
ACTION_RETURN_BOOL(AttachLightDef(self, lightid.GetIndex(), lightname.GetIndex()));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int AttachLightDirect(AActor *self, int _lightid, int type, int color, int radius1, int radius2, int flags, double ofs_x, double ofs_y, double ofs_z, double param, double spoti, double spoto, double spotp)
|
||||
{
|
||||
FName lightid = FName(ENamedName(_lightid));
|
||||
auto userlight = self->UserLights[FindUserLight(self, lightid, true)];
|
||||
userlight->SetType(ELightType(type));
|
||||
userlight->SetArg(LIGHT_RED, RPART(color));
|
||||
userlight->SetArg(LIGHT_GREEN, GPART(color));
|
||||
userlight->SetArg(LIGHT_BLUE, BPART(color));
|
||||
userlight->SetArg(LIGHT_INTENSITY, radius1);
|
||||
userlight->SetArg(LIGHT_SECONDARY_INTENSITY, radius2);
|
||||
userlight->SetFlags(LightFlags::FromInt(flags));
|
||||
float of[] = { float(ofs_x), float(ofs_y), float(ofs_z)};
|
||||
userlight->SetOffset(of);
|
||||
userlight->SetParameter(type == PulseLight? param*TICRATE : param*360.);
|
||||
userlight->SetSpotInnerAngle(spoti);
|
||||
userlight->SetSpotOuterAngle(spoto);
|
||||
if (spotp >= -90. && spotp <= 90.)
|
||||
{
|
||||
userlight->SetSpotPitch(spotp);
|
||||
}
|
||||
else
|
||||
{
|
||||
userlight->UnsetSpotPitch();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_AttachLight, AttachLightDirect)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_NAME(lightid);
|
||||
PARAM_INT(type);
|
||||
PARAM_INT(color);
|
||||
PARAM_INT(radius1);
|
||||
PARAM_INT(radius2);
|
||||
PARAM_INT(flags);
|
||||
PARAM_FLOAT(ofs_x);
|
||||
PARAM_FLOAT(ofs_y);
|
||||
PARAM_FLOAT(ofs_z);
|
||||
PARAM_FLOAT(parami);
|
||||
PARAM_FLOAT(spoti);
|
||||
PARAM_FLOAT(spoto);
|
||||
PARAM_FLOAT(spotp);
|
||||
ACTION_RETURN_BOOL(AttachLightDirect(self, lightid, type, color, radius1, radius2, flags, ofs_x, ofs_y, ofs_z, parami, spoti, spoto, spotp));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int RemoveLight(AActor *self, int _lightid)
|
||||
{
|
||||
FName lightid = FName(ENamedName(_lightid));
|
||||
auto userlight = FindUserLight(self, lightid, false);
|
||||
if (userlight < self->UserLights.Size())
|
||||
{
|
||||
delete self->UserLights[userlight];
|
||||
self->UserLights.Delete(userlight);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_RemoveLight, RemoveLight)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_NAME(lightid);
|
||||
ACTION_RETURN_BOOL(RemoveLight(self, lightid));
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// This is called before saving the game
|
||||
|
|
|
@ -54,7 +54,11 @@ DEFINE_TFLAGS_OPERATORS(LightFlags)
|
|||
class FLightDefaults
|
||||
{
|
||||
public:
|
||||
FLightDefaults(FName name, ELightType type);
|
||||
FLightDefaults(FName name, ELightType type = PointLight)
|
||||
{
|
||||
m_Name = name;
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
void ApplyProperties(FDynamicLight * light) const;
|
||||
FName GetName() const { return m_Name; }
|
||||
|
@ -72,6 +76,28 @@ public:
|
|||
void SetSpot(bool spot) { if (spot) m_lightFlags |= LF_SPOT; else m_lightFlags &= ~LF_SPOT; }
|
||||
void SetSpotInnerAngle(double angle) { m_spotInnerAngle = angle; }
|
||||
void SetSpotOuterAngle(double angle) { m_spotOuterAngle = angle; }
|
||||
void SetSpotPitch(double pitch)
|
||||
{
|
||||
m_pitch = pitch;
|
||||
m_explicitPitch = true;
|
||||
}
|
||||
void UnsetSpotPitch()
|
||||
{
|
||||
m_pitch = 0.;
|
||||
m_explicitPitch = false;
|
||||
}
|
||||
void SetType(ELightType type) { m_type = type; }
|
||||
void CopyFrom(const FLightDefaults &other)
|
||||
{
|
||||
auto n = m_Name;
|
||||
*this = other;
|
||||
m_Name = n;
|
||||
}
|
||||
void SetFlags(LightFlags lf)
|
||||
{
|
||||
m_lightFlags = lf;
|
||||
m_attenuate = !!(m_lightFlags & LF_ATTENUATE);
|
||||
}
|
||||
static void SetAttenuationForLevel(bool);
|
||||
|
||||
void OrderIntensities()
|
||||
|
@ -88,7 +114,7 @@ protected:
|
|||
int m_Args[5] = { 0,0,0,0,0 };
|
||||
double m_Param = 0;
|
||||
DVector3 m_Pos = { 0,0,0 };
|
||||
ELightType m_type;
|
||||
int m_type;
|
||||
int8_t m_attenuate = -1;
|
||||
LightFlags m_lightFlags = 0;
|
||||
bool m_swapped = false;
|
||||
|
@ -97,8 +123,12 @@ protected:
|
|||
DAngle m_spotInnerAngle = 10.0;
|
||||
DAngle m_spotOuterAngle = 25.0;
|
||||
DAngle m_pitch = 0.0;
|
||||
|
||||
friend FSerializer &Serialize(FSerializer &arc, const char *key, FLightDefaults &value, FLightDefaults *def);
|
||||
};
|
||||
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, TDeletingArray<FLightDefaults *> &value, TDeletingArray<FLightDefaults *> *def);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Light associations (intermediate parser data)
|
||||
|
@ -247,3 +277,5 @@ public:
|
|||
bool explicitpitch;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -186,6 +186,8 @@ AActor::~AActor ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
|
||||
|
||||
#define A(a,b) ((a), (b), def->b)
|
||||
|
||||
void AActor::Serialize(FSerializer &arc)
|
||||
|
@ -364,7 +366,8 @@ void AActor::Serialize(FSerializer &arc)
|
|||
A("friendlyseeblocks", friendlyseeblocks)
|
||||
A("spawntime", SpawnTime)
|
||||
A("spawnorder", SpawnOrder)
|
||||
A("friction", Friction);
|
||||
A("friction", Friction)
|
||||
A("userlights", UserLights);
|
||||
}
|
||||
|
||||
#undef A
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "r_state.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "a_dynlight.h"
|
||||
#include "serializer.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -63,11 +64,59 @@ int AttenuationIsSet = -1;
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
FLightDefaults::FLightDefaults(FName name, ELightType type)
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, FLightDefaults &value, FLightDefaults *def)
|
||||
{
|
||||
m_Name = name;
|
||||
m_type = type;
|
||||
if (arc.BeginObject(key))
|
||||
{
|
||||
arc("name", value.m_Name)
|
||||
.Array("args", value.m_Args, 5, nullptr)
|
||||
("param", value.m_Param)
|
||||
("pos", value.m_Pos)
|
||||
("type", value.m_type)
|
||||
("attenuate", value.m_attenuate)
|
||||
("flags", value.m_lightFlags)
|
||||
("swapped", value.m_swapped)
|
||||
("spot", value.m_spot)
|
||||
("explicitpitch", value.m_explicitPitch)
|
||||
("spotinner", value.m_spotInnerAngle)
|
||||
("spotouter", value.m_spotOuterAngle)
|
||||
("pitch", value.m_pitch)
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, TDeletingArray<FLightDefaults *> &value, TDeletingArray<FLightDefaults *> *def)
|
||||
{
|
||||
if (arc.isWriting())
|
||||
{
|
||||
if (value.Size() == 0) return arc; // do not save empty arrays
|
||||
}
|
||||
bool res = arc.BeginArray(key);
|
||||
if (arc.isReading())
|
||||
{
|
||||
if (!res)
|
||||
{
|
||||
value.Clear();
|
||||
return arc;
|
||||
}
|
||||
value.Resize(arc.ArraySize());
|
||||
for (auto &entry : value) entry = new FLightDefaults(NAME_None);
|
||||
}
|
||||
for (unsigned i = 0; i < value.Size(); i++)
|
||||
{
|
||||
Serialize(arc, nullptr, *value[i], nullptr);
|
||||
}
|
||||
arc.EndArray();
|
||||
return arc;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FLightDefaults::ApplyProperties(FDynamicLight * light) const
|
||||
{
|
||||
|
|
|
@ -593,6 +593,7 @@ struct DirectNativeDesc
|
|||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12), TP(13)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12), TP(13), TP(14)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13), VP(14); }
|
||||
#undef TP
|
||||
#undef VP
|
||||
|
||||
|
|
|
@ -1163,6 +1163,10 @@ class Actor : Thinker native
|
|||
action native void A_OverlayAlpha(int layer, double alph);
|
||||
action native void A_OverlayRenderStyle(int layer, int style);
|
||||
|
||||
action native bool A_AttachLightDef(Name lightid, Name lightdef);
|
||||
action native bool A_AttachLight(Name lightid, int type, Color lightcolor, int radius1, int radius2, int flags, Vector3 ofs, double param, double spoti, double spoto, double spotp);
|
||||
action mative bool A_RemoveLight(Name lightid);
|
||||
|
||||
int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0)
|
||||
{
|
||||
return ACS_Execute(-int(script), mapnum, arg1, arg2, arg3);
|
||||
|
|
Loading…
Reference in a new issue