// Create a new object that this class represents DObject *PClass::CreateNew () const { BYTE *mem = (BYTE *)M_Malloc (Size); assert (mem != NULL); // Set this object's defaults before constructing it. if (Defaults != NULL) memcpy (mem, Defaults, Size); else memset (mem, 0, Size); ConstructNative (mem); ((DObject *)mem)->SetClass (const_cast<PClass *>(this)); return (DObject *)mem; }
DObject *PClass::CreateNew() { uint8_t *mem = (uint8_t *)M_Malloc (Size); assert (mem != nullptr); // Set this object's defaults before constructing it. if (Defaults != nullptr) memcpy (mem, Defaults, Size); else memset (mem, 0, Size); if (ConstructNative == nullptr) { M_Free(mem); I_Error("Attempt to instantiate abstract class %s.", TypeName.GetChars()); } ConstructNative (mem); ((DObject *)mem)->SetClass (const_cast<PClass *>(this)); InitializeSpecials(mem, Defaults, &PClass::SpecialInits); return (DObject *)mem; }
void PClass::InitializeDefaults() { if (IsDescendantOf(RUNTIME_CLASS(AActor))) { assert(Defaults == nullptr); Defaults = (uint8_t *)M_Malloc(Size); // run the constructor on the defaults to set the vtbl pointer which is needed to run class-aware functions on them. // Temporarily setting bSerialOverride prevents linking into the thinker chains. auto s = DThinker::bSerialOverride; DThinker::bSerialOverride = true; ConstructNative(Defaults); DThinker::bSerialOverride = s; // We must unlink the defaults from the class list because it's just a static block of data to the engine. DObject *optr = (DObject*)Defaults; GC::Root = optr->ObjNext; optr->ObjNext = nullptr; optr->SetClass(this); // Copy the defaults from the parent but leave the DObject part alone because it contains important data. if (ParentClass->Defaults != nullptr) { memcpy(Defaults + sizeof(DObject), ParentClass->Defaults + sizeof(DObject), ParentClass->Size - sizeof(DObject)); if (Size > ParentClass->Size) { memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size); } } else { memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject)); } assert(MetaSize >= ParentClass->MetaSize); if (MetaSize != 0) { Meta = (uint8_t*)M_Malloc(MetaSize); // Copy the defaults from the parent but leave the DObject part alone because it contains important data. if (ParentClass->Meta != nullptr) { memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); if (MetaSize > ParentClass->MetaSize) { memset(Meta + ParentClass->MetaSize, 0, MetaSize - ParentClass->MetaSize); } } else { memset(Meta, 0, MetaSize); } if (MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); else memset(Meta, 0, MetaSize); } } if (VMType != nullptr) // purely internal classes have no symbol table { if (bRuntimeClass) { // Copy parent values from the parent defaults. assert(ParentClass != nullptr); if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults, &PClass::SpecialInits); for (const PField *field : Fields) { if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta)) { field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } } } if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits); for (const PField *field : Fields) { if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta)) { field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits); } } } }