285 lines
10 KiB
C++
285 lines
10 KiB
C++
/****************************************************************************
|
||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||
|
||
http://www.cocos.com
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights to
|
||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||
subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
THE SOFTWARE.
|
||
****************************************************************************/
|
||
|
||
#pragma once
|
||
|
||
#include "base/std/container/string.h"
|
||
|
||
#include "base/Macros.h"
|
||
#include "base/RefCounted.h"
|
||
#include "base/TypeDef.h"
|
||
|
||
namespace se {
|
||
class Object;
|
||
}
|
||
|
||
namespace cc {
|
||
|
||
/**
|
||
* @en
|
||
* The base class of most of all the objects in Cocos Creator.
|
||
* @zh
|
||
* 大部分对象的基类。
|
||
* @private
|
||
*/
|
||
class CCObject : public RefCounted /*cjh implements EditorExtendableObject*/ {
|
||
public:
|
||
// definitions for CCObject.Flags
|
||
enum class Flags : FlagBits {
|
||
ZERO = 0,
|
||
DESTROYED = 1 << 0,
|
||
REAL_DESTROYED = 1 << 1,
|
||
TO_DESTROY = 1 << 2,
|
||
/**
|
||
* @en The object will not be saved.
|
||
* @zh 该对象将不会被保存。
|
||
*/
|
||
DONT_SAVE = 1 << 3,
|
||
/**
|
||
* @en The object will not be saved when building a player.
|
||
* @zh 构建项目时,该对象将不会被保存。
|
||
*/
|
||
EDITOR_ONLY = 1 << 4,
|
||
DIRTY = 1 << 5,
|
||
/**
|
||
* @en Dont destroy automatically when loading a new scene.
|
||
* @zh 加载一个新场景时,不自动删除该对象。
|
||
* @private
|
||
*/
|
||
DONT_DESTROY = 1 << 6,
|
||
DESTROYING = 1 << 7,
|
||
/**
|
||
* @en The node is deactivating.
|
||
* @zh 节点正在反激活的过程中。
|
||
* @private
|
||
*/
|
||
DEACTIVATING = 1 << 8,
|
||
/**
|
||
* @en The lock node, when the node is locked, cannot be clicked in the scene.
|
||
* @zh 锁定节点,锁定后场景内不能点击。
|
||
* @private
|
||
*/
|
||
LOCKED_IN_EDITOR = 1 << 9,
|
||
/**
|
||
* @en Hide the object in editor.
|
||
* @zh 在编辑器中隐藏该对象。
|
||
*/
|
||
HIDE_IN_HIERARCHY = 1 << 10,
|
||
|
||
IS_ON_ENABLE_CALLED = 1 << 11,
|
||
IS_EDITOR_ON_ENABLE_CALLED = 1 << 12,
|
||
IS_PRELOAD_STARTED = 1 << 13,
|
||
IS_ON_LOAD_CALLED = 1 << 14,
|
||
IS_ON_LOAD_STARTED = 1 << 15,
|
||
IS_START_CALLED = 1 << 16,
|
||
|
||
IS_ROTATION_LOCKED = 1 << 17,
|
||
IS_SCALE_LOCKED = 1 << 18,
|
||
IS_ANCHOR_LOCKED = 1 << 19,
|
||
IS_SIZE_LOCKED = 1 << 20,
|
||
IS_POSITION_LOCKED = 1 << 21,
|
||
|
||
// Distributed
|
||
IS_REPLICATED = 1 << 22,
|
||
IS_CLIENT_LOAD = 1 << 23,
|
||
|
||
// var Hide = HideInGame | HideInEditor;
|
||
// should not clone or serialize these flags
|
||
PERSISTENT_MASK = ~(TO_DESTROY | DIRTY | DESTROYING | DONT_DESTROY | DEACTIVATING | IS_PRELOAD_STARTED | IS_ON_LOAD_STARTED | IS_ON_LOAD_CALLED | IS_START_CALLED | IS_ON_ENABLE_CALLED | IS_EDITOR_ON_ENABLE_CALLED | IS_ROTATION_LOCKED | IS_SCALE_LOCKED | IS_ANCHOR_LOCKED | IS_SIZE_LOCKED | IS_POSITION_LOCKED
|
||
/* RegisteredInEditor */),
|
||
|
||
// all the hideFlags
|
||
/**
|
||
* @en The object will not be saved and hide the object in editor,and lock node, when the node is locked,
|
||
* cannot be clicked in the scene,and The object will not be saved when building a player.
|
||
* @zh 该对象将不会被保存,构建项目时,该对象将不会被保存, 锁定节点,锁定后场景内不能点击, 在编辑器中隐藏该对象。
|
||
*/
|
||
ALL_HIDE_MASKS = DONT_SAVE | EDITOR_ONLY | LOCKED_IN_EDITOR | HIDE_IN_HIERARCHY,
|
||
};
|
||
|
||
static void deferredDestroy();
|
||
|
||
// cjh public declare [editorExtrasTag]: unknown;
|
||
|
||
Flags _objFlags{Flags::ZERO};
|
||
ccstd::string _name;
|
||
|
||
explicit CCObject(ccstd::string name = "");
|
||
~CCObject() override;
|
||
|
||
// MEMBER
|
||
|
||
/**
|
||
* @en The name of the object.
|
||
* @zh 该对象的名称。
|
||
* @default ""
|
||
* @example
|
||
* ```
|
||
* obj.name = "New Obj";
|
||
* ```
|
||
*/
|
||
inline const ccstd::string& getName() const { return _name; }
|
||
inline void setName(const ccstd::string& value) { _name = value; }
|
||
|
||
/**
|
||
* @en After inheriting CCObject objects, control whether you need to hide, lock, serialize, and other functions.
|
||
* @zh 在继承 CCObject 对象后,控制是否需要隐藏,锁定,序列化等功能。
|
||
*/
|
||
inline void setHideFlags(Flags hideFlags);
|
||
inline Flags getHideFlags() const;
|
||
|
||
/**
|
||
* @en
|
||
* Indicates whether the object is not yet destroyed. (It will not be available after being destroyed)<br>
|
||
* When an object's `destroy` is called, it is actually destroyed after the end of this frame.
|
||
* So `isValid` will return false from the next frame, while `isValid` in the current frame will still be true.
|
||
* If you want to determine whether the current frame has called `destroy`, use `isValid(obj, true)`,
|
||
* but this is often caused by a particular logical requirements, which is not normally required.
|
||
*
|
||
* @zh
|
||
* 表示该对象是否可用(被 destroy 后将不可用)。<br>
|
||
* 当一个对象的 `destroy` 调用以后,会在这一帧结束后才真正销毁。<br>
|
||
* 因此从下一帧开始 `isValid` 就会返回 false,而当前帧内 `isValid` 仍然会是 true。<br>
|
||
* 如果希望判断当前帧是否调用过 `destroy`,请使用 `isValid(obj, true)`,不过这往往是特殊的业务需求引起的,通常情况下不需要这样。
|
||
* @default true
|
||
* @readOnly
|
||
* @example
|
||
* ```ts
|
||
* import { Node, log } from 'cc';
|
||
* const node = new Node();
|
||
* log(node.isValid); // true
|
||
* node.destroy();
|
||
* log(node.isValid); // true, still valid in this frame
|
||
* // after a frame...
|
||
* log(node.isValid); // false, destroyed in the end of last frame
|
||
* ```
|
||
*/
|
||
inline bool isValid() const;
|
||
|
||
virtual void destruct();
|
||
|
||
/**
|
||
* @en
|
||
* Destroy this Object, and release all its own references to other objects.<br/>
|
||
* Actual object destruction will delayed until before rendering.
|
||
* From the next frame, this object is not usable any more.
|
||
* You can use `isValid(obj)` to check whether the object is destroyed before accessing it.
|
||
* @zh
|
||
* 销毁该对象,并释放所有它对其它对象的引用。<br/>
|
||
* 实际销毁操作会延迟到当前帧渲染前执行。从下一帧开始,该对象将不再可用。
|
||
* 您可以在访问对象之前使用 `isValid(obj)` 来检查对象是否已被销毁。
|
||
* @return whether it is the first time the destroy being called
|
||
* @example
|
||
* ```
|
||
* obj.destroy();
|
||
* ```
|
||
*/
|
||
virtual bool destroy();
|
||
|
||
/**
|
||
* Clear all references in the instance.
|
||
*
|
||
* NOTE: this method will not clear the getter or setter functions which defined in the instance of CCObject.
|
||
* You can override the _destruct method if you need, for example:
|
||
* _destruct: function () {
|
||
* for (var key in this) {
|
||
* if (hasOwnProperty(key)) {
|
||
* switch (typeof this[key]) {
|
||
* case 'string':
|
||
* this[key] = '';
|
||
* break;
|
||
* case 'object':
|
||
* case 'function':
|
||
* this[key] = null;
|
||
* break;
|
||
* }
|
||
* }
|
||
* }
|
||
*
|
||
*/
|
||
|
||
void destroyImmediate();
|
||
|
||
virtual ccstd::string toString() const { return ""; };
|
||
|
||
inline void setScriptObject(se::Object* seObj) { _scriptObject = seObj; }
|
||
inline se::Object* getScriptObject() const { return _scriptObject; }
|
||
|
||
protected:
|
||
virtual bool onPreDestroy() {
|
||
// FIXME: need reture value
|
||
return true;
|
||
}
|
||
|
||
se::Object* _scriptObject{nullptr}; // weak reference
|
||
};
|
||
|
||
CC_ENUM_BITWISE_OPERATORS(CCObject::Flags);
|
||
|
||
inline bool CCObject::isValid() const {
|
||
return !(_objFlags & Flags::DESTROYED);
|
||
}
|
||
|
||
inline void CCObject::setHideFlags(Flags hideFlags) {
|
||
Flags flags = hideFlags & Flags::ALL_HIDE_MASKS;
|
||
_objFlags = (_objFlags & ~Flags::ALL_HIDE_MASKS) | flags;
|
||
}
|
||
|
||
inline CCObject::Flags CCObject::getHideFlags() const {
|
||
return _objFlags & Flags::ALL_HIDE_MASKS;
|
||
}
|
||
|
||
/*
|
||
* @en
|
||
* Checks whether the object is non-nil and not yet destroyed.<br>
|
||
* When an object's `destroy` is called, it is actually destroyed after the end of this frame.
|
||
* So `isValid` will return false from the next frame, while `isValid` in the current frame will still be true.
|
||
* If you want to determine whether the current frame has called `destroy`, use `isValid(obj, true)`,
|
||
* but this is often caused by a particular logical requirements, which is not normally required.
|
||
*
|
||
* @zh
|
||
* 检查该对象是否不为 null 并且尚未销毁。<br>
|
||
* 当一个对象的 `destroy` 调用以后,会在这一帧结束后才真正销毁。<br>
|
||
* 因此从下一帧开始 `isValid` 就会返回 false,而当前帧内 `isValid` 仍然会是 true。<br>
|
||
* 如果希望判断当前帧是否调用过 `destroy`,请使用 `isValid(obj, true)`,不过这往往是特殊的业务需求引起的,通常情况下不需要这样。
|
||
*
|
||
* @method isValid
|
||
* @param value
|
||
* @param [strictMode=false] - If true, Object called destroy() in this frame will also treated as invalid.
|
||
* @return whether is valid
|
||
* @example
|
||
* ```
|
||
* import { Node, log } from 'cc';
|
||
* var node = new Node();
|
||
* log(isValid(node)); // true
|
||
* node.destroy();
|
||
* log(isValid(node)); // true, still valid in this frame
|
||
* // after a frame...
|
||
* log(isValid(node)); // false, destroyed in the end of last frame
|
||
* ```
|
||
*/
|
||
bool isObjectValid(CCObject* value, bool strictMode = false);
|
||
|
||
} // namespace cc
|