fixed and completed the special field init code. Strings can now be used as class members, and so can structs which contain strings.

- made 'DamageMultiply' an actor property and moved the initialization of ConversationRoot to the property handler for the compiler to get this stuff out of the type classes.
- consolidate default initialization into one function which performs all the required setup. The original implementation did this when adding the fields but that cannot work because at that time no defaults have been created yet.
- fixed: When deriving a class the child class's defaults also must initialize the copied parent fields with special initialization. This part was completely missing.
- removed DECORATE code for parsing native classes because it's no longer needed.
This commit is contained in:
Christoph Oelckers 2016-11-11 14:40:32 +01:00
parent 15ddf70f58
commit 6529931281
9 changed files with 81 additions and 86 deletions

View file

@ -2778,14 +2778,14 @@ void PClass::StaticBootstrap()
PClass::PClass()
{
Size = sizeof(DObject);
ParentClass = NULL;
Pointers = NULL;
FlatPointers = NULL;
HashNext = NULL;
Defaults = NULL;
ParentClass = nullptr;
Pointers = nullptr;
FlatPointers = nullptr;
HashNext = nullptr;
Defaults = nullptr;
bRuntimeClass = false;
bExported = false;
ConstructNative = NULL;
ConstructNative = nullptr;
mDescriptiveName = "Class";
PClass::AllClasses.Push(this);
@ -2969,10 +2969,7 @@ DObject *PClass::CreateNew() const
ConstructNative (mem);
((DObject *)mem)->SetClass (const_cast<PClass *>(this));
if (Defaults != NULL)
{
InitializeSpecials(mem);
}
return (DObject *)mem;
}
@ -3037,16 +3034,52 @@ void PClass::Derive(PClass *newclass)
{
newclass->ParentClass = this;
newclass->ConstructNative = ConstructNative;
newclass->Symbols.SetParentTable(&this->Symbols);
newclass->InitializeDefaults();
}
// Set up default instance of the new class.
newclass->Defaults = (BYTE *)M_Malloc(newclass->Size);
if (Defaults) memcpy(newclass->Defaults, Defaults, Size);
if (newclass->Size > Size)
//==========================================================================
//
// PClassActor :: InitializeNativeDefaults
//
//==========================================================================
void PClass::InitializeDefaults()
{
assert(Defaults == NULL);
Defaults = (BYTE *)M_Malloc(Size);
if (ParentClass->Defaults != NULL)
{
memset(newclass->Defaults + Size, 0, newclass->Size - Size);
memcpy(Defaults, ParentClass->Defaults, ParentClass->Size);
if (Size > ParentClass->Size)
{
memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size);
}
}
else
{
memset(Defaults, 0, Size);
}
newclass->Symbols.SetParentTable(&this->Symbols);
if (bRuntimeClass)
{
// Copy parent values from the parent defaults.
assert(ParentClass != NULL);
ParentClass->InitializeSpecials(Defaults);
// and initialize our own special values.
auto it = Symbols.GetIterator();
PSymbolTable::MapType::Pair *pair;
while (it.NextPair(pair))
{
auto field = dyn_cast<PField>(pair->Value);
if (field != nullptr && !(field->Flags & VARF_Native))
{
field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
}
}
}
}
//==========================================================================
@ -3136,7 +3169,6 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags)
{
Defaults = (BYTE *)M_Realloc(Defaults, Size);
memset(Defaults + oldsize, 0, Size - oldsize);
type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
}
return field;
}

View file

@ -137,6 +137,13 @@ struct PSymbolTable
// Frees all symbols from this table.
void ReleaseSymbols();
typedef TMap<FName, PSymbol *> MapType;
MapType::Iterator GetIterator()
{
return MapType::Iterator(Symbols);
}
// add a name to help debugging.
#ifdef _DEBUG
FString name;
@ -147,7 +154,6 @@ struct PSymbolTable
private:
typedef TMap<FName, PSymbol *> MapType;
PSymbolTable *ParentSymbolTable;
MapType Symbols;
@ -761,6 +767,7 @@ public:
void WriteAllFields(FSerializer &ar, const void *addr) const;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
bool ReadAllFields(FSerializer &ar, void *addr) const;
void InitializeDefaults();
virtual void DeriveData(PClass *newclass) {}
static void StaticInit();

View file

@ -355,35 +355,6 @@ size_t PClassActor::PropagateMark()
return Super::PropagateMark();
}
//==========================================================================
//
// PClassActor :: InitializeNativeDefaults
//
// This is used by DECORATE to assign ActorInfos to internal classes
//
//==========================================================================
void PClassActor::InitializeNativeDefaults()
{
assert(Defaults == NULL);
Defaults = (BYTE *)M_Malloc(Size);
if (ParentClass->Defaults != NULL)
{
memcpy(Defaults, ParentClass->Defaults, ParentClass->Size);
if (Size > ParentClass->Size)
{
memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size);
}
}
else
{
memset (Defaults, 0, Size);
// Non-DECORATE properties that must be set.
((AActor*)Defaults)->DamageMultiply = 1.; // fixme: Make this a DECORATE property.
((AActor*)Defaults)->ConversationRoot = -1;
}
}
//==========================================================================
//
// PClassActor :: SetReplacement

View file

@ -234,7 +234,6 @@ public:
void SetDamageFactor(FName type, double factor);
void SetPainChance(FName type, int chance);
size_t PropagateMark();
void InitializeNativeDefaults();
bool SetReplacement(FName replaceName);
void SetDropItems(DDropItem *drops);
virtual void Finalize(FStateDefinitions &statedef);

View file

@ -875,7 +875,7 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag)
// Starts a new actor definition
//
//==========================================================================
PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native)
PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName)
{
PClassActor *replacee = NULL;
PClassActor *ti = NULL;
@ -908,36 +908,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
parent = RUNTIME_CLASS(AActor);
}
}
if (native)
{
ti = PClass::FindActor(typeName);
if (ti == NULL)
{
extern void DumpTypeTable();
DumpTypeTable();
sc.Message(MSG_ERROR, "Unknown native actor '%s'", typeName.GetChars());
goto create;
}
else if (ti != RUNTIME_CLASS(AActor) && ti->ParentClass->NativeClass() != parent->NativeClass())
{
sc.Message(MSG_ERROR, "Native class '%s' does not inherit from '%s'", typeName.GetChars(), parentName.GetChars());
parent = RUNTIME_CLASS(AActor);
goto create;
}
else if (ti->Defaults != NULL)
{
sc.Message(MSG_ERROR, "Redefinition of internal class '%s'", typeName.GetChars());
goto create;
}
ti->InitializeNativeDefaults();
ti->ParentClass->DeriveData(ti);
}
else
{
create:
ti = DecoDerivedClass(sc, parent, typeName);
}
ti->Replacee = ti->Replacement = NULL;
ti->DoomEdNum = -1;
@ -1025,12 +996,13 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag)
if (sc.CheckString("native"))
{
native = true;
sc.ScriptMessage("Cannot define native classes in DECORATE");
FScriptPosition::ErrorCounter++;
}
try
{
PClassActor *info = CreateNewActor(sc, typeName, parentName, native);
PClassActor *info = CreateNewActor(sc, typeName, parentName);
info->DoomEdNum = DoomEdNum > 0 ? DoomEdNum : -1;
info->SourceLumpName = Wads.GetLumpFullPath(sc.LumpNum);

View file

@ -164,8 +164,6 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id,
//
//==========================================================================
PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native);
void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod);
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant);

View file

@ -652,6 +652,15 @@ DEFINE_PROPERTY(damage, X, Actor)
CreateDamageFunction(bag.Info, defaults, id, true);
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(damagemultiply, F, Actor)
{
PROP_FLOAT_PARM(dmgm, 0);
defaults->DamageMultiply = dmgm;
}
//==========================================================================
//
//==========================================================================

View file

@ -1917,13 +1917,19 @@ void ZCCCompiler::InitDefaults()
if (ti->ParentClass->Defaults == DEFAULTS_VMEXPORT)
{
ti->ParentClass->Defaults = nullptr;
static_cast<PClassActor *>(ti->ParentClass)->InitializeNativeDefaults();
ti->ParentClass->InitializeDefaults();
ti->ParentClass->ParentClass->DeriveData(ti->ParentClass);
}
ti->InitializeNativeDefaults();
ti->InitializeDefaults();
ti->ParentClass->DeriveData(ti);
// We need special treatment for this one field in AActor's defaults which cannot be made visible to DECORATE as a property.
// It's better to do this here under controlled conditions than deeper down in the class type classes.
if (ti == RUNTIME_CLASS(AActor))
{
((AActor*)ti->Defaults)->ConversationRoot = 1;
}
Baggage bag;
#ifdef _DEBUG

View file

@ -23,7 +23,8 @@ class Actor : Thinker native
FloatBobPhase -1; // randomly initialize by default
Gravity 1;
Friction 1;
DamageFactor 1.0;
DamageFactor 1.0; // damage multiplier as target of damage.
DamageMultiply 1.0; // damage multiplier as source of damage.
PushFactor 0.25;
WeaveIndexXY 0;
WeaveIndexZ 16;