Files
EVEngine/src/engine/common/Object.h
T
sunxfancy 87d6062711 chore: update CMake configuration and enhance filesystem tests
- Modified CMakeLists.txt to include the `--recurse-submodules` option for Git clone commands, ensuring all submodules are fetched.
- Enhanced filesystem tests to cover additional scenarios, including memory data mounting and real directory resolution.
- Updated image tests to validate PNG encoding and decoding, ensuring proper handling of unsupported formats.
- Improved model3D tests to check for material counts and face normals, enhancing robustness of 3D model handling.
- Added error handling in sound tests for invalid data scenarios, ensuring stability in audio processing.

These changes improve the overall test coverage and configuration management of the project.
2026-08-08 16:19:14 +08:00

100 lines
2.4 KiB
C++

#pragma once
#include <type_traits>
namespace eve
{
class Object;
template <typename T>
concept DerivedFromObject = std::is_base_of_v<eve::Object, T>;
/**
* @brief Object is the base class for all game objects.
* It provides reference counting and dirty flag for update.
*/
class Object {
public:
Object() { update = this; }
/**
* @brief Update the current object with a replacement.
* You don't need to care about the reference to the old object
* since it will be automatically updated in the ref smart pointer.
*/
void setUpdate(Object *update) { this->update = update; }
protected:
virtual ~Object() {}
template <typename T>
friend class ref;
bool isDirty() const { return this != update; }
Object *getUpdate() const { return update; }
void ref() { ++ref_count; }
void unref() { if (--ref_count == 0) delete this; }
Object* update;
unsigned ref_count = 0;
};
/**
* @brief ref is a smart pointer that automatically calls ref() and unref() on the object.
* Type T must be a subclass of Object.
*/
template <typename T>
class ref {
public:
static_assert( DerivedFromObject<T> );
// Default constructor creates a null pointer.
ref() : ptr(nullptr) {}
// Constructor from a raw pointer.
ref(T* ptr) : ptr(ptr) { ptr->ref(); }
// Copy constructor.
ref(const ref& other) : ptr(other.ptr) { ptr->ref(); }
// Destructor. will call unref() on the object.
~ref() { ptr->unref(); }
// Assignment operator. The old object will be unref() and the new one will be ref().
ref& operator=(const ref& other) {
if (ptr != other.ptr) {
ptr->unref();
ptr = other.ptr;
ptr->ref();
}
return *this;
}
// Assignment operator from a raw pointer.
ref& operator=(T* other) {
if (ptr != other) {
ptr->unref();
ptr = other;
ptr->ref();
}
return *this;
}
operator T*() { checkDirty(); return ptr; }
T* operator->() { checkDirty(); return ptr; }
T& operator*() { checkDirty(); return *ptr; }
T* get() { checkDirty(); return ptr; }
protected:
// getUpdate() returns the base Object*; the update contract guarantees
// the replacement is actually a T*, so a downcast here is safe.
void checkDirty() { if (ptr->isDirty()) ptr = static_cast<T*>(ptr->getUpdate()); }
T* ptr;
};
} // namespace eve