Refactor native core objects to simplify usage for newcomers

This commit is contained in:
Wojtek Figat
2022-01-07 13:16:36 +01:00
parent e144a6f69d
commit 192af7ec14
47 changed files with 204 additions and 249 deletions

View File

@@ -131,7 +131,7 @@ extern FLAXENGINE_API const Char* ToString(const BuildConfiguration configuratio
/// <summary> /// <summary>
/// Game cooking temporary data. /// Game cooking temporary data.
/// </summary> /// </summary>
API_CLASS(Sealed, Namespace="FlaxEditor") class FLAXENGINE_API CookingData : public PersistentScriptingObject API_CLASS(Sealed, Namespace="FlaxEditor") class FLAXENGINE_API CookingData : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE(CookingData); DECLARE_SCRIPTING_TYPE(CookingData);
public: public:

View File

@@ -164,7 +164,7 @@ CookingData::Statistics::Statistics()
} }
CookingData::CookingData(const SpawnParams& params) CookingData::CookingData(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
{ {
} }

View File

@@ -140,7 +140,7 @@ void OnVisualScriptingDebugFlow()
void OnLogMessage(LogType type, const StringView& msg); void OnLogMessage(LogType type, const StringView& msg);
ManagedEditor::ManagedEditor() ManagedEditor::ManagedEditor()
: PersistentScriptingObject(SpawnParams(ObjectID, ManagedEditor::TypeInitializer)) : ScriptingObject(SpawnParams(ObjectID, ManagedEditor::TypeInitializer))
{ {
// Link events // Link events
auto editor = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; auto editor = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly;
@@ -494,5 +494,5 @@ void ManagedEditor::DestroyManaged()
Internal_OnVisualScriptingDebugFlow = nullptr; Internal_OnVisualScriptingDebugFlow = nullptr;
// Base // Base
PersistentScriptingObject::DestroyManaged(); ScriptingObject::DestroyManaged();
} }

View File

@@ -14,7 +14,7 @@ namespace CSG
/// <summary> /// <summary>
/// Managed Editor root object /// Managed Editor root object
/// </summary> /// </summary>
class ManagedEditor : public PersistentScriptingObject class ManagedEditor : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ManagedEditor); DECLARE_SCRIPTING_TYPE_NO_SPAWN(ManagedEditor);
@@ -144,6 +144,6 @@ private:
public: public:
// [PersistentScriptingObject] // [ScriptingObject]
void DestroyManaged() override; void DestroyManaged() override;
}; };

View File

@@ -7,17 +7,17 @@
/// <summary> /// <summary>
/// Represents a single audio device. /// Represents a single audio device.
/// </summary> /// </summary>
API_CLASS(NoSpawn) class AudioDevice : public PersistentScriptingObject API_CLASS(NoSpawn) class AudioDevice : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(AudioDevice); DECLARE_SCRIPTING_TYPE_NO_SPAWN(AudioDevice);
explicit AudioDevice() explicit AudioDevice()
: PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
{ {
} }
AudioDevice(const AudioDevice& other) AudioDevice(const AudioDevice& other)
: PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
{ {
Name = other.Name; Name = other.Name;
InternalName = other.InternalName; InternalName = other.InternalName;

View File

@@ -1,25 +0,0 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#include "Object.h"
#include "ObjectsRemovalService.h"
RemovableObject::~RemovableObject()
{
#if BUILD_DEBUG
// Prevent removing object that is still reverenced by the removal service
ASSERT(!ObjectsRemovalService::IsInPool(this));
#endif
}
void RemovableObject::DeleteObjectNow()
{
ObjectsRemovalService::Dereference(this);
OnDeleteObject();
}
void RemovableObject::DeleteObject(float timeToLive, bool useGameTime)
{
// Add to deferred remove (or just update timeout but don't remove object here)
ObjectsRemovalService::Add(this, timeToLive, useGameTime);
}

View File

@@ -37,30 +37,13 @@ public:
/// <summary> /// <summary>
/// Finalizes an instance of the <see cref="Object"/> class. /// Finalizes an instance of the <see cref="Object"/> class.
/// </summary> /// </summary>
virtual ~Object() virtual ~Object();
{
}
/// <summary> /// <summary>
/// Gets the string representation of this object. /// Gets the string representation of this object.
/// </summary> /// </summary>
/// <returns>The string.</returns> /// <returns>The string.</returns>
virtual String ToString() const = 0; virtual String ToString() const = 0;
};
/// <summary>
/// Interface for removable Engine objects.
/// </summary>
/// <seealso cref="Object" />
class FLAXENGINE_API RemovableObject : public Object
{
public:
/// <summary>
/// Virtual destructor but protected. Removable objects should be deleted using `DeleteObject` which supports deferred delete.
/// Note: it's unsafe to delete object using destructor it it has been marked for deferred delete.
/// </summary>
virtual ~RemovableObject();
/// <summary> /// <summary>
/// Deletes the object without queueing it to the ObjectsRemovalService. /// Deletes the object without queueing it to the ObjectsRemovalService.
@@ -68,7 +51,7 @@ public:
void DeleteObjectNow(); void DeleteObjectNow();
/// <summary> /// <summary>
/// Deletes the object. /// Deletes the object (deferred).
/// </summary> /// </summary>
/// <param name="timeToLive">The time to live (in seconds). Use zero to kill it now.</param> /// <param name="timeToLive">The time to live (in seconds). Use zero to kill it now.</param>
/// <param name="useGameTime">True if unscaled game time for the object life timeout, otherwise false to use absolute time.</param> /// <param name="useGameTime">True if unscaled game time for the object life timeout, otherwise false to use absolute time.</param>
@@ -82,3 +65,6 @@ public:
Delete(this); Delete(this);
} }
}; };
// [Deprecated on 5.01.2022, expires on 5.01.2024]
typedef Object RemovableObject;

View File

@@ -16,8 +16,8 @@ namespace ObjectsRemovalServiceImpl
CriticalSection NewItemsLocker; CriticalSection NewItemsLocker;
DateTime LastUpdate; DateTime LastUpdate;
float LastUpdateGameTime; float LastUpdateGameTime;
Dictionary<RemovableObject*, float> Pool(8192); Dictionary<Object*, float> Pool(8192);
Dictionary<RemovableObject*, float> NewItemsPool(2048); Dictionary<Object*, float> NewItemsPool(2048);
} }
using namespace ObjectsRemovalServiceImpl; using namespace ObjectsRemovalServiceImpl;
@@ -38,7 +38,7 @@ public:
ObjectsRemovalServiceService ObjectsRemovalServiceServiceInstance; ObjectsRemovalServiceService ObjectsRemovalServiceServiceInstance;
bool ObjectsRemovalService::IsInPool(RemovableObject* obj) bool ObjectsRemovalService::IsInPool(Object* obj)
{ {
if (!IsReady) if (!IsReady)
return false; return false;
@@ -67,7 +67,7 @@ bool ObjectsRemovalService::HasNewItemsForFlush()
return result; return result;
} }
void ObjectsRemovalService::Dereference(RemovableObject* obj) void ObjectsRemovalService::Dereference(Object* obj)
{ {
if (!IsReady) if (!IsReady)
return; return;
@@ -81,7 +81,7 @@ void ObjectsRemovalService::Dereference(RemovableObject* obj)
PoolLocker.Unlock(); PoolLocker.Unlock();
} }
void ObjectsRemovalService::Add(RemovableObject* obj, float timeToLive, bool useGameTime) void ObjectsRemovalService::Add(Object* obj, float timeToLive, bool useGameTime)
{ {
ScopeLock lock(NewItemsLocker); ScopeLock lock(NewItemsLocker);
@@ -213,3 +213,24 @@ void ObjectsRemovalServiceService::Dispose()
IsReady = false; IsReady = false;
} }
Object::~Object()
{
#if BUILD_DEBUG
// Prevent removing object that is still reverenced by the removal service
ASSERT(!ObjectsRemovalService::IsInPool(this));
#endif
}
void Object::DeleteObjectNow()
{
ObjectsRemovalService::Dereference(this);
OnDeleteObject();
}
void Object::DeleteObject(float timeToLive, bool useGameTime)
{
// Add to deferred remove (or just update timeout but don't remove object here)
ObjectsRemovalService::Add(this, timeToLive, useGameTime);
}

View File

@@ -16,7 +16,7 @@ public:
/// </summary> /// </summary>
/// <param name="obj">The object.</param> /// <param name="obj">The object.</param>
/// <returns>True if object has been registered in the pool for the removing, otherwise false.</returns> /// <returns>True if object has been registered in the pool for the removing, otherwise false.</returns>
static bool IsInPool(RemovableObject* obj); static bool IsInPool(Object* obj);
/// <summary> /// <summary>
/// Determines whether any object has been registered to be removed from pool (requests are flushed on Flush call). /// Determines whether any object has been registered to be removed from pool (requests are flushed on Flush call).
@@ -28,7 +28,7 @@ public:
/// Removes the specified object from the dead pool (clears the reference to it). /// Removes the specified object from the dead pool (clears the reference to it).
/// </summary> /// </summary>
/// <param name="obj">The object.</param> /// <param name="obj">The object.</param>
static void Dereference(RemovableObject* obj); static void Dereference(Object* obj);
/// <summary> /// <summary>
/// Adds the specified object to the dead pool. /// Adds the specified object to the dead pool.
@@ -36,7 +36,7 @@ public:
/// <param name="obj">The object.</param> /// <param name="obj">The object.</param>
/// <param name="timeToLive">The time to live (in seconds).</param> /// <param name="timeToLive">The time to live (in seconds).</param>
/// <param name="useGameTime">True if unscaled game time for the object life timeout, otherwise false to use absolute time.</param> /// <param name="useGameTime">True if unscaled game time for the object life timeout, otherwise false to use absolute time.</param>
static void Add(RemovableObject* obj, float timeToLive = 1.0f, bool useGameTime = false); static void Add(Object* obj, float timeToLive = 1.0f, bool useGameTime = false);
/// <summary> /// <summary>
/// Flushes the objects pool removing objects marked to remove now (with negative or zero time to live). /// Flushes the objects pool removing objects marked to remove now (with negative or zero time to live).

View File

@@ -7,7 +7,7 @@
#include "Foliage.h" #include "Foliage.h"
FoliageType::FoliageType() FoliageType::FoliageType()
: PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
, Foliage(nullptr) , Foliage(nullptr)
, Index(-1) , Index(-1)
{ {

View File

@@ -41,7 +41,7 @@ API_ENUM() enum class FoliageScalingModes
/// <summary> /// <summary>
/// Foliage mesh instances type descriptor. Defines the shared properties of the spawned mesh instances. /// Foliage mesh instances type descriptor. Defines the shared properties of the spawned mesh instances.
/// </summary> /// </summary>
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FoliageType : public PersistentScriptingObject, public ISerializable API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FoliageType : public ScriptingObject, public ISerializable
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(FoliageType); DECLARE_SCRIPTING_TYPE_NO_SPAWN(FoliageType);
friend Foliage; friend Foliage;

View File

@@ -13,13 +13,13 @@
/// <summary> /// <summary>
/// Interface for GPU device adapter. /// Interface for GPU device adapter.
/// </summary> /// </summary>
API_CLASS(NoSpawn, Attributes="HideInEditor") class FLAXENGINE_API GPUAdapter : public PersistentScriptingObject API_CLASS(NoSpawn, Attributes="HideInEditor") class FLAXENGINE_API GPUAdapter : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUDevice); DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUDevice);
public: public:
GPUAdapter() GPUAdapter()
: PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
{ {
} }

View File

@@ -6,7 +6,7 @@
#include "Textures/GPUTexture.h" #include "Textures/GPUTexture.h"
GPUContext::GPUContext(GPUDevice* device) GPUContext::GPUContext(GPUDevice* device)
: PersistentScriptingObject(ScriptingObjectSpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(ScriptingObjectSpawnParams(Guid::New(), TypeInitializer))
, _device(device) , _device(device)
{ {
} }

View File

@@ -113,7 +113,7 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUDrawIndexedIndirectArgs);
/// <summary> /// <summary>
/// Interface for GPU device context that can record and send graphics commands to the GPU in a sequence. /// Interface for GPU device context that can record and send graphics commands to the GPU in a sequence.
/// </summary> /// </summary>
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUContext : public PersistentScriptingObject API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUContext : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUContext); DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUContext);
private: private:

View File

@@ -173,12 +173,12 @@ GPUPipelineState::Description GPUPipelineState::Description::DefaultFullscreenTr
}; };
GPUResource::GPUResource() GPUResource::GPUResource()
: PersistentScriptingObject(SpawnParams(Guid::New(), GPUResource::TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), GPUResource::TypeInitializer))
{ {
} }
GPUResource::GPUResource(const SpawnParams& params) GPUResource::GPUResource(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
{ {
} }
@@ -241,7 +241,7 @@ void GPUResource::OnDeleteObject()
{ {
ReleaseGPU(); ReleaseGPU();
PersistentScriptingObject::OnDeleteObject(); ScriptingObject::OnDeleteObject();
} }
double GPUResourceView::DummyLastRenderTime = -1; double GPUResourceView::DummyLastRenderTime = -1;
@@ -262,7 +262,7 @@ struct GPUDevice::PrivateData
GPUDevice* GPUDevice::Instance = nullptr; GPUDevice* GPUDevice::Instance = nullptr;
GPUDevice::GPUDevice(RendererType type, ShaderProfile profile) GPUDevice::GPUDevice(RendererType type, ShaderProfile profile)
: PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
, _state(DeviceState::Missing) , _state(DeviceState::Missing)
, _isRendering(false) , _isRendering(false)
, _wasVSyncUsed(false) , _wasVSyncUsed(false)

View File

@@ -29,7 +29,7 @@ class MaterialBase;
/// <summary> /// <summary>
/// Graphics device object for rendering on GPU. /// Graphics device object for rendering on GPU.
/// </summary> /// </summary>
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUDevice : public PersistentScriptingObject API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUDevice : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUDevice); DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUDevice);
public: public:

View File

@@ -15,7 +15,7 @@
/// <summary> /// <summary>
/// The base class for all GPU resources. /// The base class for all GPU resources.
/// </summary> /// </summary>
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API GPUResource : public PersistentScriptingObject API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API GPUResource : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUResource); DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUResource);
public: public:
@@ -108,7 +108,7 @@ protected:
public: public:
// [PersistentScriptingObject] // [ScriptingObject]
String ToString() const override; String ToString() const override;
void OnDeleteObject() override; void OnDeleteObject() override;
}; };
@@ -186,14 +186,14 @@ public:
/// <summary> /// <summary>
/// Interface for GPU resources views. Shared base class for texture and buffer views. /// Interface for GPU resources views. Shared base class for texture and buffer views.
/// </summary> /// </summary>
API_CLASS(Abstract, NoSpawn, Attributes="HideInEditor") class FLAXENGINE_API GPUResourceView : public PersistentScriptingObject API_CLASS(Abstract, NoSpawn, Attributes="HideInEditor") class FLAXENGINE_API GPUResourceView : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUResourceView); DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUResourceView);
protected: protected:
static double DummyLastRenderTime; static double DummyLastRenderTime;
explicit GPUResourceView(const SpawnParams& params) explicit GPUResourceView(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
, LastRenderTime(&DummyLastRenderTime) , LastRenderTime(&DummyLastRenderTime)
{ {
} }

View File

@@ -167,9 +167,9 @@ struct SerializedMaterialParam
/// <summary> /// <summary>
/// Material variable object. Allows to modify material parameter value at runtime. /// Material variable object. Allows to modify material parameter value at runtime.
/// </summary> /// </summary>
API_CLASS(NoSpawn) class FLAXENGINE_API MaterialParameter : public PersistentScriptingObject API_CLASS(NoSpawn) class FLAXENGINE_API MaterialParameter : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(MaterialParameter, PersistentScriptingObject); DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(MaterialParameter, ScriptingObject);
friend MaterialParams; friend MaterialParams;
friend MaterialInstance; friend MaterialInstance;
private: private:

View File

@@ -10,9 +10,9 @@
/// <summary> /// <summary>
/// The material slot descriptor that specifies how to render geometry using it. /// The material slot descriptor that specifies how to render geometry using it.
/// </summary> /// </summary>
API_CLASS(NoSpawn) class FLAXENGINE_API MaterialSlot : public PersistentScriptingObject API_CLASS(NoSpawn) class FLAXENGINE_API MaterialSlot : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(MaterialSlot, PersistentScriptingObject); DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(MaterialSlot, ScriptingObject);
/// <summary> /// <summary>
/// The material to use for rendering. /// The material to use for rendering.

View File

@@ -14,7 +14,7 @@ class ModelBase;
/// <summary> /// <summary>
/// Base class for model resources meshes. /// Base class for model resources meshes.
/// </summary> /// </summary>
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API MeshBase : public PersistentScriptingObject API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API MeshBase : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_MINIMAL(MeshBase); DECLARE_SCRIPTING_TYPE_MINIMAL(MeshBase);
protected: protected:
@@ -30,7 +30,7 @@ protected:
bool _use16BitIndexBuffer; bool _use16BitIndexBuffer;
explicit MeshBase(const SpawnParams& params) explicit MeshBase(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
{ {
} }

View File

@@ -10,9 +10,9 @@ class MemoryReadStream;
/// <summary> /// <summary>
/// Represents single Level Of Detail for the model. Contains a collection of the meshes. /// Represents single Level Of Detail for the model. Contains a collection of the meshes.
/// </summary> /// </summary>
API_CLASS(NoSpawn) class FLAXENGINE_API ModelLOD : public PersistentScriptingObject API_CLASS(NoSpawn) class FLAXENGINE_API ModelLOD : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(ModelLOD, PersistentScriptingObject); DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(ModelLOD, ScriptingObject);
friend Model; friend Model;
friend Mesh; friend Mesh;
private: private:

View File

@@ -10,9 +10,9 @@ class MemoryReadStream;
/// <summary> /// <summary>
/// Represents single Level Of Detail for the skinned model. Contains a collection of the meshes. /// Represents single Level Of Detail for the skinned model. Contains a collection of the meshes.
/// </summary> /// </summary>
API_CLASS(NoSpawn) class FLAXENGINE_API SkinnedModelLOD : public PersistentScriptingObject API_CLASS(NoSpawn) class FLAXENGINE_API SkinnedModelLOD : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(SkinnedModelLOD, PersistentScriptingObject); DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(SkinnedModelLOD, ScriptingObject);
friend SkinnedModel; friend SkinnedModel;
private: private:

View File

@@ -8,7 +8,7 @@
#include "Engine/Engine/Engine.h" #include "Engine/Engine/Engine.h"
RenderBuffers::RenderBuffers(const SpawnParams& params) RenderBuffers::RenderBuffers(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
{ {
#define CREATE_TEXTURE(name) name = GPUDevice::Instance->CreateTexture(TEXT(#name)); _resources.Add(name) #define CREATE_TEXTURE(name) name = GPUDevice::Instance->CreateTexture(TEXT(#name)); _resources.Add(name)
CREATE_TEXTURE(DepthBuffer); CREATE_TEXTURE(DepthBuffer);

View File

@@ -19,7 +19,7 @@
/// <summary> /// <summary>
/// The scene rendering buffers container. /// The scene rendering buffers container.
/// </summary> /// </summary>
API_CLASS() class FLAXENGINE_API RenderBuffers : public PersistentScriptingObject API_CLASS() class FLAXENGINE_API RenderBuffers : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE(RenderBuffers); DECLARE_SCRIPTING_TYPE(RenderBuffers);
protected: protected:

View File

@@ -82,7 +82,7 @@ void RenderTask::DrawAll()
} }
RenderTask::RenderTask(const SpawnParams& params) RenderTask::RenderTask(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
{ {
// Register // Register
TasksLocker.Lock(); TasksLocker.Lock();

View File

@@ -24,7 +24,7 @@ class Actor;
/// <summary> /// <summary>
/// Allows to perform custom rendering using graphics pipeline. /// Allows to perform custom rendering using graphics pipeline.
/// </summary> /// </summary>
API_CLASS() class FLAXENGINE_API RenderTask : public PersistentScriptingObject API_CLASS() class FLAXENGINE_API RenderTask : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE(RenderTask); DECLARE_SCRIPTING_TYPE(RenderTask);

View File

@@ -11,7 +11,7 @@
/// <summary> /// <summary>
/// Base class for all input device objects. /// Base class for all input device objects.
/// </summary> /// </summary>
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API InputDevice : public PersistentScriptingObject API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API InputDevice : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(InputDevice); DECLARE_SCRIPTING_TYPE_NO_SPAWN(InputDevice);
public: public:
@@ -86,7 +86,7 @@ protected:
EventQueue _queue; EventQueue _queue;
explicit InputDevice(const SpawnParams& params, const StringView& name) explicit InputDevice(const SpawnParams& params, const StringView& name)
: PersistentScriptingObject(params) : ScriptingObject(params)
, _name(name) , _name(name)
{ {
} }

View File

@@ -971,7 +971,7 @@ private:
public: public:
// [PersistentScriptingObject] // [ScriptingObject]
String ToString() const override; String ToString() const override;
void OnDeleteObject() override; void OnDeleteObject() override;

View File

@@ -55,7 +55,7 @@ typedef Dictionary<Guid, Actor*, HeapAllocation> ActorsLookup;
/// <summary> /// <summary>
/// Base class for objects that are parts of the scene (actors and scripts). /// Base class for objects that are parts of the scene (actors and scripts).
/// </summary> /// </summary>
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API SceneObject : public PersistentScriptingObject, public ISerializable API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API SceneObject : public ScriptingObject, public ISerializable
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(SceneObject); DECLARE_SCRIPTING_TYPE_NO_SPAWN(SceneObject);
friend PrefabInstanceData; friend PrefabInstanceData;
@@ -64,7 +64,7 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(SceneObject);
friend ScriptsFactory; friend ScriptsFactory;
friend SceneTicking; friend SceneTicking;
public: public:
typedef PersistentScriptingObject Base; typedef ScriptingObject Base;
// Scene Object lifetime flow: // Scene Object lifetime flow:
// - Create // - Create

View File

@@ -51,7 +51,7 @@ void SendPacketToPeer(ENetPeer* peer, const NetworkChannelType channelType, cons
} }
ENetDriver::ENetDriver(const SpawnParams& params) ENetDriver::ENetDriver(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
{ {
} }

View File

@@ -13,7 +13,7 @@
/// <summary> /// <summary>
/// Low-level network transport interface implementation based on ENet library. /// Low-level network transport interface implementation based on ENet library.
/// </summary> /// </summary>
API_CLASS(Namespace="FlaxEngine.Networking", Sealed) class FLAXENGINE_API ENetDriver : public PersistentScriptingObject, public INetworkDriver API_CLASS(Namespace="FlaxEngine.Networking", Sealed) class FLAXENGINE_API ENetDriver : public ScriptingObject, public INetworkDriver
{ {
DECLARE_SCRIPTING_TYPE(ENetDriver); DECLARE_SCRIPTING_TYPE(ENetDriver);
public: public:

View File

@@ -11,7 +11,7 @@
/// <summary> /// <summary>
/// Low-level network peer class. Provides server-client communication functions, message processing and sending. /// Low-level network peer class. Provides server-client communication functions, message processing and sending.
/// </summary> /// </summary>
API_CLASS(sealed, NoSpawn, Namespace = "FlaxEngine.Networking") class FLAXENGINE_API NetworkPeer final : public PersistentScriptingObject API_CLASS(sealed, NoSpawn, Namespace = "FlaxEngine.Networking") class FLAXENGINE_API NetworkPeer final : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(NetworkPeer); DECLARE_SCRIPTING_TYPE_NO_SPAWN(NetworkPeer);
friend class NetworkManager; friend class NetworkManager;
@@ -30,7 +30,7 @@ public:
/// Initializes a new instance of the <see cref="NetworkPeer"/> class. /// Initializes a new instance of the <see cref="NetworkPeer"/> class.
/// </summary> /// </summary>
NetworkPeer() NetworkPeer()
: PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
{ {
} }

View File

@@ -12,7 +12,7 @@
/// <summary> /// <summary>
/// Particle system parameter. /// Particle system parameter.
/// </summary> /// </summary>
API_CLASS(NoSpawn) class ParticleEffectParameter : public PersistentScriptingObject API_CLASS(NoSpawn) class ParticleEffectParameter : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ParticleEffectParameter); DECLARE_SCRIPTING_TYPE_NO_SPAWN(ParticleEffectParameter);
friend ParticleEffect; friend ParticleEffect;
@@ -30,7 +30,7 @@ public:
/// Initializes a new instance of the <see cref="ParticleEffectParameter"/> class. /// Initializes a new instance of the <see cref="ParticleEffectParameter"/> class.
/// </summary> /// </summary>
ParticleEffectParameter() ParticleEffectParameter()
: PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
{ {
} }

View File

@@ -112,7 +112,7 @@ UserBase::UserBase(const String& name)
} }
UserBase::UserBase(const SpawnParams& params, const String& name) UserBase::UserBase(const SpawnParams& params, const String& name)
: PersistentScriptingObject(params) : ScriptingObject(params)
, _name(name) , _name(name)
{ {
} }

View File

@@ -10,7 +10,7 @@ API_INJECT_CPP_CODE("#include \"Engine/Platform/User.h\"");
/// <summary> /// <summary>
/// Native platform user object. /// Native platform user object.
/// </summary> /// </summary>
API_CLASS(NoSpawn, NoConstructor, Sealed, Name="User") class FLAXENGINE_API UserBase : public PersistentScriptingObject API_CLASS(NoSpawn, NoConstructor, Sealed, Name="User") class FLAXENGINE_API UserBase : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(UserBase); DECLARE_SCRIPTING_TYPE_NO_SPAWN(UserBase);
protected: protected:

View File

@@ -87,7 +87,7 @@
#endif #endif
WindowBase::WindowBase(const CreateWindowSettings& settings) WindowBase::WindowBase(const CreateWindowSettings& settings)
: PersistentScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))
, _visible(false) , _visible(false)
, _minimized(false) , _minimized(false)
, _maximized(false) , _maximized(false)
@@ -190,7 +190,7 @@ void WindowBase::OnDeleteObject()
SAFE_DELETE(_swapChain); SAFE_DELETE(_swapChain);
// Base // Base
PersistentScriptingObject::OnDeleteObject(); ScriptingObject::OnDeleteObject();
} }
bool WindowBase::GetRenderingEnabled() const bool WindowBase::GetRenderingEnabled() const

View File

@@ -269,7 +269,7 @@ API_INJECT_CPP_CODE("#include \"Engine/Platform/Window.h\"");
/// Native platform window object. /// Native platform window object.
/// </summary> /// </summary>
API_CLASS(NoSpawn, NoConstructor, Sealed, Name="Window") API_CLASS(NoSpawn, NoConstructor, Sealed, Name="Window")
class FLAXENGINE_API WindowBase : public PersistentScriptingObject class FLAXENGINE_API WindowBase : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(WindowBase); DECLARE_SCRIPTING_TYPE_NO_SPAWN(WindowBase);
friend GPUSwapChain; friend GPUSwapChain;
@@ -941,7 +941,7 @@ private:
public: public:
// [PersistentScriptingObject] // [ScriptingObject]
String ToString() const override; String ToString() const override;
void OnDeleteObject() override; void OnDeleteObject() override;
}; };

View File

@@ -369,7 +369,7 @@ bool DrawCallsList::IsEmpty() const
} }
RenderList::RenderList(const SpawnParams& params) RenderList::RenderList(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
, DirectionalLights(4) , DirectionalLights(4)
, PointLights(32) , PointLights(32)
, SpotLights(32) , SpotLights(32)

View File

@@ -322,7 +322,7 @@ struct DrawCallsList
/// <summary> /// <summary>
/// Rendering cache container object for the draw calls collecting, sorting and executing. /// Rendering cache container object for the draw calls collecting, sorting and executing.
/// </summary> /// </summary>
API_CLASS(Sealed) class FLAXENGINE_API RenderList : public PersistentScriptingObject API_CLASS(Sealed) class FLAXENGINE_API RenderList : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE(RenderList); DECLARE_SCRIPTING_TYPE(RenderList);

View File

@@ -197,7 +197,7 @@ struct MConverter<T*, typename TEnableIf<TIsBaseOf<class ScriptingObject, T>::Va
// Converter for Scripting Objects (collection of values). // Converter for Scripting Objects (collection of values).
template<typename T> template<typename T>
struct MConverter<T, typename TEnableIf<TIsBaseOf<class PersistentScriptingObject, T>::Value>::Type> struct MConverter<T, typename TEnableIf<TIsBaseOf<class ScriptingObject, T>::Value>::Type>
{ {
MonoObject* Box(const T& data, MonoClass* klass) MonoObject* Box(const T& data, MonoClass* klass)
{ {

View File

@@ -134,7 +134,7 @@ private:
public: public:
// [PersistentScriptingObject] // [ScriptingObject]
String ToString() const override; String ToString() const override;
void OnDeleteObject() override; void OnDeleteObject() override;

View File

@@ -40,20 +40,32 @@ ScriptingObject::ScriptingObject(const SpawnParams& params)
ScriptingObject::~ScriptingObject() ScriptingObject::~ScriptingObject()
{ {
// Ensure that GC handle is empty
ASSERT(_gcHandle == 0);
// Ensure that object has been already unregistered
if (IsRegistered())
UnregisterObject();
Deleted(this); Deleted(this);
// Get rid of managed object
ScriptingObject::DestroyManaged();
ASSERT(_gcHandle == 0);
// Handle custom scripting objects removing // Handle custom scripting objects removing
if (Flags & ObjectFlags::IsCustomScriptingType) if (Flags & ObjectFlags::IsCustomScriptingType)
{ {
_type.Module->OnObjectDeleted(this); _type.Module->OnObjectDeleted(this);
} }
// Ensure that object has been already unregistered
if (IsRegistered())
UnregisterObject();
}
ScriptingObject* ScriptingObject::NewObject(const ScriptingTypeHandle& typeHandle)
{
if (!typeHandle)
return nullptr;
auto& type = typeHandle.GetType();
if (type.Type != ScriptingTypes::Script)
return nullptr;
const ScriptingObjectSpawnParams params(Guid::New(), typeHandle);
return type.Script.Spawn(params);
} }
MObject* ScriptingObject::GetManagedInstance() const MObject* ScriptingObject::GetManagedInstance() const
@@ -82,17 +94,6 @@ MClass* ScriptingObject::GetClass() const
return _type ? _type.GetType().ManagedClass : nullptr; return _type ? _type.GetType().ManagedClass : nullptr;
} }
ScriptingObject* ScriptingObject::NewObject(const ScriptingTypeHandle& typeHandle)
{
if (!typeHandle)
return nullptr;
auto& type = typeHandle.GetType();
if (type.Type != ScriptingTypes::Script)
return nullptr;
const ScriptingObjectSpawnParams params(Guid::New(), typeHandle);
return type.Script.Spawn(params);
}
ScriptingObject* ScriptingObject::FromInterface(void* interfaceObj, const ScriptingTypeHandle& interfaceType) ScriptingObject* ScriptingObject::FromInterface(void* interfaceObj, const ScriptingTypeHandle& interfaceType)
{ {
if (!interfaceObj || !interfaceType) if (!interfaceObj || !interfaceType)
@@ -220,18 +221,49 @@ void ScriptingObject::OnManagedInstanceDeleted()
// Unregister object // Unregister object
if (IsRegistered()) if (IsRegistered())
UnregisterObject(); UnregisterObject();
// Self destruct
DeleteObject();
} }
void ScriptingObject::OnScriptingDispose() void ScriptingObject::OnScriptingDispose()
{ {
// Delete C# object // Delete C# object
if (IsRegistered())
UnregisterObject();
DestroyManaged(); DestroyManaged();
}
// Delete C++ object bool ScriptingObject::CreateManaged()
DeleteObject(); {
#if USE_MONO
MonoObject* managedInstance = CreateManagedInternal();
if (!managedInstance)
return true;
// Prevent form object GC destruction
auto handle = mono_gchandle_new(managedInstance, false);
auto oldHandle = Platform::InterlockedCompareExchange((int32*)&_gcHandle, *(int32*)&handle, 0);
if (*(uint32*)&oldHandle != 0)
{
// Other thread already created the object before
if (const auto monoClass = GetClass())
{
// Reset managed to unmanaged pointer
const MField* monoUnmanagedPtrField = monoClass->GetField(ScriptingObject_unmanagedPtr);
if (monoUnmanagedPtrField)
{
void* param = nullptr;
monoUnmanagedPtrField->SetValue(managedInstance, &param);
}
}
mono_gchandle_free(handle);
return true;
}
#endif
// Ensure to be registered
if (!IsRegistered())
RegisterObject();
return false;
} }
#if USE_MONO #if USE_MONO
@@ -379,7 +411,7 @@ void ScriptingObject::OnDeleteObject()
UnregisterObject(); UnregisterObject();
// Base // Base
RemovableObject::OnDeleteObject(); Object::OnDeleteObject();
} }
String ScriptingObject::ToString() const String ScriptingObject::ToString() const
@@ -392,6 +424,24 @@ ManagedScriptingObject::ManagedScriptingObject(const SpawnParams& params)
{ {
} }
void ManagedScriptingObject::OnManagedInstanceDeleted()
{
// Base
ScriptingObject::OnManagedInstanceDeleted();
// Self destruct
DeleteObject();
}
void ManagedScriptingObject::OnScriptingDispose()
{
// Base
ScriptingObject::OnScriptingDispose();
// Self destruct
DeleteObject();
}
bool ManagedScriptingObject::CreateManaged() bool ManagedScriptingObject::CreateManaged()
{ {
#if USE_MONO #if USE_MONO
@@ -432,70 +482,6 @@ PersistentScriptingObject::PersistentScriptingObject(const SpawnParams& params)
{ {
} }
PersistentScriptingObject::~PersistentScriptingObject()
{
PersistentScriptingObject::DestroyManaged();
}
void PersistentScriptingObject::OnManagedInstanceDeleted()
{
// Cleanup
if (_gcHandle)
{
#if USE_MONO
mono_gchandle_free(_gcHandle);
#endif
_gcHandle = 0;
}
// But do not delete itself
}
void PersistentScriptingObject::OnScriptingDispose()
{
// Delete C# object
if (IsRegistered())
UnregisterObject();
DestroyManaged();
// Don't delete C++ object
}
bool PersistentScriptingObject::CreateManaged()
{
#if USE_MONO
MonoObject* managedInstance = CreateManagedInternal();
if (!managedInstance)
return true;
// Prevent form object GC destruction
auto handle = mono_gchandle_new(managedInstance, false);
auto oldHandle = Platform::InterlockedCompareExchange((int32*)&_gcHandle, *(int32*)&handle, 0);
if (*(uint32*)&oldHandle != 0)
{
// Other thread already created the object before
if (const auto monoClass = GetClass())
{
// Reset managed to unmanaged pointer
const MField* monoUnmanagedPtrField = monoClass->GetField(ScriptingObject_unmanagedPtr);
if (monoUnmanagedPtrField)
{
void* param = nullptr;
monoUnmanagedPtrField->SetValue(managedInstance, &param);
}
}
mono_gchandle_free(handle);
return true;
}
#endif
// Ensure to be registered
if (!IsRegistered())
RegisterObject();
return false;
}
class ScriptingObjectInternal class ScriptingObjectInternal
{ {
public: public:
@@ -767,7 +753,7 @@ public:
static ScriptingObject* Spawn(const ScriptingObjectSpawnParams& params) static ScriptingObject* Spawn(const ScriptingObjectSpawnParams& params)
{ {
return New<PersistentScriptingObject>(params); return New<ScriptingObject>(params);
} }
}; };

View File

@@ -8,9 +8,9 @@
#include "ManagedCLR/MTypes.h" #include "ManagedCLR/MTypes.h"
/// <summary> /// <summary>
/// Represents object from unmanaged memory that can use accessed via C# scripting. /// Represents object from unmanaged memory that can use accessed via scripting.
/// </summary> /// </summary>
API_CLASS(InBuild) class FLAXENGINE_API ScriptingObject : public RemovableObject API_CLASS(InBuild) class FLAXENGINE_API ScriptingObject : public Object
{ {
friend class Scripting; friend class Scripting;
friend class BinaryModule; friend class BinaryModule;
@@ -40,14 +40,23 @@ public:
public: public:
/// <summary> // Spawns a new objects of the given type.
/// Spawns a new objects of the given type. static ScriptingObject* NewObject(const ScriptingTypeHandle& typeHandle);
/// </summary>
template<typename T> template<typename T>
static T* Spawn() static T* NewObject()
{ {
const SpawnParams params(Guid::New(), T::TypeInitializer); return (T*)NewObject(T::TypeInitializer);
return T::New(params); }
template<typename T>
static T* NewObject(const ScriptingTypeHandle& typeHandle)
{
auto obj = NewObject(typeHandle);
if (obj && !obj->Is<T>())
{
Delete(obj);
obj = nullptr;
}
return (T*)obj;
} }
public: public:
@@ -108,13 +117,6 @@ public:
public: public:
static ScriptingObject* NewObject(const ScriptingTypeHandle& typeHandle);
template<typename T>
static T* NewObject()
{
return (T*)NewObject(T::TypeInitializer);
}
// Tries to cast native interface object to scripting object instance. Returns null if fails. // Tries to cast native interface object to scripting object instance. Returns null if fails.
static ScriptingObject* FromInterface(void* interfaceObj, const ScriptingTypeHandle& interfaceType); static ScriptingObject* FromInterface(void* interfaceObj, const ScriptingTypeHandle& interfaceType);
static void* ToInterface(ScriptingObject* obj, const ScriptingTypeHandle& interfaceType); static void* ToInterface(ScriptingObject* obj, const ScriptingTypeHandle& interfaceType);
@@ -189,7 +191,7 @@ public:
virtual void OnManagedInstanceDeleted(); virtual void OnManagedInstanceDeleted();
virtual void OnScriptingDispose(); virtual void OnScriptingDispose();
virtual bool CreateManaged() = 0; virtual bool CreateManaged();
virtual void DestroyManaged(); virtual void DestroyManaged();
public: public:
@@ -223,7 +225,7 @@ protected:
public: public:
// [RemovableObject] // [Object]
void OnDeleteObject() override; void OnDeleteObject() override;
String ToString() const override; String ToString() const override;
}; };
@@ -246,32 +248,17 @@ public:
public: public:
// [ScriptingObject] // [ScriptingObject]
bool CreateManaged() override;
};
/// <summary>
/// Managed object that uses pinned GC handle to prevent collecting and moving.
/// Used by the objects that lifetime is controlled by the C++ side.
/// </summary>
API_CLASS(InBuild) class FLAXENGINE_API PersistentScriptingObject : public ScriptingObject
{
public:
/// <summary>
/// Initializes a new instance of the <see cref="PersistentScriptingObject"/> class.
/// </summary>
/// <param name="params">The object initialization parameters.</param>
explicit PersistentScriptingObject(const SpawnParams& params);
/// <summary>
/// Finalizes an instance of the <see cref="PersistentScriptingObject"/> class.
/// </summary>
~PersistentScriptingObject();
public:
// [ManagedScriptingObject]
void OnManagedInstanceDeleted() override; void OnManagedInstanceDeleted() override;
void OnScriptingDispose() override; void OnScriptingDispose() override;
bool CreateManaged() override; bool CreateManaged() override;
}; };
/// <summary>
/// Use ScriptingObject instead.
/// [Deprecated on 5.01.2022, expires on 5.01.2024]
/// </summary>
API_CLASS(InBuild) class FLAXENGINE_API PersistentScriptingObject : public ScriptingObject
{
public:
PersistentScriptingObject(const SpawnParams& params);
};

View File

@@ -18,7 +18,7 @@ DECLARE_ENUM_EX_6(TaskState, int64, 0, Created, Failed, Canceled, Queued, Runnin
/// <summary> /// <summary>
/// Represents an asynchronous operation. /// Represents an asynchronous operation.
/// </summary> /// </summary>
class FLAXENGINE_API Task : public RemovableObject, public NonCopyable class FLAXENGINE_API Task : public Object, public NonCopyable
{ {
// //
// Tasks execution and states flow: // Tasks execution and states flow:

View File

@@ -14,7 +14,7 @@ namespace
} }
TaskGraphSystem::TaskGraphSystem(const SpawnParams& params) TaskGraphSystem::TaskGraphSystem(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
{ {
} }
@@ -36,7 +36,7 @@ void TaskGraphSystem::PostExecute(TaskGraph* graph)
} }
TaskGraph::TaskGraph(const SpawnParams& params) TaskGraph::TaskGraph(const SpawnParams& params)
: PersistentScriptingObject(params) : ScriptingObject(params)
{ {
} }

View File

@@ -10,7 +10,7 @@ class TaskGraph;
/// <summary> /// <summary>
/// System that can generate work into Task Graph for asynchronous execution. /// System that can generate work into Task Graph for asynchronous execution.
/// </summary> /// </summary>
API_CLASS(Abstract) class FLAXENGINE_API TaskGraphSystem : public PersistentScriptingObject API_CLASS(Abstract) class FLAXENGINE_API TaskGraphSystem : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE(TaskGraphSystem); DECLARE_SCRIPTING_TYPE(TaskGraphSystem);
friend TaskGraph; friend TaskGraph;
@@ -52,7 +52,7 @@ public:
/// <summary> /// <summary>
/// Graph-based asynchronous tasks scheduler for high-performance computing and processing. /// Graph-based asynchronous tasks scheduler for high-performance computing and processing.
/// </summary> /// </summary>
API_CLASS() class FLAXENGINE_API TaskGraph : public PersistentScriptingObject API_CLASS() class FLAXENGINE_API TaskGraph : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE(TaskGraph); DECLARE_SCRIPTING_TYPE(TaskGraph);
private: private:

View File

@@ -39,9 +39,9 @@ API_ENUM() enum class ChannelMask
/// <summary> /// <summary>
/// Represents a parameter in the Graph. /// Represents a parameter in the Graph.
/// </summary> /// </summary>
API_CLASS() class FLAXENGINE_API GraphParameter : public PersistentScriptingObject API_CLASS() class FLAXENGINE_API GraphParameter : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(GraphParameter, PersistentScriptingObject); DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(GraphParameter, ScriptingObject);
public: public:
/// <summary> /// <summary>