2022-08-01 11:18:03 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cocos2d.h>
|
|
|
|
|
|
|
|
namespace geode {
|
|
|
|
/**
|
2022-10-30 14:59:20 -04:00
|
|
|
* A smart pointer to a managed CCObject-deriving class. Retains shared
|
|
|
|
* ownership over the managed instance. Releases the object when the Ref
|
2022-08-01 11:18:03 -04:00
|
|
|
* is destroyed, or assigned another object or nullptr.
|
2022-10-30 14:59:20 -04:00
|
|
|
*
|
|
|
|
* Use-cases include, for example, non-CCNode class members, or nodes that
|
2022-08-01 11:18:03 -04:00
|
|
|
* are not always in the scene tree.
|
2022-10-30 14:59:20 -04:00
|
|
|
*
|
2022-08-01 11:18:03 -04:00
|
|
|
* @example class MyNode : public CCNode {
|
|
|
|
* protected:
|
2022-10-30 14:59:20 -04:00
|
|
|
* // no need to manually call retain or
|
|
|
|
* // release on this array; Ref manages it
|
2022-08-01 11:18:03 -04:00
|
|
|
* // for you :3
|
|
|
|
* Ref<CCArray> m_list = CCArray::create();
|
|
|
|
* };
|
|
|
|
*/
|
2022-10-30 14:59:20 -04:00
|
|
|
template <class T>
|
2022-08-01 11:18:03 -04:00
|
|
|
class Ref final {
|
|
|
|
static_assert(
|
|
|
|
std::is_base_of_v<cocos2d::CCObject, T>,
|
|
|
|
"Ref can only be used with a CCObject-inheriting class!"
|
|
|
|
);
|
|
|
|
|
|
|
|
T* m_obj = nullptr;
|
|
|
|
|
|
|
|
public:
|
|
|
|
/**
|
2022-10-30 14:59:20 -04:00
|
|
|
* Construct a Ref of an object. The object will be retained and
|
2022-08-01 11:18:03 -04:00
|
|
|
* managed until Ref goes out of scope
|
|
|
|
*/
|
|
|
|
Ref(T* obj) : m_obj(obj) {
|
|
|
|
CC_SAFE_RETAIN(obj);
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
Ref(Ref<T> const& other) : Ref(other.data()) {}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
Ref(Ref<T>&& other) : m_obj(other.m_obj) {
|
|
|
|
other.m_obj = nullptr;
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
/**
|
|
|
|
* Construct an empty Ref (the managed object will be null)
|
|
|
|
*/
|
|
|
|
Ref() = default;
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
~Ref() {
|
|
|
|
CC_SAFE_RELEASE(m_obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-10-30 14:59:20 -04:00
|
|
|
* Swap the managed object with another object. The managed object
|
2022-08-01 11:18:03 -04:00
|
|
|
* will be released, and the new object retained
|
|
|
|
* @param other The new object to swap to
|
|
|
|
*/
|
|
|
|
void swap(T* other) {
|
|
|
|
CC_SAFE_RELEASE(m_obj);
|
|
|
|
m_obj = other;
|
|
|
|
CC_SAFE_RETAIN(other);
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
/**
|
|
|
|
* Return the managed object
|
|
|
|
* @returns The managed object
|
|
|
|
*/
|
|
|
|
T* data() const {
|
|
|
|
return m_obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
operator T*() const {
|
|
|
|
return m_obj;
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
T* operator*() const {
|
|
|
|
return m_obj;
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
T* operator->() const {
|
|
|
|
return m_obj;
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
T* operator=(T* obj) {
|
|
|
|
this->swap(obj);
|
|
|
|
return obj;
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
Ref<T>& operator=(Ref<T> const& other) {
|
|
|
|
this->swap(other.data());
|
|
|
|
return *this;
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
Ref<T>& operator=(Ref<T>&& other) {
|
|
|
|
this->swap(other.data());
|
|
|
|
return *this;
|
|
|
|
}
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2022-08-01 11:18:03 -04:00
|
|
|
bool operator==(T* other) const {
|
|
|
|
return m_obj == other;
|
|
|
|
}
|
|
|
|
bool operator==(Ref<T> const& other) const {
|
|
|
|
return m_obj == other.m_obj;
|
|
|
|
}
|
2022-11-09 10:32:44 -05:00
|
|
|
|
|
|
|
bool operator!=(T* other) const {
|
|
|
|
return m_obj != other;
|
|
|
|
}
|
|
|
|
bool operator!=(Ref<T> const& other) const {
|
|
|
|
return m_obj != other.m_obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
// for containers
|
|
|
|
bool operator<(Ref<T> const& other) const {
|
|
|
|
return m_obj < other.m_obj;
|
|
|
|
}
|
|
|
|
bool operator>(Ref<T> const& other) const {
|
|
|
|
return m_obj > other.m_obj;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace std {
|
|
|
|
template<class T>
|
|
|
|
struct hash<geode::Ref<T>> {
|
|
|
|
size_t operator()(geode::Ref<T> const& ref) const {
|
|
|
|
return std::hash<T*>()(ref.data());
|
|
|
|
}
|
2022-08-01 11:18:03 -04:00
|
|
|
};
|
|
|
|
}
|