no message
This commit is contained in:
23
cocos/core/scene-graph/Layers.cpp
Normal file
23
cocos/core/scene-graph/Layers.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://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.
|
||||
****************************************************************************/
|
||||
121
cocos/core/scene-graph/Layers.h
Normal file
121
cocos/core/scene-graph/Layers.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/****************************************************************************
|
||||
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/Macros.h"
|
||||
#include "base/std/container/vector.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
/**
|
||||
* @zh 节点层管理器,层数据是以掩码数据方式存储在 [[Node.layer]] 中,用于射线检测、物理碰撞和用户自定义脚本逻辑。
|
||||
* 每个节点可属于一个或多个层,可通过 “包含式” 或 “排除式” 两种检测器进行层检测。
|
||||
* @en Node's layer manager, it's stored as bit mask data in [[Node.layer]].
|
||||
* Layer information is widely used in raycast, physics and user logic.
|
||||
* Every node can be assigned to multiple layers with different bit masks, you can setup layer with inclusive or exclusive operation.
|
||||
*/
|
||||
class Layers final {
|
||||
public:
|
||||
Layers() = delete;
|
||||
~Layers() = delete;
|
||||
|
||||
// built-in layers, users can use 0~19 bits, 20~31 are system preserve bits.
|
||||
enum class LayerList : uint32_t {
|
||||
NONE = 0,
|
||||
IGNORE_RAYCAST = (1 << 20),
|
||||
GIZMOS = (1 << 21),
|
||||
EDITOR = (1 << 22),
|
||||
UI_3D = (1 << 23),
|
||||
SCENE_GIZMO = (1 << 24),
|
||||
UI_2D = (1 << 25),
|
||||
|
||||
PROFILER = (1 << 28),
|
||||
DEFAULT = (1 << 30),
|
||||
ALL = 0xffffffff,
|
||||
};
|
||||
|
||||
using Enum = LayerList;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Make a layer mask accepting nothing but the listed layers
|
||||
* @zh
|
||||
* 创建一个包含式层检测器,只接受列表中的层
|
||||
* @param includes All accepted layers
|
||||
* @return A filter which can detect all accepted layers
|
||||
*/
|
||||
static uint32_t makeMaskInclude(const ccstd::vector<uint32_t> &includes) {
|
||||
uint32_t mask = 0;
|
||||
for (uint32_t inc : includes) {
|
||||
mask |= inc;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Make a layer mask accepting everything but the listed layers
|
||||
* @zh
|
||||
* 创建一个排除式层检测器,只拒绝列表中的层
|
||||
* @param excludes All excluded layers
|
||||
* @return A filter which can detect for excluded layers
|
||||
*/
|
||||
static uint32_t makeMaskExclude(const ccstd::vector<uint32_t> &excludes) {
|
||||
return ~makeMaskInclude(excludes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 添加一个新层,用户可编辑 0 - 19 位为用户自定义层
|
||||
* @en Add a new layer, user can use layers from bit position 0 to 19, other bits are reserved.
|
||||
* @param name Layer's name
|
||||
* @param bitNum Layer's bit position
|
||||
*/
|
||||
static void addLayer(const std::string &name, uint32_t bitNum);
|
||||
|
||||
/**
|
||||
* @en Remove a layer, user can remove layers from bit position 0 to 19, other bits are reserved.
|
||||
* @zh 移除一个层,用户可编辑 0 - 19 位为用户自定义层
|
||||
* @param bitNum Layer's bit position
|
||||
*/
|
||||
static void deleteLayer(uint32_t bitNum);
|
||||
|
||||
/**
|
||||
* @en Given a layer name, returns the layer index as defined by either a Builtin or a User Layer in the Tags and Layers manager.
|
||||
* @zh 给定层名称,返回由标记和层管理器中的内置层或用户层定义的层索引。
|
||||
* @param name layer's name
|
||||
*/
|
||||
static uint32_t nameToLayer(const std::string &name);
|
||||
|
||||
/**
|
||||
* @en Given a layer number, returns the name of the layer as defined in either a Builtin or a User Layer in the Tags and Layers manager.
|
||||
* @zh 给定层数,返回在标记和层管理器中的内置层或用户层中定义的层名称。
|
||||
* @param bitNum layer's value
|
||||
*/
|
||||
static std::string layerToName(uint32_t bitNum);
|
||||
};
|
||||
|
||||
CC_ENUM_BITWISE_OPERATORS(Layers::LayerList);
|
||||
|
||||
} // namespace cc
|
||||
885
cocos/core/scene-graph/Node.cpp
Normal file
885
cocos/core/scene-graph/Node.cpp
Normal file
@@ -0,0 +1,885 @@
|
||||
/****************************************************************************
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/scene-graph/Node.h"
|
||||
#include "base/StringUtil.h"
|
||||
#include "core/data/Object.h"
|
||||
#include "core/memop/CachedArray.h"
|
||||
#include "core/platform/Debug.h"
|
||||
#include "core/scene-graph/NodeEnum.h"
|
||||
#include "core/scene-graph/Scene.h"
|
||||
#include "core/utils/IDGenerator.h"
|
||||
#include "math/Utils.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
// static variables
|
||||
|
||||
uint32_t Node::clearFrame{0};
|
||||
uint32_t Node::clearRound{1000};
|
||||
const uint32_t Node::TRANSFORM_ON{1 << 0};
|
||||
uint32_t Node::globalFlagChangeVersion{0};
|
||||
|
||||
namespace {
|
||||
const ccstd::string EMPTY_NODE_NAME;
|
||||
IDGenerator idGenerator("Node");
|
||||
} // namespace
|
||||
|
||||
Node::Node() : Node(EMPTY_NODE_NAME) {
|
||||
}
|
||||
|
||||
Node::Node(const ccstd::string &name) {
|
||||
#define NODE_SHARED_MEMORY_BYTE_LENGTH (20)
|
||||
static_assert(offsetof(Node, _padding) + sizeof(_padding) - offsetof(Node, _eventMask) == NODE_SHARED_MEMORY_BYTE_LENGTH, "Wrong shared memory size");
|
||||
_sharedMemoryActor.initialize(&_eventMask, NODE_SHARED_MEMORY_BYTE_LENGTH);
|
||||
#undef NODE_SHARED_MEMORY_BYTE_LENGTH
|
||||
|
||||
_id = idGenerator.getNewId();
|
||||
if (name.empty()) {
|
||||
_name.append("New Node");
|
||||
} else {
|
||||
_name = name;
|
||||
}
|
||||
// _eventProcessor = ccnew NodeEventProcessor(this);
|
||||
}
|
||||
|
||||
Node::~Node() {
|
||||
if (!_children.empty()) {
|
||||
// Reset children's _parent to nullptr to avoid dangerous pointer
|
||||
for (const auto &child : _children) {
|
||||
child->_parent = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::onBatchCreated(bool dontChildPrefab) {
|
||||
// onBatchCreated was implemented in TS, so code should never go here.
|
||||
CC_ABORT();
|
||||
emit<BatchCreated>(dontChildPrefab);
|
||||
}
|
||||
|
||||
Node *Node::instantiate(Node *cloned, bool isSyncedNode) {
|
||||
if (!cloned) {
|
||||
CC_ABORT();
|
||||
// TODO(): cloned = legacyCC.instantiate._clone(this, this);
|
||||
return nullptr;
|
||||
}
|
||||
// TODO():
|
||||
// const newPrefabInfo = cloned._prefab;
|
||||
// if (EDITOR && newPrefabInfo) {
|
||||
// if (cloned == = newPrefabInfo.root) {
|
||||
// // newPrefabInfo.fileId = '';
|
||||
// } else {
|
||||
// // var PrefabUtils = Editor.require('scene://utils/prefab');
|
||||
// // PrefabUtils.unlinkPrefab(cloned);
|
||||
// }
|
||||
//}
|
||||
// if (EDITOR && legacyCC.GAME_VIEW) {
|
||||
// const syncing = newPrefabInfo&& cloned == = newPrefabInfo.root && newPrefabInfo.sync;
|
||||
// if (!syncing) {
|
||||
// cloned._name += ' (Clone)';
|
||||
// }
|
||||
//}
|
||||
cloned->_parent = nullptr;
|
||||
cloned->onBatchCreated(isSyncedNode);
|
||||
return cloned;
|
||||
}
|
||||
|
||||
void Node::onHierarchyChangedBase(Node *oldParent) { // NOLINT(misc-unused-parameters)
|
||||
Node *newParent = _parent;
|
||||
auto *scene = dynamic_cast<Scene *>(newParent);
|
||||
if (isPersistNode() && scene == nullptr) {
|
||||
emit<RemovePersistRootNode>();
|
||||
#if CC_EDITOR
|
||||
debug::warnID(1623);
|
||||
#endif
|
||||
}
|
||||
#if CC_EDITOR
|
||||
auto *curScene = getScene();
|
||||
const bool inCurrentSceneBefore = oldParent && oldParent->isChildOf(curScene);
|
||||
const bool inCurrentSceneNow = newParent && newParent->isChildOf(curScene);
|
||||
if (!inCurrentSceneBefore && inCurrentSceneNow) {
|
||||
// attached
|
||||
this->notifyEditorAttached(true);
|
||||
} else if (inCurrentSceneBefore && !inCurrentSceneNow) {
|
||||
// detached
|
||||
this->notifyEditorAttached(false);
|
||||
}
|
||||
// conflict detection
|
||||
// _Scene.DetectConflict.afterAddChild(this);
|
||||
#endif
|
||||
|
||||
bool shouldActiveNow = isActive() && !!(newParent && newParent->isActiveInHierarchy());
|
||||
if (isActiveInHierarchy() != shouldActiveNow) {
|
||||
// Director::getInstance()->getNodeActivator()->activateNode(this, shouldActiveNow); // TODO(xwx): use TS temporarily
|
||||
emit<ActiveNode>(shouldActiveNow);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::setActive(bool isActive) {
|
||||
uint8_t isActiveU8 = isActive ? 1 : 0;
|
||||
if (_active != isActiveU8) {
|
||||
_active = isActiveU8;
|
||||
Node *parent = _parent;
|
||||
if (parent) {
|
||||
bool couldActiveInScene = parent->isActiveInHierarchy();
|
||||
if (couldActiveInScene) {
|
||||
// Director::getInstance()->getNodeActivator()->activateNode(this, isActive); // TODO(xwx): use TS temporarily
|
||||
emit<ActiveNode>(isActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::setParent(Node *parent, bool isKeepWorld /* = false */) {
|
||||
if (isKeepWorld) {
|
||||
updateWorldTransform();
|
||||
}
|
||||
|
||||
if (_parent == parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node *oldParent = _parent;
|
||||
Node *newParent = parent;
|
||||
#if CC_DEBUG > 0
|
||||
if (oldParent && (oldParent->_objFlags & Flags::DEACTIVATING) == Flags::DEACTIVATING) {
|
||||
debug::errorID(3821);
|
||||
}
|
||||
#endif
|
||||
_parent = newParent;
|
||||
_siblingIndex = 0;
|
||||
onSetParent(oldParent, isKeepWorld);
|
||||
emit<ParentChanged>(oldParent);
|
||||
if (oldParent) {
|
||||
if (!(oldParent->_objFlags & Flags::DESTROYING)) {
|
||||
index_t removeAt = getIdxOfChild(oldParent->_children, this);
|
||||
// TODO(): DEV
|
||||
/*if (DEV && removeAt < 0) {
|
||||
errorID(1633);
|
||||
return;
|
||||
}*/
|
||||
if (removeAt < 0) {
|
||||
return;
|
||||
}
|
||||
oldParent->_children.erase(oldParent->_children.begin() + removeAt);
|
||||
oldParent->updateSiblingIndex();
|
||||
oldParent->emit<ChildRemoved>(this);
|
||||
}
|
||||
}
|
||||
if (newParent) {
|
||||
#if CC_DEBUG > 0
|
||||
if ((newParent->_objFlags & Flags::DEACTIVATING) == Flags::DEACTIVATING) {
|
||||
debug::errorID(3821);
|
||||
}
|
||||
#endif
|
||||
newParent->_children.emplace_back(this);
|
||||
_siblingIndex = static_cast<index_t>(newParent->_children.size() - 1);
|
||||
newParent->emit<ChildAdded>(this);
|
||||
}
|
||||
onHierarchyChanged(oldParent);
|
||||
}
|
||||
|
||||
void Node::walk(const WalkCallback &preFunc) {
|
||||
walk(preFunc, nullptr);
|
||||
}
|
||||
|
||||
void Node::walk(const WalkCallback &preFunc, const WalkCallback &postFunc) { // NOLINT(misc-no-recursion)
|
||||
if (preFunc) {
|
||||
preFunc(this);
|
||||
}
|
||||
|
||||
for (const auto &child : _children) {
|
||||
if (child) {
|
||||
child->walk(preFunc, postFunc);
|
||||
}
|
||||
}
|
||||
|
||||
if (postFunc) {
|
||||
postFunc(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Component *Node::addComponent(Component *comp) {
|
||||
// comp->_node = this; // cjh TODO: shared_ptr
|
||||
// _components.emplace_back(comp);
|
||||
//
|
||||
// if (isActiveInHierarchy()) {
|
||||
// NodeActivator::activateComp(comp);
|
||||
// }
|
||||
//
|
||||
// return comp;
|
||||
// }
|
||||
//
|
||||
// void Node::removeComponent(Component *comp) {
|
||||
// auto iteComp = std::find(_components.begin(), _components.end(), comp);
|
||||
// if (iteComp != _components.end()) {
|
||||
// _components.erase(iteComp);
|
||||
// }
|
||||
// }
|
||||
|
||||
bool Node::onPreDestroyBase() {
|
||||
Flags destroyingFlag = Flags::DESTROYING;
|
||||
_objFlags |= destroyingFlag;
|
||||
bool destroyByParent = (!!_parent) && (!!(_parent->_objFlags & destroyingFlag));
|
||||
#if CC_EDITOR
|
||||
if (!destroyByParent) {
|
||||
this->notifyEditorAttached(false);
|
||||
}
|
||||
#endif
|
||||
if (isPersistNode()) {
|
||||
emit<RemovePersistRootNode>();
|
||||
}
|
||||
if (!destroyByParent) {
|
||||
if (_parent) {
|
||||
emit<ParentChanged>(this);
|
||||
index_t childIdx = getIdxOfChild(_parent->_children, this);
|
||||
if (childIdx != -1) {
|
||||
_parent->_children.erase(_parent->_children.begin() + childIdx);
|
||||
}
|
||||
_siblingIndex = 0;
|
||||
_parent->updateSiblingIndex();
|
||||
_parent->emit<ChildRemoved>(this);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: The following code is not needed now since we override Node._onPreDestroy in node.jsb.ts
|
||||
// and the logic will be done in TS.
|
||||
// emit(NodeEventType::NODE_DESTROYED, this);
|
||||
// for (const auto &child : _children) {
|
||||
// child->destroyImmediate();
|
||||
// }
|
||||
//
|
||||
// emit(EventTypesToJS::NODE_DESTROY_COMPONENTS);
|
||||
|
||||
offAll();
|
||||
return destroyByParent;
|
||||
}
|
||||
|
||||
Node *Node::getChildByName(const ccstd::string &name) const {
|
||||
if (name.empty()) {
|
||||
CC_LOG_INFO("Invalid name");
|
||||
return nullptr;
|
||||
}
|
||||
for (const auto &child : _children) {
|
||||
if (child->_name == name) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Node::setScene(Node *node) {
|
||||
node->updateScene();
|
||||
}
|
||||
|
||||
void Node::updateScene() {
|
||||
if (_parent == nullptr) {
|
||||
return;
|
||||
}
|
||||
_scene = _parent->_scene;
|
||||
emit<SceneUpdated>(_scene);
|
||||
}
|
||||
|
||||
/* static */
|
||||
index_t Node::getIdxOfChild(const ccstd::vector<IntrusivePtr<Node>> &child, Node *target) {
|
||||
auto iteChild = std::find(child.begin(), child.end(), target);
|
||||
if (iteChild != child.end()) {
|
||||
return static_cast<index_t>(iteChild - child.begin());
|
||||
}
|
||||
return CC_INVALID_INDEX;
|
||||
}
|
||||
|
||||
Node *Node::getChildByUuid(const ccstd::string &uuid) const {
|
||||
if (uuid.empty()) {
|
||||
CC_LOG_INFO("Invalid uuid");
|
||||
return nullptr;
|
||||
}
|
||||
for (const auto &child : _children) {
|
||||
if (child->_id == uuid) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Node::isChildOf(Node *parent) const {
|
||||
const Node *child = this;
|
||||
do {
|
||||
if (child == parent) {
|
||||
return true;
|
||||
}
|
||||
child = child->_parent;
|
||||
} while (child);
|
||||
return false;
|
||||
}
|
||||
|
||||
void Node::removeAllChildren() {
|
||||
for (auto i = static_cast<index_t>(_children.size() - 1); i >= 0; --i) {
|
||||
if (_children[i]) {
|
||||
_children[i]->setParent(nullptr);
|
||||
}
|
||||
}
|
||||
_children.clear();
|
||||
}
|
||||
|
||||
void Node::setSiblingIndex(index_t index) {
|
||||
if (!_parent) {
|
||||
return;
|
||||
}
|
||||
if (!!(_parent->_objFlags & Flags::DEACTIVATING)) {
|
||||
debug::errorID(3821);
|
||||
return;
|
||||
}
|
||||
ccstd::vector<IntrusivePtr<Node>> &siblings = _parent->_children;
|
||||
index = index != -1 ? index : static_cast<index_t>(siblings.size()) - 1;
|
||||
index_t oldIdx = getIdxOfChild(siblings, this);
|
||||
if (index != oldIdx) {
|
||||
if (oldIdx != CC_INVALID_INDEX) {
|
||||
siblings.erase(siblings.begin() + oldIdx);
|
||||
}
|
||||
if (index < siblings.size()) {
|
||||
siblings.insert(siblings.begin() + index, this);
|
||||
} else {
|
||||
siblings.emplace_back(this);
|
||||
}
|
||||
_parent->updateSiblingIndex();
|
||||
emit<SiblingIndexChanged>(index);
|
||||
}
|
||||
}
|
||||
|
||||
Node *Node::getChildByPath(const ccstd::string &path) const {
|
||||
size_t end = 0;
|
||||
ccstd::vector<ccstd::string> segments = StringUtil::split(path, "/");
|
||||
auto *lastNode = const_cast<Node *>(this);
|
||||
for (const ccstd::string &segment : segments) {
|
||||
if (segment.empty()) {
|
||||
continue;
|
||||
}
|
||||
Node *next{nullptr};
|
||||
if (lastNode) {
|
||||
for (const auto &child : lastNode->_children) {
|
||||
if (child->_name == segment) {
|
||||
next = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastNode = next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return lastNode;
|
||||
}
|
||||
|
||||
//
|
||||
void Node::setPositionInternal(float x, float y, float z, bool calledFromJS) {
|
||||
_localPosition.set(x, y, z);
|
||||
invalidateChildren(TransformBit::POSITION);
|
||||
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::POSITION);
|
||||
}
|
||||
|
||||
if (!calledFromJS) {
|
||||
notifyLocalPositionUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void Node::setRotationInternal(float x, float y, float z, float w, bool calledFromJS) {
|
||||
_localRotation.set(x, y, z, w);
|
||||
_eulerDirty = true;
|
||||
|
||||
invalidateChildren(TransformBit::ROTATION);
|
||||
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::ROTATION);
|
||||
}
|
||||
|
||||
if (!calledFromJS) {
|
||||
notifyLocalRotationUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void Node::setRotationFromEuler(float x, float y, float z) {
|
||||
_euler.set(x, y, z);
|
||||
Quaternion::fromEuler(x, y, z, &_localRotation);
|
||||
_eulerDirty = false;
|
||||
invalidateChildren(TransformBit::ROTATION);
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::ROTATION);
|
||||
}
|
||||
|
||||
notifyLocalRotationUpdated();
|
||||
}
|
||||
|
||||
void Node::setScaleInternal(float x, float y, float z, bool calledFromJS) {
|
||||
_localScale.set(x, y, z);
|
||||
|
||||
invalidateChildren(TransformBit::SCALE);
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::SCALE);
|
||||
}
|
||||
|
||||
if (!calledFromJS) {
|
||||
notifyLocalScaleUpdated();
|
||||
}
|
||||
}
|
||||
void Node::updateWorldTransform() { // NOLINT(misc-no-recursion)
|
||||
uint32_t dirtyBits = 0;
|
||||
updateWorldTransformRecursive(dirtyBits);
|
||||
}
|
||||
|
||||
void Node::updateWorldTransformRecursive(uint32_t &dirtyBits) { // NOLINT(misc-no-recursion)
|
||||
const uint32_t currDirtyBits = _transformFlags;
|
||||
if (!currDirtyBits) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node *parent = getParent();
|
||||
if (parent && parent->_transformFlags) {
|
||||
parent->updateWorldTransformRecursive(dirtyBits);
|
||||
}
|
||||
dirtyBits |= currDirtyBits;
|
||||
if (parent) {
|
||||
if (dirtyBits & static_cast<uint32_t>(TransformBit::POSITION)) {
|
||||
_worldPosition.transformMat4(_localPosition, parent->_worldMatrix);
|
||||
_worldMatrix.m[12] = _worldPosition.x;
|
||||
_worldMatrix.m[13] = _worldPosition.y;
|
||||
_worldMatrix.m[14] = _worldPosition.z;
|
||||
}
|
||||
if (dirtyBits & static_cast<uint32_t>(TransformBit::RS)) {
|
||||
Mat4::fromRTS(_localRotation, _localPosition, _localScale, &_worldMatrix);
|
||||
Mat4::multiply(parent->_worldMatrix, _worldMatrix, &_worldMatrix);
|
||||
const bool rotChanged = dirtyBits & static_cast<uint32_t>(TransformBit::ROTATION);
|
||||
Quaternion *rotTmp = rotChanged ? &_worldRotation : nullptr;
|
||||
Mat4::toRTS(_worldMatrix, rotTmp, nullptr, &_worldScale);
|
||||
}
|
||||
} else {
|
||||
if (dirtyBits & static_cast<uint32_t>(TransformBit::POSITION)) {
|
||||
_worldPosition.set(_localPosition);
|
||||
_worldMatrix.m[12] = _worldPosition.x;
|
||||
_worldMatrix.m[13] = _worldPosition.y;
|
||||
_worldMatrix.m[14] = _worldPosition.z;
|
||||
}
|
||||
if (dirtyBits & static_cast<uint32_t>(TransformBit::RS)) {
|
||||
if (dirtyBits & static_cast<uint32_t>(TransformBit::ROTATION)) {
|
||||
_worldRotation.set(_localRotation);
|
||||
}
|
||||
if (dirtyBits & static_cast<uint32_t>(TransformBit::SCALE)) {
|
||||
_worldScale.set(_localScale);
|
||||
}
|
||||
Mat4::fromRTS(_worldRotation, _worldPosition, _worldScale, &_worldMatrix);
|
||||
}
|
||||
}
|
||||
_transformFlags = (static_cast<uint32_t>(TransformBit::NONE));
|
||||
}
|
||||
|
||||
const Mat4 &Node::getWorldMatrix() const { // NOLINT(misc-no-recursion)
|
||||
const_cast<Node *>(this)->updateWorldTransform();
|
||||
return _worldMatrix;
|
||||
}
|
||||
|
||||
Mat4 Node::getWorldRS() {
|
||||
updateWorldTransform();
|
||||
Mat4 target{_worldMatrix};
|
||||
target.m[12] = target.m[13] = target.m[14] = 0;
|
||||
return target;
|
||||
}
|
||||
|
||||
Mat4 Node::getWorldRT() {
|
||||
updateWorldTransform();
|
||||
Mat4 target;
|
||||
Mat4::fromRT(_worldRotation, _worldPosition, &target);
|
||||
return target;
|
||||
}
|
||||
|
||||
void Node::invalidateChildren(TransformBit dirtyBit) { // NOLINT(misc-no-recursion)
|
||||
auto curDirtyBit{static_cast<uint32_t>(dirtyBit)};
|
||||
const uint32_t hasChangedFlags = getChangedFlags();
|
||||
const uint32_t transformFlags = _transformFlags;
|
||||
if (isValid() && (transformFlags & hasChangedFlags & curDirtyBit) != curDirtyBit) {
|
||||
_transformFlags = (transformFlags | curDirtyBit);
|
||||
setChangedFlags(hasChangedFlags | curDirtyBit);
|
||||
|
||||
for (Node *child : getChildren()) {
|
||||
child->invalidateChildren(dirtyBit | TransformBit::POSITION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::setWorldPosition(float x, float y, float z) {
|
||||
_worldPosition.set(x, y, z);
|
||||
if (_parent) {
|
||||
_parent->updateWorldTransform();
|
||||
Mat4 invertWMat{_parent->_worldMatrix};
|
||||
invertWMat.inverse();
|
||||
_localPosition.transformMat4(_worldPosition, invertWMat);
|
||||
} else {
|
||||
_localPosition.set(_worldPosition);
|
||||
}
|
||||
notifyLocalPositionUpdated();
|
||||
|
||||
invalidateChildren(TransformBit::POSITION);
|
||||
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::POSITION);
|
||||
}
|
||||
}
|
||||
|
||||
const Vec3 &Node::getWorldPosition() const {
|
||||
const_cast<Node *>(this)->updateWorldTransform();
|
||||
return _worldPosition;
|
||||
}
|
||||
|
||||
void Node::setWorldRotation(float x, float y, float z, float w) {
|
||||
_worldRotation.set(x, y, z, w);
|
||||
if (_parent) {
|
||||
_parent->updateWorldTransform();
|
||||
_localRotation.set(_parent->_worldRotation.getConjugated());
|
||||
_localRotation.multiply(_worldRotation);
|
||||
} else {
|
||||
_localRotation.set(_worldRotation);
|
||||
}
|
||||
|
||||
_eulerDirty = true;
|
||||
|
||||
notifyLocalRotationUpdated();
|
||||
|
||||
invalidateChildren(TransformBit::ROTATION);
|
||||
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::ROTATION);
|
||||
}
|
||||
}
|
||||
|
||||
const Quaternion &Node::getWorldRotation() const { // NOLINT(misc-no-recursion)
|
||||
const_cast<Node *>(this)->updateWorldTransform();
|
||||
return _worldRotation;
|
||||
}
|
||||
|
||||
void Node::setWorldScale(float x, float y, float z) {
|
||||
if (_parent != nullptr) {
|
||||
updateWorldTransform(); // ensure reentryability
|
||||
Vec3 oldWorldScale = _worldScale;
|
||||
_worldScale.set(x, y, z);
|
||||
Mat3 localRS;
|
||||
Mat3 localRotInv;
|
||||
Mat4 worldMatrixTmp = _worldMatrix;
|
||||
Vec3 rescaleFactor = _worldScale / oldWorldScale;
|
||||
// apply new world scale to temp world matrix
|
||||
worldMatrixTmp.scale(rescaleFactor); // need opt
|
||||
// get temp local matrix
|
||||
Mat4 tmpLocalTransform = _parent->getWorldMatrix().getInversed() * worldMatrixTmp;
|
||||
// convert to Matrix 3 x 3
|
||||
Mat3::fromMat4(tmpLocalTransform, &localRS);
|
||||
Mat3::fromQuat(_localRotation.getConjugated(), &localRotInv);
|
||||
// remove rotation part of the local matrix
|
||||
Mat3::multiply(localRotInv, localRS, &localRS);
|
||||
|
||||
// extract scaling part from local matrix
|
||||
_localScale.x = Vec3{localRS.m[0], localRS.m[1], localRS.m[2]}.length();
|
||||
_localScale.y = Vec3{localRS.m[3], localRS.m[4], localRS.m[5]}.length();
|
||||
_localScale.z = Vec3{localRS.m[6], localRS.m[7], localRS.m[8]}.length();
|
||||
} else {
|
||||
_worldScale.set(x, y, z);
|
||||
_localScale = _worldScale;
|
||||
}
|
||||
|
||||
notifyLocalScaleUpdated();
|
||||
|
||||
invalidateChildren(TransformBit::SCALE);
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::SCALE);
|
||||
}
|
||||
}
|
||||
|
||||
const Vec3 &Node::getWorldScale() const {
|
||||
const_cast<Node *>(this)->updateWorldTransform();
|
||||
return _worldScale;
|
||||
}
|
||||
|
||||
void Node::setForward(const Vec3 &dir) {
|
||||
const float len = dir.length();
|
||||
Vec3 v3Temp = dir * (-1.F / len);
|
||||
Quaternion qTemp{Quaternion::identity()};
|
||||
Quaternion::fromViewUp(v3Temp, &qTemp);
|
||||
setWorldRotation(qTemp);
|
||||
}
|
||||
|
||||
void Node::setAngle(float val) {
|
||||
_euler.set(0, 0, val);
|
||||
Quaternion::createFromAngleZ(val, &_localRotation);
|
||||
_eulerDirty = false;
|
||||
invalidateChildren(TransformBit::ROTATION);
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::ROTATION);
|
||||
}
|
||||
|
||||
notifyLocalRotationUpdated();
|
||||
}
|
||||
|
||||
void Node::onSetParent(Node *oldParent, bool keepWorldTransform) {
|
||||
if (_parent) {
|
||||
if ((oldParent == nullptr || oldParent->_scene != _parent->_scene) && _parent->_scene != nullptr) {
|
||||
walk(setScene);
|
||||
}
|
||||
}
|
||||
|
||||
if (keepWorldTransform) {
|
||||
if (_parent) {
|
||||
_parent->updateWorldTransform();
|
||||
if (mathutils::approx<float>(_parent->_worldMatrix.determinant(), 0.F, mathutils::EPSILON)) {
|
||||
CC_LOG_WARNING("14300");
|
||||
_transformFlags |= static_cast<uint32_t>(TransformBit::TRS);
|
||||
updateWorldTransform();
|
||||
} else {
|
||||
Mat4 tmpMat4 = _parent->_worldMatrix.getInversed() * _worldMatrix;
|
||||
Mat4::toRTS(tmpMat4, &_localRotation, &_localPosition, &_localScale);
|
||||
}
|
||||
} else {
|
||||
_localPosition.set(_worldPosition);
|
||||
_localRotation.set(_worldRotation);
|
||||
_localScale.set(_worldScale);
|
||||
}
|
||||
|
||||
notifyLocalPositionRotationScaleUpdated();
|
||||
_eulerDirty = true;
|
||||
}
|
||||
invalidateChildren(TransformBit::TRS);
|
||||
}
|
||||
|
||||
void Node::rotate(const Quaternion &rot, NodeSpace ns /* = NodeSpace::LOCAL*/, bool calledFromJS /* = false*/) {
|
||||
Quaternion qTempA{rot};
|
||||
qTempA.normalize();
|
||||
if (ns == NodeSpace::LOCAL) {
|
||||
_localRotation *= qTempA;
|
||||
} else if (ns == NodeSpace::WORLD) {
|
||||
Quaternion qTempB{Quaternion::identity()};
|
||||
qTempB = qTempA * getWorldRotation();
|
||||
qTempA = _worldRotation;
|
||||
qTempA.inverse();
|
||||
qTempB = qTempA * qTempB;
|
||||
_localRotation = _localRotation * qTempB;
|
||||
}
|
||||
_eulerDirty = true;
|
||||
invalidateChildren(TransformBit::ROTATION);
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::ROTATION);
|
||||
}
|
||||
|
||||
if (!calledFromJS) {
|
||||
notifyLocalRotationUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void Node::lookAt(const Vec3 &pos, const Vec3 &up) {
|
||||
Vec3 vTemp = getWorldPosition();
|
||||
Quaternion qTemp{Quaternion::identity()};
|
||||
vTemp -= pos;
|
||||
vTemp.normalize();
|
||||
Quaternion::fromViewUp(vTemp, up, &qTemp);
|
||||
setWorldRotation(qTemp);
|
||||
}
|
||||
|
||||
Vec3 Node::inverseTransformPoint(const Vec3 &p) { // NOLINT(misc-no-recursion)
|
||||
Vec3 out(p);
|
||||
inverseTransformPointRecursive(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
void Node::inverseTransformPointRecursive(Vec3 &out) const { // NOLINT(misc-no-recursion)
|
||||
auto *parent = getParent();
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
parent->inverseTransformPointRecursive(out);
|
||||
Vec3::transformInverseRTS(out, getRotation(), getPosition(), getScale(), &out);
|
||||
}
|
||||
|
||||
void Node::setMatrix(const Mat4 &val) {
|
||||
val.decompose(&_localScale, &_localRotation, &_localPosition);
|
||||
notifyLocalPositionRotationScaleUpdated();
|
||||
|
||||
invalidateChildren(TransformBit::TRS);
|
||||
_eulerDirty = true;
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::TRS);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::setWorldRotationFromEuler(float x, float y, float z) {
|
||||
Quaternion::fromEuler(x, y, z, &_worldRotation);
|
||||
if (_parent) {
|
||||
_parent->updateWorldTransform();
|
||||
_localRotation = _parent->_worldRotation.getConjugated() * _worldRotation;
|
||||
} else {
|
||||
_localRotation = _worldRotation;
|
||||
}
|
||||
_eulerDirty = true;
|
||||
|
||||
invalidateChildren(TransformBit::ROTATION);
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::ROTATION);
|
||||
}
|
||||
|
||||
notifyLocalRotationUpdated();
|
||||
}
|
||||
|
||||
void Node::setRTSInternal(Quaternion *rot, Vec3 *pos, Vec3 *scale, bool calledFromJS) {
|
||||
uint32_t dirtyBit = 0;
|
||||
if (rot) {
|
||||
dirtyBit |= static_cast<uint32_t>(TransformBit::ROTATION);
|
||||
_localRotation = *rot;
|
||||
_eulerDirty = true;
|
||||
}
|
||||
if (pos) {
|
||||
_localPosition = *pos;
|
||||
dirtyBit |= static_cast<uint32_t>(TransformBit::POSITION);
|
||||
}
|
||||
if (scale) {
|
||||
_localScale = *scale;
|
||||
dirtyBit |= static_cast<uint32_t>(TransformBit::SCALE);
|
||||
}
|
||||
|
||||
if (!calledFromJS) {
|
||||
notifyLocalPositionRotationScaleUpdated();
|
||||
}
|
||||
|
||||
if (dirtyBit) {
|
||||
invalidateChildren(static_cast<TransformBit>(dirtyBit));
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(static_cast<TransformBit>(dirtyBit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::resetChangedFlags() {
|
||||
globalFlagChangeVersion++;
|
||||
}
|
||||
|
||||
void Node::clearNodeArray() {
|
||||
if (clearFrame < clearRound) {
|
||||
clearFrame++;
|
||||
} else {
|
||||
clearFrame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ccstd::string Node::getPathInHierarchy() const {
|
||||
ccstd::string result = getName();
|
||||
Node *curNode = getParent();
|
||||
while (curNode && curNode->getParent()) {
|
||||
result.insert(0, "/").insert(0, curNode->getName());
|
||||
curNode = curNode->getParent();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Node::translate(const Vec3 &trans, NodeSpace ns) {
|
||||
Vec3 v3Temp{trans};
|
||||
if (ns == NodeSpace::LOCAL) {
|
||||
v3Temp.transformQuat(_localRotation);
|
||||
_localPosition.x += v3Temp.x;
|
||||
_localPosition.y += v3Temp.y;
|
||||
_localPosition.z += v3Temp.z;
|
||||
} else if (ns == NodeSpace::WORLD) {
|
||||
if (_parent) {
|
||||
Quaternion qTemp = _parent->getWorldRotation();
|
||||
qTemp.inverse();
|
||||
v3Temp.transformQuat(qTemp);
|
||||
Vec3 scale{_worldScale};
|
||||
_localPosition.x += v3Temp.x / scale.x;
|
||||
_localPosition.y += v3Temp.y / scale.y;
|
||||
_localPosition.z += v3Temp.z / scale.z;
|
||||
} else {
|
||||
_localPosition.x += trans.x;
|
||||
_localPosition.y += trans.y;
|
||||
_localPosition.z += trans.z;
|
||||
}
|
||||
}
|
||||
|
||||
notifyLocalPositionUpdated();
|
||||
|
||||
invalidateChildren(TransformBit::POSITION);
|
||||
if (_eventMask & TRANSFORM_ON) {
|
||||
emit<TransformChanged>(TransformBit::POSITION);
|
||||
}
|
||||
}
|
||||
|
||||
bool Node::onPreDestroy() {
|
||||
bool result = onPreDestroyBase();
|
||||
// TODO(Lenovo): bookOfChange free
|
||||
return result;
|
||||
}
|
||||
|
||||
void Node::onHierarchyChanged(Node *oldParent) {
|
||||
emit<Reattach>();
|
||||
onHierarchyChangedBase(oldParent);
|
||||
}
|
||||
|
||||
/* static */
|
||||
// Node *Node::find(const ccstd::string &path, Node *referenceNode /* = nullptr*/) {
|
||||
// return cc::find(path, referenceNode);
|
||||
// }
|
||||
|
||||
// For deserialization
|
||||
// void Node::_setChild(index_t i, Node *child) {
|
||||
// if (i < _children.size()) {
|
||||
// _children[i] = child;
|
||||
// } else {
|
||||
// CC_LOG_ERROR("Invalid index (%d) for Node children (size: %u)", i, static_cast<uint32_t>(_children.size()));
|
||||
// }
|
||||
//}
|
||||
//
|
||||
// Node *Node::_getChild(index_t i) {
|
||||
// if (i < _children.size()) {
|
||||
// return _children[i];
|
||||
// }
|
||||
// CC_LOG_ERROR("Invalid index (%d) for Node children (size: %u)", i, static_cast<uint32_t>(_children.size()));
|
||||
// return nullptr;
|
||||
//}
|
||||
//
|
||||
// void Node::_setChildrenSize(uint32_t size) {
|
||||
// _children.resize(size);
|
||||
//}
|
||||
//
|
||||
// uint32_t Node::_getChildrenSize() {
|
||||
// return _children.size();
|
||||
//}
|
||||
//
|
||||
void Node::_setChildren(ccstd::vector<IntrusivePtr<Node>> &&children) {
|
||||
_children = std::move(children);
|
||||
}
|
||||
|
||||
void Node::destruct() {
|
||||
CCObject::destruct();
|
||||
_children.clear();
|
||||
_scene = nullptr;
|
||||
_userData = nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
} // namespace cc
|
||||
685
cocos/core/scene-graph/Node.h
Normal file
685
cocos/core/scene-graph/Node.h
Normal file
@@ -0,0 +1,685 @@
|
||||
/****************************************************************************
|
||||
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/Ptr.h"
|
||||
#include "base/std/any.h"
|
||||
#include "bindings/utils/BindingUtils.h"
|
||||
// #include "core/components/Component.h"
|
||||
// #include "core/event/Event.h"
|
||||
#include "core/data/Object.h"
|
||||
#include "core/event/EventTarget.h"
|
||||
#include "core/scene-graph/Layers.h"
|
||||
#include "core/scene-graph/NodeEnum.h"
|
||||
#include "math/Mat3.h"
|
||||
#include "math/Mat4.h"
|
||||
#include "math/Quaternion.h"
|
||||
#include "math/Vec3.h"
|
||||
#include "math/Vec4.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Scene;
|
||||
/**
|
||||
* Event types emitted by Node
|
||||
*/
|
||||
/**
|
||||
* Bit masks for Node transformation parts
|
||||
*/
|
||||
using TransformDirtyBit = TransformBit;
|
||||
|
||||
class Node : public CCObject {
|
||||
IMPL_EVENT_TARGET_WITH_PARENT(Node, getParent)
|
||||
DECLARE_TARGET_EVENT_BEGIN(Node)
|
||||
TARGET_EVENT_ARG0(TouchStart)
|
||||
TARGET_EVENT_ARG0(TouchMove)
|
||||
TARGET_EVENT_ARG0(TouchEnd)
|
||||
TARGET_EVENT_ARG0(TouchCancel)
|
||||
TARGET_EVENT_ARG0(MouseDown)
|
||||
TARGET_EVENT_ARG0(MouseMove)
|
||||
TARGET_EVENT_ARG0(MouseUp)
|
||||
TARGET_EVENT_ARG0(MouseWheel)
|
||||
TARGET_EVENT_ARG0(MouseEnter)
|
||||
TARGET_EVENT_ARG0(MouseLeave)
|
||||
TARGET_EVENT_ARG0(KeyDown)
|
||||
TARGET_EVENT_ARG0(KeyUp)
|
||||
TARGET_EVENT_ARG0(DeviceMotion)
|
||||
TARGET_EVENT_ARG1(TransformChanged, TransformBit)
|
||||
TARGET_EVENT_ARG0(SceneChangedForPersist)
|
||||
TARGET_EVENT_ARG0(SizeChanged)
|
||||
TARGET_EVENT_ARG0(AnchorChanged)
|
||||
TARGET_EVENT_ARG0(ColorChanged)
|
||||
TARGET_EVENT_ARG1(ChildAdded, Node *)
|
||||
TARGET_EVENT_ARG1(ChildRemoved, Node *)
|
||||
TARGET_EVENT_ARG1(ParentChanged, Node *)
|
||||
TARGET_EVENT_ARG0(MobilityChanged)
|
||||
TARGET_EVENT_ARG1(LayerChanged, uint32_t)
|
||||
TARGET_EVENT_ARG0(SiblingOrderChanged)
|
||||
TARGET_EVENT_ARG1(SiblingIndexChanged, index_t)
|
||||
TARGET_EVENT_ARG0(ActiveInHierarchyChanged)
|
||||
TARGET_EVENT_ARG0(Reattach)
|
||||
TARGET_EVENT_ARG0(RemovePersistRootNode)
|
||||
TARGET_EVENT_ARG0(UITransformDirty)
|
||||
TARGET_EVENT_ARG1(ActiveNode, bool)
|
||||
TARGET_EVENT_ARG1(BatchCreated, bool)
|
||||
TARGET_EVENT_ARG1(SceneUpdated, cc::Scene *)
|
||||
TARGET_EVENT_ARG3(LocalPositionUpdated, float, float, float)
|
||||
TARGET_EVENT_ARG4(LocalRotationUpdated, float, float, float, float)
|
||||
TARGET_EVENT_ARG3(LocalScaleUpdated, float, float, float)
|
||||
TARGET_EVENT_ARG10(LocalRTSUpdated, float, float, float, float, float, float, float, float, float, float)
|
||||
TARGET_EVENT_ARG1(EditorAttached, bool)
|
||||
TARGET_EVENT_ARG0(LightProbeBakingChanged)
|
||||
DECLARE_TARGET_EVENT_END()
|
||||
public:
|
||||
class UserData : public RefCounted {
|
||||
public:
|
||||
~UserData() override = default;
|
||||
|
||||
protected:
|
||||
UserData() = default;
|
||||
};
|
||||
|
||||
using Super = CCObject;
|
||||
|
||||
static const uint32_t TRANSFORM_ON;
|
||||
|
||||
static Node *instantiate(Node *cloned, bool isSyncedNode);
|
||||
static void setScene(Node *);
|
||||
|
||||
/**
|
||||
* @en Finds a node by hierarchy path, the path is case-sensitive.
|
||||
* It will traverse the hierarchy by splitting the path using '/' character.
|
||||
* This function will still returns the node even if it is inactive.
|
||||
* It is recommended to not use this function every frame instead cache the result at startup.
|
||||
* @zh 通过路径从节点树中查找节点的方法,路径是大小写敏感的,并且通过 `/` 来分隔节点层级。
|
||||
* 即使节点的状态是未启用的也可以找到,建议将结果缓存,而不是每次需要都去查找。
|
||||
* @param path The path of the target node
|
||||
* @param referenceNode If given, the search will be limited in the sub node tree of the reference node
|
||||
*/
|
||||
// static Node *find(const ccstd::string &path, Node *referenceNode = nullptr);
|
||||
|
||||
/**
|
||||
* @en Determine whether the given object is a normal Node. Will return false if [[Scene]] given.
|
||||
* @zh 指定对象是否是普通的节点?如果传入 [[Scene]] 会返回 false。
|
||||
*/
|
||||
template <typename T>
|
||||
static bool isNode(T *obj);
|
||||
|
||||
static void resetChangedFlags();
|
||||
static void clearNodeArray();
|
||||
|
||||
Node();
|
||||
explicit Node(const ccstd::string &name);
|
||||
~Node() override;
|
||||
|
||||
virtual void onPostActivated(bool active) {}
|
||||
|
||||
void setParent(Node *parent, bool isKeepWorld = false);
|
||||
inline void modifyParent(Node *parent) { _parent = parent; }
|
||||
|
||||
inline Scene *getScene() const { return _scene; };
|
||||
|
||||
using WalkCallback = std::function<void(Node *)>;
|
||||
void walk(const WalkCallback &preFunc);
|
||||
void walk(const WalkCallback &preFunc, const WalkCallback &postFunc);
|
||||
|
||||
bool destroy() override {
|
||||
if (CCObject::destroy()) {
|
||||
setActive(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void destruct() override;
|
||||
|
||||
inline void destroyAllChildren() {
|
||||
for (const auto &child : _children) {
|
||||
child->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
inline void updateSiblingIndex() {
|
||||
index_t i = 0;
|
||||
for (const auto &child : _children) {
|
||||
child->_siblingIndex = i++;
|
||||
}
|
||||
emit<SiblingOrderChanged>();
|
||||
}
|
||||
|
||||
inline void addChild(Node *node) { node->setParent(this); }
|
||||
|
||||
inline void removeChild(Node *node) const {
|
||||
auto idx = getIdxOfChild(_children, node);
|
||||
if (idx != -1) {
|
||||
node->setParent(nullptr);
|
||||
}
|
||||
}
|
||||
inline void removeFromParent() {
|
||||
if (_parent) {
|
||||
_parent->removeChild(this);
|
||||
}
|
||||
}
|
||||
void removeAllChildren();
|
||||
|
||||
bool isChildOf(Node *parent) const;
|
||||
|
||||
void setActive(bool isActive);
|
||||
|
||||
void setSiblingIndex(index_t index);
|
||||
|
||||
inline bool isPersistNode() const {
|
||||
return static_cast<FlagBits>(_objFlags & Flags::DONT_DESTROY) > 0;
|
||||
}
|
||||
|
||||
inline void setPersistNode(bool val) {
|
||||
val ? _objFlags |= Flags::DONT_DESTROY : _objFlags &= ~Flags::DONT_DESTROY;
|
||||
}
|
||||
|
||||
inline const ccstd::string &getUuid() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
inline bool isActive() const { return _active != 0; }
|
||||
|
||||
inline bool isActiveInHierarchy() const { return _activeInHierarchy != 0; }
|
||||
inline void setActiveInHierarchy(bool v) {
|
||||
_activeInHierarchy = (v ? 1 : 0);
|
||||
}
|
||||
|
||||
inline const ccstd::vector<IntrusivePtr<Node>> &getChildren() const { return _children; }
|
||||
inline Node *getParent() const { return _parent; }
|
||||
// inline NodeEventProcessor *getEventProcessor() const { return _eventProcessor; }
|
||||
|
||||
Node *getChildByUuid(const ccstd::string &uuid) const;
|
||||
Node *getChildByName(const ccstd::string &name) const;
|
||||
Node *getChildByPath(const ccstd::string &path) const;
|
||||
inline index_t getSiblingIndex() const { return _siblingIndex; }
|
||||
inline UserData *getUserData() { return _userData.get(); }
|
||||
inline void setUserData(UserData *data) { _userData = data; }
|
||||
inline void insertChild(Node *child, index_t siblingIndex) {
|
||||
child->setParent(this);
|
||||
child->setSiblingIndex(siblingIndex);
|
||||
}
|
||||
|
||||
void invalidateChildren(TransformBit dirtyBit);
|
||||
|
||||
void translate(const Vec3 &, NodeSpace ns = NodeSpace::LOCAL);
|
||||
void rotate(const Quaternion &rot, NodeSpace ns = NodeSpace::LOCAL, bool calledFromJS = false);
|
||||
inline void rotateForJS(float x, float y, float z, float w, NodeSpace ns = NodeSpace::LOCAL) {
|
||||
rotate(Quaternion(x, y, z, w), ns, true);
|
||||
}
|
||||
void lookAt(const Vec3 &pos, const Vec3 &up = Vec3::UNIT_Y);
|
||||
|
||||
void pauseSystemEvents(bool recursive) {} // cjh TODO:
|
||||
void resumeSystemEvents(bool recursive) {} // cjh TODO:
|
||||
|
||||
ccstd::string getPathInHierarchy() const;
|
||||
// ===============================
|
||||
// transform
|
||||
// ===============================
|
||||
|
||||
/**
|
||||
* @en Set position in local coordinate system
|
||||
* @zh 设置本地坐标
|
||||
* @param position Target position
|
||||
*/
|
||||
inline void setPosition(const Vec3 &pos) { setPosition(pos.x, pos.y, pos.z); }
|
||||
inline void setPosition(float x, float y) { setPosition(x, y, _localPosition.z); }
|
||||
inline void setPosition(float x, float y, float z) { setPositionInternal(x, y, z, false); }
|
||||
inline void setPositionInternal(float x, float y, bool calledFromJS) { setPositionInternal(x, y, _localPosition.z, calledFromJS); }
|
||||
void setPositionInternal(float x, float y, float z, bool calledFromJS);
|
||||
// It is invoked after deserialization. It only sets position value, not triggers other logic.
|
||||
inline void setPositionForJS(float x, float y, float z) { _localPosition.set(x, y, z); }
|
||||
/**
|
||||
* @en Get position in local coordinate system, please try to pass `out` vector and reuse it to avoid garbage.
|
||||
* @zh 获取本地坐标,注意,尽可能传递复用的 [[Vec3]] 以避免产生垃圾。
|
||||
* @param out Set the result to out vector
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new vector will be generated and return
|
||||
*/
|
||||
inline const Vec3 &getPosition() const { return _localPosition; }
|
||||
|
||||
/**
|
||||
* @en Set rotation in local coordinate system with a quaternion representing the rotation
|
||||
* @zh 用四元数设置本地旋转
|
||||
* @param rotation Rotation in quaternion
|
||||
*/
|
||||
inline void setRotation(const Quaternion &rotation) { setRotation(rotation.x, rotation.y, rotation.z, rotation.w); }
|
||||
inline void setRotation(float x, float y, float z, float w) { setRotationInternal(x, y, z, w, false); }
|
||||
void setRotationInternal(float x, float y, float z, float w, bool calledFromJS);
|
||||
inline void setRotationForJS(float x, float y, float z, float w) { _localRotation.set(x, y, z, w); }
|
||||
|
||||
inline void setEulerAngles(const Vec3 &val) { setRotationFromEuler(val.x, val.y, val.z); }
|
||||
inline void setRotationFromEuler(const Vec3 &val) { setRotationFromEuler(val.x, val.y, val.z); }
|
||||
inline void setRotationFromEuler(float x, float y) { setRotationFromEuler(x, y, _euler.z); }
|
||||
void setRotationFromEuler(float x, float y, float z);
|
||||
inline void setRotationFromEulerForJS(float x, float y, float z) { _euler.set(x, y, z); }
|
||||
/**
|
||||
* @en Get rotation as quaternion in local coordinate system, please try to pass `out` quaternion and reuse it to avoid garbage.
|
||||
* @zh 获取本地旋转,注意,尽可能传递复用的 [[Quat]] 以避免产生垃圾。
|
||||
* @param out Set the result to out quaternion
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new quaternion will be generated and return
|
||||
*/
|
||||
inline const Quaternion &getRotation() const { return _localRotation; }
|
||||
|
||||
/**
|
||||
* @en Set scale in local coordinate system
|
||||
* @zh 设置本地缩放
|
||||
* @param scale Target scale
|
||||
*/
|
||||
inline void setScale(const Vec3 &scale) { setScale(scale.x, scale.y, scale.z); }
|
||||
inline void setScale(float x, float y) { setScale(x, y, _localScale.z); }
|
||||
inline void setScale(float x, float y, float z) { setScaleInternal(x, y, z, false); }
|
||||
inline void setScaleInternal(float x, float y, bool calledFromJS) { setScaleInternal(x, y, _localScale.z, calledFromJS); }
|
||||
void setScaleInternal(float x, float y, float z, bool calledFromJS);
|
||||
inline void setScaleForJS(float x, float y, float z) { _localScale.set(x, y, z); }
|
||||
/**
|
||||
* @en Get scale in local coordinate system, please try to pass `out` vector and reuse it to avoid garbage.
|
||||
* @zh 获取本地缩放,注意,尽可能传递复用的 [[Vec3]] 以避免产生垃圾。
|
||||
* @param out Set the result to out vector
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new vector will be generated and return
|
||||
*/
|
||||
inline const Vec3 &getScale() const { return _localScale; }
|
||||
|
||||
/**
|
||||
* @en Inversely transform a point from world coordinate system to local coordinate system.
|
||||
* @zh 逆向变换一个空间点,一般用于将世界坐标转换到本地坐标系中。
|
||||
* @param p A position in world coordinate system
|
||||
* @return The result point in local coordinate system will be stored in this vector
|
||||
*/
|
||||
Vec3 inverseTransformPoint(const Vec3 &p);
|
||||
|
||||
/**
|
||||
* @en Set position in world coordinate system
|
||||
* @zh 设置世界坐标
|
||||
* @param position Target position
|
||||
*/
|
||||
inline void setWorldPosition(const Vec3 &pos) { setWorldPosition(pos.x, pos.y, pos.z); }
|
||||
void setWorldPosition(float x, float y, float z);
|
||||
|
||||
/**
|
||||
* @en Get position in world coordinate system, please try to pass `out` vector and reuse it to avoid garbage.
|
||||
* @zh 获取世界坐标,注意,尽可能传递复用的 [[Vec3]] 以避免产生垃圾。
|
||||
* @param out Set the result to out vector
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new vector will be generated and return
|
||||
*/
|
||||
const Vec3 &getWorldPosition() const;
|
||||
|
||||
/**
|
||||
* @en Set rotation in world coordinate system with a quaternion representing the rotation
|
||||
* @zh 用四元数设置世界坐标系下的旋转
|
||||
* @param rotation Rotation in quaternion
|
||||
*/
|
||||
inline void setWorldRotation(const Quaternion &rotation) { setWorldRotation(rotation.x, rotation.y, rotation.z, rotation.w); }
|
||||
void setWorldRotation(float x, float y, float z, float w);
|
||||
/**
|
||||
* @en Get rotation as quaternion in world coordinate system, please try to pass `out` quaternion and reuse it to avoid garbage.
|
||||
* @zh 获取世界坐标系下的旋转,注意,尽可能传递复用的 [[Quat]] 以避免产生垃圾。
|
||||
* @param out Set the result to out quaternion
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new quaternion will be generated and return
|
||||
*/
|
||||
const Quaternion &getWorldRotation() const;
|
||||
|
||||
/**
|
||||
* @en Set rotation in world coordinate system with euler angles
|
||||
* @zh 用欧拉角设置世界坐标系下的旋转
|
||||
* @param x X axis rotation
|
||||
* @param y Y axis rotation
|
||||
* @param z Z axis rotation
|
||||
*/
|
||||
inline void setWorldScale(const Vec3 &scale) { setWorldScale(scale.x, scale.y, scale.z); }
|
||||
void setWorldScale(float x, float y, float z);
|
||||
|
||||
/**
|
||||
* @en Get scale in world coordinate system, please try to pass `out` vector and reuse it to avoid garbage.
|
||||
* @zh 获取世界缩放,注意,尽可能传递复用的 [[Vec3]] 以避免产生垃圾。
|
||||
* @param out Set the result to out vector
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new vector will be generated and return
|
||||
*/
|
||||
const Vec3 &getWorldScale() const;
|
||||
|
||||
void setWorldRotationFromEuler(float x, float y, float z);
|
||||
|
||||
/**
|
||||
* @en Local transformation matrix
|
||||
* @zh 本地坐标系变换矩阵
|
||||
*/
|
||||
void setMatrix(const Mat4 &val);
|
||||
|
||||
/**
|
||||
* @en Update the world transform information if outdated
|
||||
* @zh 更新节点的世界变换信息
|
||||
*/
|
||||
void updateWorldTransform();
|
||||
|
||||
/**
|
||||
* @en Get a world transform matrix
|
||||
* @zh 获取世界变换矩阵
|
||||
* @param out Set the result to out matrix
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new matrix will be generated and return
|
||||
*/
|
||||
const Mat4 &getWorldMatrix() const;
|
||||
|
||||
/**
|
||||
* @en Get a world transform matrix with only rotation and scale
|
||||
* @zh 获取只包含旋转和缩放的世界变换矩阵
|
||||
* @param out Set the result to out matrix
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new matrix will be generated and return
|
||||
*/
|
||||
Mat4 getWorldRS();
|
||||
|
||||
/**
|
||||
* @en Get a world transform matrix with only rotation and translation
|
||||
* @zh 获取只包含旋转和位移的世界变换矩阵
|
||||
* @param out Set the result to out matrix
|
||||
* @return If `out` given, the return value equals to `out`, otherwise a new matrix will be generated and return
|
||||
*/
|
||||
Mat4 getWorldRT();
|
||||
|
||||
/**
|
||||
* @en Set local transformation with rotation, position and scale separately.
|
||||
* @zh 一次性设置所有局部变换(平移、旋转、缩放)信息
|
||||
* @param rot The rotation
|
||||
* @param pos The position
|
||||
* @param scale The scale
|
||||
*/
|
||||
void setRTSInternal(Quaternion *rot, Vec3 *pos, Vec3 *scale, bool calledFromJS);
|
||||
inline void setRTS(Quaternion *rot, Vec3 *pos, Vec3 *scale) { setRTSInternal(rot, pos, scale, false); }
|
||||
|
||||
void setForward(const Vec3 &dir);
|
||||
|
||||
void setAngle(float);
|
||||
|
||||
inline const Vec3 &getEulerAngles() {
|
||||
if (_eulerDirty) {
|
||||
Quaternion::toEuler(_localRotation, false, &_euler);
|
||||
_eulerDirty = false;
|
||||
}
|
||||
return _euler;
|
||||
}
|
||||
|
||||
inline float getAngle() const {
|
||||
return _euler.z;
|
||||
}
|
||||
|
||||
inline Vec3 getForward() const {
|
||||
Vec3 forward{0, 0, -1};
|
||||
forward.transformQuat(getWorldRotation());
|
||||
return forward;
|
||||
}
|
||||
|
||||
inline Vec3 getUp() const {
|
||||
Vec3 up{0, 1, 0};
|
||||
up.transformQuat(getWorldRotation());
|
||||
return up;
|
||||
}
|
||||
|
||||
inline Vec3 getRight() const {
|
||||
Vec3 right{1, 0, 0};
|
||||
right.transformQuat(getWorldRotation());
|
||||
return right;
|
||||
}
|
||||
|
||||
inline bool isStatic() const {
|
||||
return _isStatic != 0;
|
||||
}
|
||||
|
||||
inline void setStatic(bool v) {
|
||||
_isStatic = v ? 1 : 0;
|
||||
}
|
||||
|
||||
inline MobilityMode getMobility() const {
|
||||
return _mobility;
|
||||
}
|
||||
|
||||
inline void setMobility(MobilityMode m) {
|
||||
_mobility = m;
|
||||
emit<MobilityChanged>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Whether the node's transformation have changed during the current frame.
|
||||
* @zh 这个节点的空间变换信息在当前帧内是否有变过?
|
||||
*/
|
||||
inline uint32_t getChangedFlags() const {
|
||||
return _hasChangedFlagsVersion == globalFlagChangeVersion ? _hasChangedFlags : 0;
|
||||
}
|
||||
inline void setChangedFlags(uint32_t value) {
|
||||
_hasChangedFlagsVersion = globalFlagChangeVersion;
|
||||
_hasChangedFlags = value;
|
||||
}
|
||||
/**
|
||||
* @zh 节点的变换改动版本号。
|
||||
* @en The transformation change version number of the node.
|
||||
*/
|
||||
inline uint32_t getFlagChangedVersion() const {
|
||||
return _hasChangedFlagsVersion;
|
||||
}
|
||||
|
||||
inline bool isTransformDirty() const { return _transformFlags != static_cast<uint32_t>(TransformBit::NONE); }
|
||||
inline void setLayer(uint32_t layer) {
|
||||
_layer = layer;
|
||||
emit<LayerChanged>(layer);
|
||||
}
|
||||
inline uint32_t getLayer() const { return _layer; }
|
||||
|
||||
// inline NodeUiProperties *getUIProps() const { return _uiProps.get(); }
|
||||
|
||||
// // ------------------ Component code start -----------------------------
|
||||
// // TODO(Lenovo):
|
||||
//
|
||||
// template <typename T, typename = std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// static Component *findComponent(Node * /*node*/) {
|
||||
// // cjh TODO:
|
||||
// CC_ABORT();
|
||||
// return nullptr;
|
||||
// }
|
||||
//
|
||||
// template <typename T, typename = std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// static Component *findComponents(Node * /*node*/, const ccstd::vector<Component *> & /*components*/) {
|
||||
// // cjh TODO:
|
||||
// CC_ABORT();
|
||||
// return nullptr;
|
||||
// }
|
||||
//
|
||||
// template <typename T, typename = std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// static Component *findChildComponent(const ccstd::vector<Node *> & /*children*/) {
|
||||
// // cjh TODO:
|
||||
// CC_ABORT();
|
||||
// return nullptr;
|
||||
// }
|
||||
//
|
||||
// template <typename T, typename = std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// static void findChildComponents(const ccstd::vector<Node *> & /*children*/, ccstd::vector<Component *> & /*components*/) {
|
||||
// // cjh TODO:
|
||||
// CC_ABORT();
|
||||
// }
|
||||
//
|
||||
// template <typename T, typename = std::enable_if_t<std::is_base_of_v<Component, T>, T>>
|
||||
// T *addComponent() {
|
||||
// T *comp = new T();
|
||||
// return static_cast<T *>(addComponent(comp));
|
||||
// }
|
||||
//
|
||||
// template <typename T, typename std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// void removeComponent() {
|
||||
// for (auto iter = _components.begin(); iter != _components.end(); ++iter) {
|
||||
// if (dynamic_cast<T *>(*iter) != nullptr) {
|
||||
// _components.erase(iter);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Component *addComponent(Component *comp);
|
||||
// void removeComponent(Component *comp);
|
||||
//
|
||||
// template <typename T, typename = std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// Component *getComponent() const {
|
||||
// for (auto *component : _components) {
|
||||
// if (dynamic_cast<T *>(component) != nullptr) {
|
||||
// return component;
|
||||
// }
|
||||
// }
|
||||
// return nullptr;
|
||||
// }
|
||||
//
|
||||
// // TODO(Lenovo):
|
||||
// template <typename T, typename std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// ccstd::vector<Component *> getComponents() const {
|
||||
// // cjh TODO:
|
||||
// CC_ABORT();
|
||||
// return {};
|
||||
// };
|
||||
//
|
||||
// template <typename T, typename std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// Component *getComponentInChildren(const T & /*comp*/) const {
|
||||
// // cjh TODO:
|
||||
// CC_ABORT();
|
||||
// return nullptr;
|
||||
// }
|
||||
//
|
||||
// template <typename T, typename std::enable_if_t<std::is_base_of<Component, T>::value>>
|
||||
// ccstd::vector<Component *> getComponentsInChildren() const {
|
||||
// // cjh TODO:
|
||||
// CC_ABORT();
|
||||
// return {};
|
||||
// }
|
||||
//
|
||||
// inline ccstd::vector<Component *> getComponents() const { return _components; }
|
||||
//
|
||||
// void checkMultipleComp(Component *comp) {}
|
||||
// ccstd::vector<Component *> _components;
|
||||
//
|
||||
// friend void componentCorrupted(Node *node, Component *comp, uint32_t index);
|
||||
// ------------------ Component code end -----------------------------
|
||||
|
||||
// For deserialization
|
||||
// void _setChild(index_t i, Node *child);
|
||||
// Node * _getChild(index_t i);
|
||||
// void _setChildrenSize(uint32_t size);
|
||||
// uint32_t _getChildrenSize();
|
||||
void _setChildren(ccstd::vector<IntrusivePtr<Node>> &&children); // NOLINT
|
||||
|
||||
inline se::Object *_getSharedArrayBufferObject() const { return _sharedMemoryActor.getSharedArrayBufferObject(); } // NOLINT
|
||||
|
||||
bool onPreDestroy() override;
|
||||
bool onPreDestroyBase();
|
||||
|
||||
// For deserialization
|
||||
ccstd::string _id;
|
||||
Node *_parent{nullptr};
|
||||
MobilityMode _mobility = MobilityMode::Static;
|
||||
|
||||
private:
|
||||
static index_t getIdxOfChild(const ccstd::vector<IntrusivePtr<Node>> &, Node *);
|
||||
|
||||
virtual void onBatchCreated(bool dontChildPrefab);
|
||||
virtual void updateScene();
|
||||
|
||||
void onSetParent(Node *oldParent, bool keepWorldTransform);
|
||||
void onHierarchyChanged(Node *);
|
||||
void onHierarchyChangedBase(Node *oldParent);
|
||||
|
||||
void inverseTransformPointRecursive(Vec3 &out) const;
|
||||
void updateWorldTransformRecursive(uint32_t &superDirtyBits);
|
||||
|
||||
inline void notifyLocalPositionUpdated() {
|
||||
emit<LocalPositionUpdated>(_localPosition.x, _localPosition.y, _localPosition.z);
|
||||
}
|
||||
|
||||
inline void notifyLocalRotationUpdated() {
|
||||
emit<LocalRotationUpdated>(_localRotation.x, _localRotation.y, _localRotation.z, _localRotation.w);
|
||||
}
|
||||
|
||||
inline void notifyLocalScaleUpdated() {
|
||||
emit<LocalScaleUpdated>(_localScale.x, _localScale.y, _localScale.z);
|
||||
}
|
||||
|
||||
inline void notifyLocalPositionRotationScaleUpdated() {
|
||||
emit<LocalRTSUpdated>(
|
||||
_localPosition.x, _localPosition.y, _localPosition.z,
|
||||
_localRotation.x, _localRotation.y, _localRotation.z, _localRotation.w,
|
||||
_localScale.x, _localScale.y, _localScale.z);
|
||||
}
|
||||
|
||||
#if CC_EDITOR
|
||||
inline void notifyEditorAttached(bool attached) {
|
||||
emit<EditorAttached>(attached);
|
||||
}
|
||||
#endif
|
||||
|
||||
// increase on every frame, used to identify the frame
|
||||
static uint32_t globalFlagChangeVersion;
|
||||
|
||||
static uint32_t clearFrame;
|
||||
static uint32_t clearRound;
|
||||
|
||||
Scene *_scene{nullptr};
|
||||
IntrusivePtr<UserData> _userData;
|
||||
|
||||
ccstd::vector<IntrusivePtr<Node>> _children;
|
||||
bindings::NativeMemorySharedToScriptActor _sharedMemoryActor;
|
||||
// local transform
|
||||
Vec3 _localPosition{Vec3::ZERO};
|
||||
Vec3 _localScale{Vec3::ONE};
|
||||
Quaternion _localRotation{Quaternion::identity()};
|
||||
Vec3 _euler{0, 0, 0};
|
||||
|
||||
// world transform
|
||||
Vec3 _worldPosition{Vec3::ZERO};
|
||||
Vec3 _worldScale{Vec3::ONE};
|
||||
Quaternion _worldRotation{Quaternion::identity()};
|
||||
Mat4 _worldMatrix{Mat4::IDENTITY};
|
||||
|
||||
// Shared memory with JS
|
||||
// NOTE: TypeArray created in node.jsb.ts _ctor should have the same memory layout
|
||||
uint32_t _eventMask{0}; // Uint32: 0
|
||||
uint32_t _layer{static_cast<uint32_t>(Layers::LayerList::DEFAULT)}; // Uint32: 1
|
||||
uint32_t _transformFlags{static_cast<uint32_t>(TransformBit::TRS)}; // Uint32: 2
|
||||
index_t _siblingIndex{0}; // Int32: 0
|
||||
uint8_t _activeInHierarchy{0}; // Uint8: 0
|
||||
uint8_t _active{1}; // Uint8: 1
|
||||
uint8_t _isStatic{0}; // Uint8: 2
|
||||
uint8_t _padding{0}; // Uint8: 3
|
||||
|
||||
/* set _hasChangedFlagsVersion to globalFlagChangeVersion when `_hasChangedFlags` updated.
|
||||
* `globalFlagChangeVersion == _hasChangedFlagsVersion` means that "_hasChangedFlags is dirty in current frametime".
|
||||
*/
|
||||
uint32_t _hasChangedFlagsVersion{0};
|
||||
uint32_t _hasChangedFlags{0};
|
||||
|
||||
bool _eulerDirty{false};
|
||||
|
||||
friend class NodeActivator;
|
||||
friend class Scene;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(Node);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool Node::isNode(T *obj) {
|
||||
return dynamic_cast<Node *>(obj) != nullptr && dynamic_cast<Scene *>(obj) == nullptr;
|
||||
}
|
||||
} // namespace cc
|
||||
23
cocos/core/scene-graph/NodeEnum.cpp
Normal file
23
cocos/core/scene-graph/NodeEnum.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/****************************************************************************
|
||||
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.
|
||||
****************************************************************************/
|
||||
69
cocos/core/scene-graph/NodeEnum.h
Normal file
69
cocos/core/scene-graph/NodeEnum.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
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
|
||||
|
||||
namespace cc {
|
||||
|
||||
enum class NodeSpace {
|
||||
LOCAL,
|
||||
WORLD
|
||||
};
|
||||
|
||||
enum class TransformBit : uint32_t {
|
||||
NONE = 0,
|
||||
POSITION = (1 << 0),
|
||||
ROTATION = (1 << 1),
|
||||
SCALE = (1 << 2),
|
||||
RS = ROTATION | SCALE,
|
||||
TRS = POSITION | ROTATION | SCALE,
|
||||
TRS_MASK = ~TRS,
|
||||
};
|
||||
CC_ENUM_BITWISE_OPERATORS(TransformBit);
|
||||
|
||||
/**
|
||||
* @en Node's mobility
|
||||
* @zh 节点的移动性
|
||||
*/
|
||||
enum class MobilityMode {
|
||||
/**
|
||||
* @en Static node
|
||||
* @zh 静态节点
|
||||
*/
|
||||
Static = 0,
|
||||
|
||||
/**
|
||||
* @en Stationary node
|
||||
* @zh 固定节点
|
||||
*/
|
||||
Stationary = 1,
|
||||
|
||||
/**
|
||||
* @en Movable node
|
||||
* @zh 可移动节点
|
||||
*/
|
||||
Movable = 2,
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
116
cocos/core/scene-graph/Scene.cpp
Normal file
116
cocos/core/scene-graph/Scene.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/****************************************************************************
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/scene-graph/Scene.h"
|
||||
#include "core/scene-graph/SceneGlobals.h"
|
||||
// #include "core/Director.h"
|
||||
#include "core/Root.h"
|
||||
//#include "core/scene-graph/NodeActivator.h"
|
||||
#include "engine/EngineEvents.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
Scene::Scene(const ccstd::string &name)
|
||||
: Node(name) {
|
||||
// _activeInHierarchy is initalized to 'false', so doesn't need to set it to false again
|
||||
// _activeInHierarchy = false;
|
||||
if (Root::getInstance() != nullptr) {
|
||||
_renderScene = Root::getInstance()->createScene({});
|
||||
}
|
||||
_globals = ccnew SceneGlobals();
|
||||
}
|
||||
|
||||
Scene::Scene() : Scene("") {}
|
||||
|
||||
Scene::~Scene() = default;
|
||||
|
||||
void Scene::setSceneGlobals(SceneGlobals *globals) { _globals = globals; }
|
||||
|
||||
void Scene::load() {
|
||||
events::SceneLoad::broadcast();
|
||||
if (!_inited) {
|
||||
//cjh if (TEST) {
|
||||
// CC_ASSERT(!_activeInHierarchy, 'Should deactivate ActionManager by default');
|
||||
// }
|
||||
// expandNestedPrefabInstanceNode(this); // TODO(xwx): expandNestedPrefabInstanceNode not implement yet
|
||||
// applyTargetOverrides(this); // TODO(xwx): applyTargetOverrides not implement yet
|
||||
//cjh _onBatchCreated is implemented in TS now, so comment the following line
|
||||
// onBatchCreated(false); //cjh EDITOR && _prefabSyncedInLiveReload);
|
||||
_inited = true;
|
||||
}
|
||||
_scene = this;
|
||||
// static method can't use this as parameter type
|
||||
walk(Node::setScene);
|
||||
}
|
||||
|
||||
void Scene::activate(bool active /* = true */) { // NOLINT(misc-unused-parameters)
|
||||
#if CC_EDITOR
|
||||
this->notifyEditorAttached(active);
|
||||
#endif
|
||||
//cjh
|
||||
// Director::getInstance()->getNodeActivator()->activateNode(this, active);
|
||||
// The test environment does not currently support the renderer
|
||||
// if (!TEST) {
|
||||
_globals->activate(this);
|
||||
if (_renderScene) {
|
||||
_renderScene->activate();
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void Scene::onBatchCreated(bool dontSyncChildPrefab) {
|
||||
// Moved from Node::onBatchCreated, Node::onBatchCreated only emits event to JS now.
|
||||
if (_parent) {
|
||||
index_t idx = getIdxOfChild(_parent->_children, this);
|
||||
if (idx != CC_INVALID_INDEX) {
|
||||
_siblingIndex = idx;
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
auto len = static_cast<int32_t>(_children.size());
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
_children[i]->setSiblingIndex(i);
|
||||
_children[i]->onBatchCreated(dontSyncChildPrefab);
|
||||
}
|
||||
}
|
||||
|
||||
bool Scene::destroy() {
|
||||
bool success = Super::destroy();
|
||||
if (success) {
|
||||
for (auto &child : _children) {
|
||||
child->setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (_renderScene != nullptr) {
|
||||
Root::getInstance()->destroyScene(_renderScene);
|
||||
}
|
||||
|
||||
_active = false;
|
||||
setActiveInHierarchy(false);
|
||||
return success;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
77
cocos/core/scene-graph/Scene.h
Normal file
77
cocos/core/scene-graph/Scene.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/****************************************************************************
|
||||
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 "core/scene-graph/Node.h"
|
||||
|
||||
namespace cc {
|
||||
class SceneGlobals;
|
||||
namespace scene {
|
||||
class RenderScene;
|
||||
}
|
||||
|
||||
class Scene final : public Node {
|
||||
public:
|
||||
using Super = Node;
|
||||
explicit Scene(const ccstd::string &name);
|
||||
Scene();
|
||||
~Scene() override;
|
||||
|
||||
inline scene::RenderScene *getRenderScene() const { return _renderScene; }
|
||||
inline SceneGlobals *getSceneGlobals() const { return _globals.get(); }
|
||||
void setSceneGlobals(SceneGlobals *globals);
|
||||
inline bool isAutoReleaseAssets() const { return _autoReleaseAssets; }
|
||||
inline void setAutoReleaseAssets(bool val) { _autoReleaseAssets = val; }
|
||||
|
||||
void load();
|
||||
void activate(bool active = true);
|
||||
|
||||
void onBatchCreated(bool dontSyncChildPrefab) override;
|
||||
bool destroy() override;
|
||||
|
||||
protected:
|
||||
void updateScene() override { _scene = this; }
|
||||
|
||||
IntrusivePtr<scene::RenderScene> _renderScene;
|
||||
/**
|
||||
* @en Per-scene level rendering info
|
||||
* @zh 场景级别的渲染信息
|
||||
*/
|
||||
// @serializable
|
||||
IntrusivePtr<SceneGlobals> _globals;
|
||||
bool _inited{false};
|
||||
|
||||
/**
|
||||
* @en Indicates whether all (directly or indirectly) static referenced assets of this scene are releasable by default after scene unloading.
|
||||
* @zh 指示该场景中直接或间接静态引用到的所有资源是否默认在场景切换后自动释放。
|
||||
*/
|
||||
// @serializable
|
||||
// @editable
|
||||
bool _autoReleaseAssets{false};
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(Scene);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
130
cocos/core/scene-graph/SceneGlobals.cpp
Normal file
130
cocos/core/scene-graph/SceneGlobals.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/****************************************************************************
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/scene-graph/SceneGlobals.h"
|
||||
#include "core/Root.h"
|
||||
#include "gi/light-probe/LightProbe.h"
|
||||
#include "renderer/pipeline/PipelineSceneData.h"
|
||||
#include "renderer/pipeline/custom/RenderInterfaceTypes.h"
|
||||
#include "scene/Ambient.h"
|
||||
#include "scene/Fog.h"
|
||||
#include "scene/Octree.h"
|
||||
#include "scene/Shadow.h"
|
||||
#include "scene/Skin.h"
|
||||
#include "scene/Skybox.h"
|
||||
#include "scene/PostSettings.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
SceneGlobals::SceneGlobals() {
|
||||
_ambientInfo = ccnew scene::AmbientInfo();
|
||||
_shadowInfo = ccnew scene::ShadowsInfo();
|
||||
_skyboxInfo = ccnew scene::SkyboxInfo();
|
||||
_fogInfo = ccnew scene::FogInfo();
|
||||
_octreeInfo = ccnew scene::OctreeInfo();
|
||||
_lightProbeInfo = ccnew gi::LightProbeInfo();
|
||||
_bakedWithStationaryMainLight = false;
|
||||
_bakedWithHighpLightmap = false;
|
||||
_skinInfo = ccnew scene::SkinInfo();
|
||||
_postSettingsInfo = ccnew scene::PostSettingsInfo();
|
||||
}
|
||||
|
||||
void SceneGlobals::activate(Scene *scene) {
|
||||
auto *sceneData = Root::getInstance()->getPipeline()->getPipelineSceneData();
|
||||
if (_ambientInfo != nullptr) {
|
||||
_ambientInfo->activate(sceneData->getAmbient());
|
||||
}
|
||||
|
||||
if (_skyboxInfo != nullptr) {
|
||||
_skyboxInfo->activate(sceneData->getSkybox());
|
||||
}
|
||||
|
||||
if (_shadowInfo != nullptr) {
|
||||
_shadowInfo->activate(sceneData->getShadows());
|
||||
}
|
||||
|
||||
if (_fogInfo != nullptr) {
|
||||
_fogInfo->activate(sceneData->getFog());
|
||||
}
|
||||
|
||||
if (_octreeInfo != nullptr) {
|
||||
_octreeInfo->activate(sceneData->getOctree());
|
||||
}
|
||||
|
||||
if (_lightProbeInfo != nullptr && sceneData->getLightProbes() != nullptr) {
|
||||
_lightProbeInfo->activate(scene, sceneData->getLightProbes());
|
||||
}
|
||||
|
||||
if (_skinInfo != nullptr && sceneData->getSkin()) {
|
||||
_skinInfo->activate(sceneData->getSkin());
|
||||
}
|
||||
|
||||
if (_postSettingsInfo != nullptr && sceneData->getPostSettings()) {
|
||||
_postSettingsInfo->activate(sceneData->getPostSettings());
|
||||
}
|
||||
|
||||
Root::getInstance()->onGlobalPipelineStateChanged();
|
||||
}
|
||||
|
||||
void SceneGlobals::setAmbientInfo(scene::AmbientInfo *info) {
|
||||
_ambientInfo = info;
|
||||
}
|
||||
|
||||
void SceneGlobals::setShadowsInfo(scene::ShadowsInfo *info) {
|
||||
_shadowInfo = info;
|
||||
}
|
||||
|
||||
void SceneGlobals::setSkyboxInfo(scene::SkyboxInfo *info) {
|
||||
_skyboxInfo = info;
|
||||
}
|
||||
|
||||
void SceneGlobals::setFogInfo(scene::FogInfo *info) {
|
||||
_fogInfo = info;
|
||||
}
|
||||
|
||||
void SceneGlobals::setOctreeInfo(scene::OctreeInfo *info) {
|
||||
_octreeInfo = info;
|
||||
}
|
||||
|
||||
void SceneGlobals::setLightProbeInfo(gi::LightProbeInfo *info) {
|
||||
_lightProbeInfo = info;
|
||||
}
|
||||
|
||||
void SceneGlobals::setBakedWithStationaryMainLight(bool value) {
|
||||
_bakedWithStationaryMainLight = value;
|
||||
}
|
||||
|
||||
void SceneGlobals::setBakedWithHighpLightmap(bool value) {
|
||||
_bakedWithHighpLightmap = value;
|
||||
}
|
||||
|
||||
void SceneGlobals::setSkinInfo(scene::SkinInfo *info) {
|
||||
_skinInfo = info;
|
||||
}
|
||||
|
||||
void SceneGlobals::setPostSettingsInfo(scene::PostSettingsInfo *info) {
|
||||
_postSettingsInfo = info;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
88
cocos/core/scene-graph/SceneGlobals.h
Normal file
88
cocos/core/scene-graph/SceneGlobals.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
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/Ptr.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
class Scene;
|
||||
namespace scene {
|
||||
class AmbientInfo;
|
||||
class ShadowsInfo;
|
||||
class SkyboxInfo;
|
||||
class FogInfo;
|
||||
class OctreeInfo;
|
||||
class SkinInfo;
|
||||
class PostSettingsInfo;
|
||||
} // namespace scene
|
||||
|
||||
namespace gi {
|
||||
class LightProbeInfo;
|
||||
}
|
||||
|
||||
class SceneGlobals : public RefCounted {
|
||||
public:
|
||||
SceneGlobals();
|
||||
~SceneGlobals() override = default;
|
||||
|
||||
void activate(Scene *scene);
|
||||
|
||||
inline scene::AmbientInfo *getAmbientInfo() const { return _ambientInfo.get(); }
|
||||
inline scene::ShadowsInfo *getShadowsInfo() const { return _shadowInfo.get(); }
|
||||
inline scene::SkyboxInfo *getSkyboxInfo() const { return _skyboxInfo.get(); }
|
||||
inline scene::FogInfo *getFogInfo() const { return _fogInfo.get(); }
|
||||
inline scene::OctreeInfo *getOctreeInfo() const { return _octreeInfo.get(); }
|
||||
inline gi::LightProbeInfo *getLightProbeInfo() const { return _lightProbeInfo.get(); }
|
||||
inline bool getBakedWithStationaryMainLight() const { return _bakedWithStationaryMainLight; }
|
||||
inline bool getBakedWithHighpLightmap() const { return _bakedWithHighpLightmap; }
|
||||
inline scene::SkinInfo *getSkinInfo() const { return _skinInfo.get(); }
|
||||
inline scene::PostSettingsInfo *getPostSettingsInfo() const { return _postSettingsInfo.get(); }
|
||||
|
||||
void setAmbientInfo(scene::AmbientInfo *info);
|
||||
void setShadowsInfo(scene::ShadowsInfo *info);
|
||||
void setSkyboxInfo(scene::SkyboxInfo *info);
|
||||
void setFogInfo(scene::FogInfo *info);
|
||||
void setOctreeInfo(scene::OctreeInfo *info);
|
||||
void setLightProbeInfo(gi::LightProbeInfo *info);
|
||||
void setBakedWithStationaryMainLight(bool value);
|
||||
void setBakedWithHighpLightmap(bool value);
|
||||
void setSkinInfo(scene::SkinInfo *info);
|
||||
void setPostSettingsInfo(scene::PostSettingsInfo *info);
|
||||
|
||||
private:
|
||||
IntrusivePtr<scene::AmbientInfo> _ambientInfo;
|
||||
IntrusivePtr<scene::ShadowsInfo> _shadowInfo;
|
||||
IntrusivePtr<scene::SkyboxInfo> _skyboxInfo;
|
||||
IntrusivePtr<scene::FogInfo> _fogInfo;
|
||||
IntrusivePtr<scene::OctreeInfo> _octreeInfo;
|
||||
IntrusivePtr<gi::LightProbeInfo> _lightProbeInfo;
|
||||
IntrusivePtr<scene::SkinInfo> _skinInfo;
|
||||
IntrusivePtr<scene::PostSettingsInfo> _postSettingsInfo;
|
||||
bool _bakedWithStationaryMainLight;
|
||||
bool _bakedWithHighpLightmap;
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
37
cocos/core/scene-graph/SceneGraphModuleHeader.h
Normal file
37
cocos/core/scene-graph/SceneGraphModuleHeader.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
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 "core/scene-graph/ComponentScheduler.h"
|
||||
//#include "core/scene-graph/Find.h"
|
||||
#include "core/scene-graph/Layers.h"
|
||||
#include "core/scene-graph/Node.h"
|
||||
//#include "core/scene-graph/NodeActivator.h"
|
||||
#include "core/scene-graph/NodeEnum.h"
|
||||
// #include "core/scene-graph/NodeEvent.h"
|
||||
// #include "core/scene-graph/NodeEventProcessor.h"
|
||||
//#include "core/scene-graph/NodeUIProperties.h"
|
||||
#include "core/scene-graph/Scene.h"
|
||||
#include "core/scene-graph/SceneGlobals.h"
|
||||
Reference in New Issue
Block a user