bool EditorUtility::calculateMeshBounds(const HSceneObject& object, AABox& bounds) { bounds = AABox(Vector3::ZERO, Vector3::ZERO); if (object.isDestroyed()) return false; bool foundOne = false; const Vector<HComponent>& components = object->getComponents(); for (auto& component : components) { Bounds curBounds; if (component->calculateBounds(curBounds)) { if (!foundOne) { bounds = curBounds.getBox(); foundOne = true; } else bounds.merge(curBounds.getBox()); } else { if (!foundOne) bounds = curBounds.getBox(); } } return foundOne; }
void GUIWidget::_updateTransform(const HSceneObject& parent) { // If the widgets parent scene object moved, we need to mark it as dirty // as the GUIManager batching relies on object positions, so it needs to be updated. const float diffEpsilon = 0.0001f; Vector3 position = parent->getWorldPosition(); Quaternion rotation = parent->getWorldRotation(); Vector3 scale = parent->getWorldScale(); if(!mWidgetIsDirty) { if(!Math::approxEquals(mPosition, position, diffEpsilon)) mWidgetIsDirty = true; else { if(!Math::approxEquals(mRotation, rotation, diffEpsilon)) mWidgetIsDirty = true; else { if(Math::approxEquals(mScale, scale)) mWidgetIsDirty = true; } } } mPosition = position; mRotation = rotation; mScale = scale; mTransform = parent->getWorldTfrm(); }
Vector<HBone> CAnimation::findChildBones() { Stack<HSceneObject> todo; todo.push(SO()); Vector<HBone> bones; while (todo.size() > 0) { HSceneObject currentSO = todo.top(); todo.pop(); HBone bone = currentSO->getComponent<CBone>(); if (bone != nullptr) { bone->_setParent(static_object_cast<CAnimation>(getHandle()), true); bones.push_back(bone); } int childCount = currentSO->getNumChildren(); for (int i = 0; i < childCount; i++) { HSceneObject child = currentSO->getChild(i); if (child->getComponent<CAnimation>() != nullptr) continue; todo.push(child); } } return bones; }
void PrefabUtility::clearPrefabIds(const HSceneObject& sceneObject, bool recursive) { Stack<HSceneObject> todo; todo.push(sceneObject); while (!todo.empty()) { HSceneObject currentSO = todo.top(); todo.pop(); for (auto& component : currentSO->mComponents) component->mLinkId = (UINT32)-1; if (recursive) { UINT32 numChildren = (UINT32)currentSO->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = currentSO->getChild(i); child->mLinkId = (UINT32)-1; if (child->mPrefabLinkUUID.empty()) todo.push(child); } } } }
void CCollider::updateParentRigidbody() { if (mIsTrigger) { setRigidbody(HRigidbody()); return; } HSceneObject currentSO = SO(); while (currentSO != nullptr) { HRigidbody parent = currentSO->getComponent<CRigidbody>(); if (parent != nullptr) { if(currentSO->getActive() && isValidParent(parent)) setRigidbody(parent); else setRigidbody(HRigidbody()); return; } currentSO = currentSO->getParent(); } // Not found setRigidbody(HRigidbody()); }
bool ScriptEditorUtility::internal_IsInternal(ScriptSceneObject* soPtr) { if (ScriptSceneObject::checkIfDestroyed(soPtr)) return false; HSceneObject so = soPtr->getHandle(); return so->hasFlag(SOF_Internal); }
void CAnimation::updateSceneObjectMapping() { Vector<SceneObjectMappingInfo> newMappingInfos; for(auto& entry : mMappingInfos) { if (entry.isMappedToBone) newMappingInfos.push_back(entry); else unmapSceneObject(entry.sceneObject); } if (mPrimaryPlayingClip.isLoaded()) { HSceneObject root = SO(); const auto& findMappings = [&](const String& name, AnimationCurveFlags flags) { if (flags.isSet(AnimationCurveFlag::ImportedCurve)) return; HSceneObject currentSO = root->findPath(name); bool found = false; for (UINT32 i = 0; i < (UINT32)newMappingInfos.size(); i++) { if (newMappingInfos[i].sceneObject == currentSO) { found = true; break; } } if (!found) { SceneObjectMappingInfo newMappingInfo; newMappingInfo.isMappedToBone = false; newMappingInfo.sceneObject = currentSO; newMappingInfos.push_back(newMappingInfo); mapCurveToSceneObject(name, currentSO); } }; SPtr<AnimationCurves> curves = mPrimaryPlayingClip->getCurves(); for(auto& curve : curves->position) findMappings(curve.name, curve.flags); for(auto& curve : curves->rotation) findMappings(curve.name, curve.flags); for(auto& curve : curves->scale) findMappings(curve.name, curve.flags); } mMappingInfos = newMappingInfos; }
void Light::_updateTransform(const HSceneObject& parent) { UINT32 curHash = parent->getTransformHash(); if (curHash != _getLastModifiedHash()) { setPosition(parent->getWorldPosition()); setRotation(parent->getWorldRotation()); _setLastModifiedHash(curHash); } }
PhysXRigidbody::PhysXRigidbody(PxPhysics* physx, PxScene* scene, const HSceneObject& linkedSO) :Rigidbody(linkedSO) { PxTransform tfrm = toPxTransform(linkedSO->getWorldPosition(), linkedSO->getWorldRotation()); mInternal = physx->createRigidDynamic(tfrm); mInternal->userData = this; scene->addActor(*mInternal); }
void CmdDeleteSO::recordSO(const HSceneObject& sceneObject) { MemorySerializer serializer; mSerializedObject = serializer.encode(mSceneObject.get(), mSerializedObjectSize); HSceneObject parent = mSceneObject->getParent(); if (parent != nullptr) mSerializedObjectParentId = parent->getInstanceId(); mSceneObjectProxy = CmdUtility::createProxy(mSceneObject); }
void ScriptPrefabUtility::internal_UpdateFromPrefab(ScriptSceneObject* soPtr) { if (ScriptSceneObject::checkIfDestroyed(soPtr)) return; HSceneObject so = soPtr->getNativeSceneObject(); HSceneObject prefabParent = so->getPrefabParent(); if(prefabParent != nullptr) PrefabUtility::updateFromPrefab(prefabParent); }
void PrefabUtility::recordInstanceData(const HSceneObject& so, SceneObjectProxy& output, UnorderedMap<UINT32, GameObjectInstanceDataPtr>& linkedInstanceData) { struct StackData { HSceneObject so; SceneObjectProxy* proxy; }; Stack<StackData> todo; todo.push({so, &output}); output.instanceData = so->_getInstanceData(); output.linkId = (UINT32)-1; while (!todo.empty()) { StackData curData = todo.top(); todo.pop(); const Vector<HComponent>& components = curData.so->getComponents(); for (auto& component : components) { curData.proxy->components.push_back(ComponentProxy()); ComponentProxy& componentProxy = curData.proxy->components.back(); componentProxy.instanceData = component->_getInstanceData(); componentProxy.linkId = component->getLinkId(); linkedInstanceData[componentProxy.linkId] = componentProxy.instanceData; } UINT32 numChildren = curData.so->getNumChildren(); curData.proxy->children.resize(numChildren); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = curData.so->getChild(i); SceneObjectProxy& childProxy = curData.proxy->children[i]; childProxy.instanceData = child->_getInstanceData(); childProxy.linkId = child->getLinkId(); linkedInstanceData[childProxy.linkId] = childProxy.instanceData; if (child->mPrefabLinkUUID.empty()) { todo.push({ child, &curData.proxy->children[i] }); } } } }
void Prefab::initialize(const HSceneObject& sceneObject) { sceneObject->mPrefabDiff = nullptr; UINT32 newNextLinkId = PrefabUtility::generatePrefabIds(sceneObject, mNextLinkId); if (newNextLinkId < mNextLinkId) { BS_EXCEPT(InternalErrorException, "Prefab ran out of IDs to assign. " \ "Consider increasing the size of the prefab ID data type."); } mNextLinkId = newNextLinkId; // If there are any child prefab instances, make sure to update their diffs so they are saved with this prefab Stack<HSceneObject> todo; todo.push(sceneObject); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); UINT32 childCount = current->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = current->getChild(i); if (!child->mPrefabLinkUUID.empty()) PrefabUtility::recordPrefabDiff(child); else todo.push(child); } } // Clone the hierarchy for internal storage mRoot = sceneObject->clone(false); mRoot->mParent = nullptr; // Remove objects with "dont save" flag todo.push(mRoot); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); if (current->hasFlag(SOF_DontSave)) current->destroy(); else { UINT32 numChildren = current->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) todo.push(current->getChild(i)); } } }
void ScriptLight::internal_updateTransform(ScriptLight* thisPtr, ScriptSceneObject* parent) { HSceneObject parentSO = parent->getNativeSceneObject(); if (!parentSO.isDestroyed()) { thisPtr->getInternal()->_updateTransform(parentSO); if (parentSO->getActive() != thisPtr->getInternal()->getIsActive()) { thisPtr->getInternal()->setIsActive(parentSO->getActive()); } } }
void ScriptGUIWidget::internal_UpdateTransform(ScriptGUIWidget* thisPtr, ScriptSceneObject* parent) { HSceneObject parentSO = parent->getNativeSceneObject(); SPtr<GUIWidget> widget = thisPtr->getInternal(); if (!parentSO.isDestroyed() && widget != nullptr) { widget->_updateTransform(parentSO); widget->_updateRT(); if (parentSO->getActive() != widget->getIsActive()) widget->setIsActive(parentSO->getActive()); } }
void CRigidbody::checkForNestedRigibody() { HSceneObject currentSO = SO()->getParent(); while(currentSO != nullptr) { if(currentSO->hasComponent<CRigidbody>()) { LOGWRN("Nested Rigidbodies detected. This will result in inconsistent transformations. To parent one " \ "Rigidbody to another move its colliders to the new parent, but remove the Rigidbody component."); return; } currentSO = currentSO->getParent(); } }
MonoObject* ScriptPrefabUtility::internal_getPrefabParent(ScriptSceneObject* nativeInstance) { if (ScriptSceneObject::checkIfDestroyed(nativeInstance)) return nullptr; HSceneObject so = nativeInstance->getNativeSceneObject(); HSceneObject parent = so->getPrefabParent(); if(parent != nullptr) { ScriptSceneObject* scriptParent = ScriptGameObjectManager::instance().getOrCreateScriptSceneObject(parent); return scriptParent->getManagedInstance(); } return nullptr; }
void Prefab::initialize(const HSceneObject& sceneObject) { sceneObject->mPrefabDiff = nullptr; PrefabUtility::generatePrefabIds(sceneObject); // If there are any child prefab instances, make sure to update their diffs so they are saved with this prefab Stack<HSceneObject> todo; todo.push(sceneObject); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); UINT32 childCount = current->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = current->getChild(i); if (!child->mPrefabLinkUUID.empty()) PrefabUtility::recordPrefabDiff(child); else todo.push(child); } } // Clone the hierarchy for internal storage if (mRoot != nullptr) mRoot->destroy(true); mRoot = sceneObject->clone(false); mRoot->mParent = nullptr; mRoot->mLinkId = -1; // Remove objects with "dont save" flag todo.push(mRoot); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); if (current->hasFlag(SOF_DontSave)) current->destroy(); else { UINT32 numChildren = current->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) todo.push(current->getChild(i)); } } }
void PrefabUtility::recordPrefabDiff(const HSceneObject& sceneObject) { HSceneObject topLevelObject = sceneObject; while (topLevelObject != nullptr) { if (!topLevelObject->mPrefabLinkUUID.empty()) break; if (topLevelObject->mParent != nullptr) topLevelObject = topLevelObject->mParent; else topLevelObject = nullptr; } if (topLevelObject == nullptr) topLevelObject = sceneObject; Stack<HSceneObject> todo; todo.push(topLevelObject); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); if (!current->mPrefabLinkUUID.empty()) { current->mPrefabDiff = nullptr; HPrefab prefabLink = static_resource_cast<Prefab>(gResources().loadFromUUID(current->mPrefabLinkUUID, false, false)); if (prefabLink.isLoaded(false)) current->mPrefabDiff = PrefabDiff::create(prefabLink->_getRoot(), current->getHandle()); } UINT32 childCount = current->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = current->getChild(i); todo.push(child); } } gResources().unloadAllUnused(); }
UINT32 PrefabUtility::generatePrefabIds(const HSceneObject& sceneObject, UINT32 startingId) { Stack<HSceneObject> todo; todo.push(sceneObject); while (!todo.empty()) { HSceneObject currentSO = todo.top(); todo.pop(); for (auto& component : currentSO->mComponents) { if (component->getLinkId() == (UINT32)-1) component->mLinkId = startingId++; } UINT32 numChildren = (UINT32)currentSO->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = currentSO->getChild(i); if (!child->hasFlag(SOF_DontSave)) { if (child->getLinkId() == (UINT32)-1) child->mLinkId = startingId++; if(child->mPrefabLinkUUID.empty()) todo.push(currentSO->getChild(i)); } } } return startingId; }
HSceneObject Prefab::instantiate() { if (mRoot == nullptr) return HSceneObject(); #if BS_IS_BANSHEE3D if (gCoreApplication().isEditor()) { // Update any child prefab instances in case their prefabs changed _updateChildInstances(); } #endif HSceneObject clone = _clone(); clone->_instantiate(); return clone; }
void CRigidbody::updateColliders() { Stack<HSceneObject> todo; todo.push(SO()); while(!todo.empty()) { HSceneObject currentSO = todo.top(); todo.pop(); if(currentSO->hasComponent<CCollider>()) { Vector<HCollider> colliders = currentSO->getComponents<CCollider>(); for (auto& entry : colliders) { if (!entry->isValidParent(mThisHandle)) continue; Collider* collider = entry->_getInternal(); if (collider == nullptr) continue; entry->setRigidbody(mThisHandle, true); mChildren.push_back(entry); collider->setRigidbody(mInternal.get()); mInternal->addCollider(collider->_getInternal()); } } UINT32 childCount = currentSO->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = currentSO->getChild(i); if (child->hasComponent<CRigidbody>()) continue; todo.push(child); } } }
void CmdRecordSO::revert() { if (mSceneObject == nullptr || mSceneObject.isDestroyed()) return; HSceneObject parent = mSceneObject->getParent(); UINT32 numChildren = mSceneObject->getNumChildren(); HSceneObject* children = nullptr; if (!mRecordHierarchy) { children = bs_stack_new<HSceneObject>(numChildren); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = mSceneObject->getChild(i); children[i] = child; child->setParent(HSceneObject()); } } mSceneObject->destroy(true); GameObjectManager::instance().setDeserializationMode(GODM_RestoreExternal | GODM_UseNewIds); MemorySerializer serializer; SPtr<SceneObject> restored = std::static_pointer_cast<SceneObject>(serializer.decode(mSerializedObject, mSerializedObjectSize)); EditorUtility::restoreIds(restored->getHandle(), mSceneObjectProxy); restored->setParent(parent); if (!mRecordHierarchy) { for (UINT32 i = 0; i < numChildren; i++) children[i]->setParent(restored->getHandle()); bs_stack_delete(children, numChildren); } restored->_instantiate(); }
void GUIGameObjectField::dataDropped(void* data) { DraggedSceneObjects* draggedSceneObjects = reinterpret_cast<DraggedSceneObjects*>(data); if (draggedSceneObjects->numObjects <= 0) return; MonoClass* sceneObjectClass = ScriptAssemblyManager::instance().getSceneObjectClass(); if (mType == sceneObjectClass->getFullName()) // A scene object { setValue(draggedSceneObjects->objects[0], true); } else // A component { for (UINT32 i = 0; i < draggedSceneObjects->numObjects; i++) { HSceneObject so = draggedSceneObjects->objects[i]; const Vector<HComponent>& components = so->getComponents(); for (auto& component : components) { if (component->getTypeId() == TID_ManagedComponent) // We only care about managed components { HManagedComponent managedComponent = static_object_cast<ManagedComponent>(component); MonoClass* acceptedClass = MonoManager::instance().findClass(mNamespace, mType); MonoClass* providedClass = MonoManager::instance().findClass(managedComponent->getManagedNamespace(), managedComponent->getManagedTypeName()); if (acceptedClass != nullptr && providedClass != nullptr) { if (providedClass->isSubClassOf(acceptedClass)) { setValue(managedComponent, true); } } } } } } }
void CBone::updateParentAnimation() { HSceneObject currentSO = SO(); while (currentSO != nullptr) { HAnimation parent = currentSO->getComponent<CAnimation>(); if (parent != nullptr) { if (currentSO->getActive()) _setParent(parent); else _setParent(HAnimation()); return; } currentSO = currentSO->getParent(); } _setParent(HAnimation()); }
ScriptSerializedSceneObject::ScriptSerializedSceneObject(MonoObject* instance, const HSceneObject& so, bool recordHierarchy) : ScriptObject(instance), mSO(so), mRecordHierarchy(recordHierarchy), mSerializedObject(nullptr), mSerializedObjectSize(0) { if (mSO.isDestroyed()) return; UINT32 numChildren = mSO->getNumChildren(); HSceneObject* children = nullptr; if (!mRecordHierarchy) { children = bs_stack_new<HSceneObject>(numChildren); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = mSO->getChild(i); children[i] = child; child->setParent(HSceneObject()); } } bool isInstantiated = !mSO->hasFlag(SOF_DontInstantiate); mSO->_setFlags(SOF_DontInstantiate); MemorySerializer serializer; mSerializedObject = serializer.encode(mSO.get(), mSerializedObjectSize); if (isInstantiated) mSO->_unsetFlags(SOF_DontInstantiate); mSceneObjectProxy = EditorUtility::createProxy(mSO); if (!mRecordHierarchy) { for (UINT32 i = 0; i < numChildren; i++) children[i]->setParent(mSO->getHandle()); bs_stack_delete(children, numChildren); } }
void Prefab::_updateChildInstances() { Stack<HSceneObject> todo; todo.push(mRoot); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); UINT32 childCount = current->getNumChildren(); for (UINT32 i = 0; i < childCount; i++) { HSceneObject child = current->getChild(i); if (!child->mPrefabLinkUUID.empty()) PrefabUtility::updateFromPrefab(child); else todo.push(child); } } }
void PrefabUtility::revertToPrefab(const HSceneObject& so) { String prefabLinkUUID = so->getPrefabLink(); HPrefab prefabLink = static_resource_cast<Prefab>(gResources().loadFromUUID(prefabLinkUUID, false, false)); if (prefabLink == nullptr) return; // Save IDs, destroy original, create new, restore IDs SceneObjectProxy soProxy; UnorderedMap<UINT32, GameObjectInstanceDataPtr> linkedInstanceData; recordInstanceData(so, soProxy, linkedInstanceData); HSceneObject parent = so->getParent(); // This will destroy the object but keep it in the parent's child list HSceneObject currentSO = so; so->destroyInternal(currentSO, true); HSceneObject newInstance = prefabLink->instantiate(); newInstance->mParent = parent; restoreLinkedInstanceData(newInstance, soProxy, linkedInstanceData); }
void CmdRecordSO::recordSO(const HSceneObject& sceneObject) { UINT32 numChildren = mSceneObject->getNumChildren(); HSceneObject* children = nullptr; if (!mRecordHierarchy) { children = bs_stack_new<HSceneObject>(numChildren); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = mSceneObject->getChild(i); children[i] = child; child->setParent(HSceneObject()); } } bool isInstantiated = !mSceneObject->hasFlag(SOF_DontInstantiate); mSceneObject->_setFlags(SOF_DontInstantiate); MemorySerializer serializer; mSerializedObject = serializer.encode(mSceneObject.get(), mSerializedObjectSize); if (isInstantiated) mSceneObject->_unsetFlags(SOF_DontInstantiate); mSceneObjectProxy = EditorUtility::createProxy(mSceneObject); if (!mRecordHierarchy) { for (UINT32 i = 0; i < numChildren; i++) children[i]->setParent(sceneObject->getHandle()); bs_stack_delete(children, numChildren); } }
void PrefabUtility::restoreLinkedInstanceData(const HSceneObject& so, SceneObjectProxy& proxy, UnorderedMap<UINT32, GameObjectInstanceDataPtr>& linkedInstanceData) { Stack<HSceneObject> todo; todo.push(so); // Root is not in the instance data map because its link ID belongs to the parent prefab, if any so->_setInstanceData(proxy.instanceData); while (!todo.empty()) { HSceneObject current = todo.top(); todo.pop(); Vector<HComponent>& components = current->mComponents; for (auto& component : components) { if (component->getLinkId() != (UINT32)-1) { auto iterFind = linkedInstanceData.find(component->getLinkId()); if (iterFind != linkedInstanceData.end()) { component->_setInstanceData(iterFind->second); component._setHandleData(component.getInternalPtr()); } } } UINT32 numChildren = current->getNumChildren(); for (UINT32 i = 0; i < numChildren; i++) { HSceneObject child = current->getChild(i); if (child->getLinkId() != (UINT32)-1) { auto iterFind = linkedInstanceData.find(child->getLinkId()); if (iterFind != linkedInstanceData.end()) child->_setInstanceData(iterFind->second); } if (child->mPrefabLinkUUID.empty()) todo.push(child); } } }