// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Delegate.h"
#include "GPUResource.h"
///
/// GPU Resource container utility object.
///
template
class GPUResourceProperty
{
private:
T* _resource;
private:
// Disable copy actions
GPUResourceProperty(const GPUResourceProperty& other) = delete;
public:
///
/// Action fired when resource gets unloaded (reference gets cleared bu async tasks should stop execution).
///
Delegate OnUnload;
public:
///
/// Initializes a new instance of the class.
///
GPUResourceProperty()
: _resource(nullptr)
{
}
///
/// Initializes a new instance of the class.
///
/// The resource.
GPUResourceProperty(T* resource)
: _resource(nullptr)
{
Set(resource);
}
///
/// Finalizes an instance of the class.
///
~GPUResourceProperty()
{
// Check if object has been binded
if (_resource)
{
// Unlink
_resource->Releasing.template Unbind(this);
_resource = nullptr;
}
}
public:
FORCE_INLINE bool operator==(T* other) const
{
return Get() == other;
}
FORCE_INLINE bool operator==(GPUResourceProperty& other) const
{
return Get() == other.Get();
}
GPUResourceProperty& operator=(const GPUResourceProperty& other)
{
if (this != &other)
Set(other.Get());
return *this;
}
FORCE_INLINE GPUResourceProperty& operator=(T& other)
{
Set(&other);
return *this;
}
FORCE_INLINE GPUResourceProperty& operator=(T* other)
{
Set(other);
return *this;
}
///
/// Implicit conversion to GPU Resource
///
/// Resource
FORCE_INLINE operator T*() const
{
return _resource;
}
///
/// Implicit conversion to resource
///
/// True if resource has been binded, otherwise false
FORCE_INLINE operator bool() const
{
return _resource != nullptr;
}
///
/// Implicit conversion to resource
///
/// Resource
FORCE_INLINE T* operator->() const
{
return _resource;
}
///
/// Gets linked resource
///
/// Resource
FORCE_INLINE T* Get() const
{
return _resource;
}
///
/// Checks if resource has been binded
///
/// True if resource has been binded, otherwise false
FORCE_INLINE bool IsBinded() const
{
return _resource != nullptr;
}
///
/// Checks if resource is missing
///
/// True if resource is missing, otherwise false
FORCE_INLINE bool IsMissing() const
{
return _resource == nullptr;
}
public:
///
/// Set resource
///
/// Value to assign
void Set(T* value)
{
if (_resource != value)
{
// Remove reference from the old one
if (_resource)
_resource->Releasing.template Unbind(this);
// Change referenced object
_resource = value;
// Add reference to the new one
if (_resource)
_resource->Releasing.template Bind(this);
}
}
///
/// Unlink resource
///
void Unlink()
{
if (_resource)
{
// Remove reference from the old one
_resource->Releasing.template Unbind(this);
_resource = nullptr;
}
}
private:
void onResourceUnload()
{
if (_resource)
{
_resource = nullptr;
OnUnload(this);
}
}
};
typedef GPUResourceProperty GPUResourceReference;
typedef GPUResourceProperty GPUTextureReference;
typedef GPUResourceProperty BufferReference;