| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- #include "BsScriptComponent.h"
- #include "BsScriptGameObjectManager.h"
- #include "BsScriptObjectManager.h"
- #include "BsScriptAssemblyManager.h"
- #include "BsScriptMeta.h"
- #include "BsMonoField.h"
- #include "BsMonoClass.h"
- #include "BsMonoMethod.h"
- #include "BsMonoManager.h"
- #include "BsMonoUtil.h"
- #include "BsScriptSceneObject.h"
- #include "BsManagedComponent.h"
- #include "BsSceneObject.h"
- #include "BsMonoUtil.h"
- namespace BansheeEngine
- {
- ScriptComponent::ScriptComponent(MonoObject* instance)
- :ScriptObject(instance), mTypeMissing(false)
- {
- assert(instance != nullptr);
- MonoUtil::getClassName(instance, mNamespace, mType);
- }
- void ScriptComponent::initRuntimeData()
- {
- metaData.scriptClass->addInternalCall("Internal_AddComponent", &ScriptComponent::internal_addComponent);
- metaData.scriptClass->addInternalCall("Internal_GetComponent", &ScriptComponent::internal_getComponent);
- metaData.scriptClass->addInternalCall("Internal_GetComponents", &ScriptComponent::internal_getComponents);
- metaData.scriptClass->addInternalCall("Internal_RemoveComponent", &ScriptComponent::internal_removeComponent);
- metaData.scriptClass->addInternalCall("Internal_GetSceneObject", &ScriptComponent::internal_getSceneObject);
- }
- MonoObject* ScriptComponent::internal_addComponent(MonoObject* parentSceneObject, MonoReflectionType* type)
- {
- ScriptSceneObject* scriptSO = ScriptSceneObject::toNative(parentSceneObject);
- HSceneObject so = static_object_cast<SceneObject>(scriptSO->getNativeHandle());
- if (checkIfDestroyed(so))
- return nullptr;
- GameObjectHandle<ManagedComponent> mc = so->addComponent<ManagedComponent>(type);
- return mc->getManagedInstance();
- }
- MonoObject* ScriptComponent::internal_getComponent(MonoObject* parentSceneObject, MonoReflectionType* type)
- {
- ScriptSceneObject* scriptSO = ScriptSceneObject::toNative(parentSceneObject);
- HSceneObject so = static_object_cast<SceneObject>(scriptSO->getNativeHandle());
- if (checkIfDestroyed(so))
- return nullptr;
- const Vector<HComponent>& mComponents = so->getComponents();
- for(auto& component : mComponents)
- {
- if(component->getTypeId() == TID_ManagedComponent)
- {
- GameObjectHandle<ManagedComponent> managedComponent = static_object_cast<ManagedComponent>(component);
- if(managedComponent->getRuntimeType() == type)
- {
- return managedComponent->getManagedInstance();
- }
- }
- }
- return nullptr;
- }
- MonoArray* ScriptComponent::internal_getComponents(MonoObject* parentSceneObject)
- {
- ScriptSceneObject* scriptSO = ScriptSceneObject::toNative(parentSceneObject);
- HSceneObject so = static_object_cast<SceneObject>(scriptSO->getNativeHandle());
- Vector<MonoObject*> managedComponents;
- if (!checkIfDestroyed(so))
- {
- const Vector<HComponent>& mComponents = so->getComponents();
- for (auto& component : mComponents)
- {
- if (component->getTypeId() == TID_ManagedComponent)
- {
- GameObjectHandle<ManagedComponent> managedComponent = static_object_cast<ManagedComponent>(component);
- managedComponents.push_back(managedComponent->getManagedInstance());
- }
- }
- }
- MonoArray* componentArray = mono_array_new(MonoManager::instance().getDomain(),
- metaData.scriptClass->_getInternalClass(), (UINT32)managedComponents.size());
- for(UINT32 i = 0; i < (UINT32)managedComponents.size(); i++)
- {
- void* elemAddr = mono_array_addr_with_size(componentArray, sizeof(MonoObject*), i);
- memcpy(elemAddr, &managedComponents[i], sizeof(MonoObject*));
- }
- return componentArray;
- }
- void ScriptComponent::internal_removeComponent(MonoObject* parentSceneObject, MonoReflectionType* type)
- {
- ScriptSceneObject* scriptSO = ScriptSceneObject::toNative(parentSceneObject);
- HSceneObject so = static_object_cast<SceneObject>(scriptSO->getNativeHandle());
- if (checkIfDestroyed(so))
- return;
- // We only allow single component per type
- const Vector<HComponent>& mComponents = so->getComponents();
- for(auto& component : mComponents)
- {
- if(component->getTypeId() == TID_ManagedComponent)
- {
- GameObjectHandle<ManagedComponent> managedComponent = static_object_cast<ManagedComponent>(component);
- if(managedComponent->getRuntimeType() == type)
- {
- managedComponent->destroy();
- return;
- }
- }
- }
- LOGWRN("Attempting to remove a component that doesn't exists on SceneObject \"" + so->getName() + "\"");
- }
- MonoObject* ScriptComponent::internal_getSceneObject(ScriptComponent* nativeInstance)
- {
- if (checkIfDestroyed(nativeInstance->mManagedComponent))
- return nullptr;
- HSceneObject sceneObject = nativeInstance->mManagedComponent->sceneObject();
- ScriptSceneObject* scriptSO = ScriptGameObjectManager::instance().getScriptSceneObject(sceneObject);
- if (scriptSO == nullptr)
- scriptSO = ScriptGameObjectManager::instance().createScriptSceneObject(sceneObject);
- assert(scriptSO->getManagedInstance() != nullptr);
- return scriptSO->getManagedInstance();
- }
- bool ScriptComponent::checkIfDestroyed(const GameObjectHandleBase& handle)
- {
- if (handle.isDestroyed())
- {
- LOGWRN("Trying to access a destroyed GameObject with instance ID: " + handle.getInstanceId());
- return true;
- }
- return false;
- }
- MonoObject* ScriptComponent::_createManagedInstance(bool construct)
- {
- ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
- // See if this type even still exists
- if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(mNamespace, mType, currentObjInfo))
- {
- mTypeMissing = true;
- return ScriptAssemblyManager::instance().getMissingComponentClass()->createInstance(true);
- }
- mTypeMissing = false;
- return currentObjInfo->mMonoClass->createInstance(construct);
- }
- ScriptObjectBackup ScriptComponent::beginRefresh()
- {
- ScriptGameObjectBase::beginRefresh();
- ScriptObjectBackup backupData;
- // It's possible that managed component is destroyed but a reference to it
- // is still kept. Don't backup such components.
- if (!mManagedComponent.isDestroyed(true))
- backupData.data = mManagedComponent->backup(true);
- return backupData;
- }
- void ScriptComponent::endRefresh(const ScriptObjectBackup& backupData)
- {
- ComponentBackupData componentBackup = any_cast<ComponentBackupData>(backupData.data);
- mManagedComponent->restore(mManagedInstance, componentBackup, mTypeMissing);
- ScriptGameObjectBase::endRefresh(backupData);
- }
- void ScriptComponent::_onManagedInstanceDeleted()
- {
- mManagedInstance = nullptr;
- // It's possible that managed component is destroyed but a reference to it
- // is still kept during assembly refresh. Such components shouldn't be restored
- // so we delete them.
- if (!mRefreshInProgress || mManagedComponent.isDestroyed(true))
- ScriptGameObjectManager::instance().destroyScriptGameObject(this);
- }
- void ScriptComponent::setNativeHandle(const HGameObject& gameObject)
- {
- mManagedComponent = static_object_cast<ManagedComponent>(gameObject);
- }
- }
|