Browse Source

Getting the new component system to work

BearishSun 8 years ago
parent
commit
01946d1a00

+ 3 - 3
Source/BansheeCore/Include/BsComponent.h

@@ -147,10 +147,10 @@ namespace bs
 		bool hasFlag(ComponentFlag flag) const { return mFlags.isSet(flag); }
 
 		/** Sets an index that uniquely identifies a component with the SceneManager. */
-		void setSceneManagerIdx(UINT32 idx) { mSceneManagerIdx = idx; }
+		void setSceneManagerId(UINT32 id) { mSceneManagerId = id; }
 
 		/** Returns an index that unique identifies a component with the SceneManager. */
-		UINT32 getSceneManagerIdx() const { return mSceneManagerIdx; }
+		UINT32 getSceneManagerId() const { return mSceneManagerId; }
 
 		/**
 		 * Destroys this component.
@@ -169,7 +169,7 @@ namespace bs
 		HComponent mThisHandle;
 		TransformChangedFlags mNotifyFlags;
 		ComponentFlags mFlags;
-		UINT32 mSceneManagerIdx;
+		UINT32 mSceneManagerId;
 
 	private:
 		HSceneObject mParent;

+ 12 - 0
Source/BansheeCore/Include/BsSceneManager.h

@@ -176,6 +176,18 @@ namespace bs
 		/** Removes a component from the inactive component list. */
 		void removeFromInactiveList(const HComponent& component);
 
+		/** Removes a component from the uninitialized component list. */
+		void removeFromUninitializedList(const HComponent& component);
+
+		/** 
+		 * Encodes an index and a type into a single 32-bit integer. Top 2 bits represent the type, while the rest represent
+		 * the index.
+		 */
+		UINT32 encodeComponentId(UINT32 idx, UINT32 type);
+
+		/** Decodes an id encoded with encodeComponentId(). */
+		void decodeComponentId(UINT32 id, UINT32& idx, UINT32& type);
+
 	protected:
 		HSceneObject mRootNode;
 

+ 1 - 0
Source/BansheeCore/Source/BsCCamera.cpp

@@ -10,6 +10,7 @@ namespace bs
 	CCamera::CCamera(const HSceneObject& parent, SPtr<RenderTarget> target, float left, float top, float width, float height)
 		: Component(parent), mTarget(target), mLeft(left), mTop(top), mWidth(width), mHeight(height)
     {
+		Component::setFlag(ComponentFlag::AlwaysRun, true);
 		setName("Camera");
     }
 

+ 1 - 0
Source/BansheeCore/Source/BsCLight.cpp

@@ -11,6 +11,7 @@ namespace bs
 		: Component(parent), mType(type), mColor(color), mIntensity(intensity), mRange(range),
 		mCastsShadows(castsShadows), mSpotAngle(spotAngle), mSpotFalloffAngle(spotFalloffAngle)
 	{
+		setFlag(ComponentFlag::AlwaysRun, true);
 		setName("Light");
 	}
 

+ 2 - 2
Source/BansheeCore/Source/BsComponent.cpp

@@ -7,11 +7,11 @@
 namespace bs
 {
 	Component::Component()
-		:mNotifyFlags(TCF_None), mSceneManagerIdx(-1)
+		:mNotifyFlags(TCF_None), mSceneManagerId(-1)
 	{ }
 
 	Component::Component(const HSceneObject& parent)
-		:mNotifyFlags(TCF_None), mParent(parent), mSceneManagerIdx(-1)
+		:mNotifyFlags(TCF_None), mParent(parent), mSceneManagerId(-1)
 	{
 		setName("Component");
 	}

+ 90 - 25
Source/BansheeCore/Source/BsSceneManager.cpp

@@ -12,6 +12,13 @@
 
 namespace bs
 {
+	enum ListType
+	{
+		ActiveList = 0,
+		InactiveList = 1,
+		UninitializedList = 2
+	};
+
 	SceneManager::SceneManager()
 	{
 		mRootNode = SceneObject::createInternal("SceneRoot");
@@ -259,14 +266,14 @@ namespace bs
 						UINT32 idx = (UINT32)mActiveComponents.size();
 						mActiveComponents.push_back(entry);
 
-						entry->setSceneManagerIdx(idx);
+						entry->setSceneManagerId(encodeComponentId(idx, ActiveList));
 					}
 					else
 					{
 						UINT32 idx = (UINT32)mInactiveComponents.size();
 						mInactiveComponents.push_back(entry);
 
-						entry->setSceneManagerIdx(idx);
+						entry->setSceneManagerId(encodeComponentId(idx, InactiveList));
 					}
 				}
 
@@ -290,7 +297,7 @@ namespace bs
 				UINT32 activeIdx = (UINT32)mActiveComponents.size();
 				mActiveComponents.push_back(component);
 
-				component->setSceneManagerIdx(activeIdx);
+				component->setSceneManagerId(encodeComponentId(activeIdx, ActiveList));
 			}
 		}
 		// Stop updates on all active components
@@ -326,7 +333,7 @@ namespace bs
 				UINT32 inactiveIdx = (UINT32)mInactiveComponents.size();
 				mInactiveComponents.push_back(component);
 
-				component->setSceneManagerIdx(inactiveIdx);
+				component->setSceneManagerId(encodeComponentId(inactiveIdx, InactiveList));
 			}
 		}
 
@@ -349,19 +356,22 @@ namespace bs
 				UINT32 idx = (UINT32)mActiveComponents.size();
 				mActiveComponents.push_back(component);
 
-				component->setSceneManagerIdx(idx);
+				component->setSceneManagerId(encodeComponentId(idx, ActiveList));
 			}
 			else
 			{
 				UINT32 idx = (UINT32)mInactiveComponents.size();
 				mInactiveComponents.push_back(component);
 
-				component->setSceneManagerIdx(idx);
+				component->setSceneManagerId(encodeComponentId(idx, InactiveList));
 			}
 		}
 		else // Stopped
 		{
+			UINT32 idx = (UINT32)mUnintializedComponents.size();
 			mUnintializedComponents.push_back(component);
+
+			component->setSceneManagerId(encodeComponentId(idx, UninitializedList));
 		}
 	}
 
@@ -379,7 +389,7 @@ namespace bs
 			UINT32 activeIdx = (UINT32)mActiveComponents.size();
 			mActiveComponents.push_back(component);
 
-			component->setSceneManagerIdx(activeIdx);
+			component->setSceneManagerId(encodeComponentId(activeIdx, ActiveList));
 		}
 	}
 
@@ -397,20 +407,34 @@ namespace bs
 			UINT32 inactiveIdx = (UINT32)mInactiveComponents.size();
 			mInactiveComponents.push_back(component);
 
-			component->setSceneManagerIdx(inactiveIdx);
+			component->setSceneManagerId(encodeComponentId(inactiveIdx, InactiveList));
 		}
 	}
 
 	void SceneManager::_notifyComponentDestroyed(const HComponent& component)
 	{
-		bool alwaysRun = component->hasFlag(ComponentFlag::AlwaysRun);
-		bool isActive = component->sceneObject()->getActive() && (alwaysRun || mComponentState == ComponentState::Running);
-		bool isEnabled = component->sceneObject()->getActive() && (alwaysRun || mComponentState != ComponentState::Stopped);
+		UINT32 listType;
+		UINT32 idx;
+		decodeComponentId(component->getSceneManagerId(), idx, listType);
 
-		if (isActive)
+		switch(listType)
+		{
+		case ActiveList:
 			removeFromActiveList(component);
-		else
+			break;
+		case InactiveList:
 			removeFromInactiveList(component);
+			break;
+		case UninitializedList:
+			removeFromUninitializedList(component);
+			break;
+		default:
+			assert(false);
+			break;
+		}
+
+		bool alwaysRun = component->hasFlag(ComponentFlag::AlwaysRun);
+		bool isEnabled = component->sceneObject()->getActive() && (alwaysRun || mComponentState != ComponentState::Stopped);
 
 		if (isEnabled)
 			component->onDisabled();
@@ -420,15 +444,19 @@ namespace bs
 
 	void SceneManager::removeFromActiveList(const HComponent& component)
 	{
-		UINT32 activeIdx = component->getSceneManagerIdx();
-		UINT32 lastActiveIdx = mActiveComponents.back()->getSceneManagerIdx();
+		UINT32 listType;
+		UINT32 idx;
+		decodeComponentId(component->getSceneManagerId(), idx, listType);
+
+		UINT32 lastIdx;
+		decodeComponentId(mActiveComponents.back()->getSceneManagerId(), lastIdx, listType);
 
-		assert(mActiveComponents[activeIdx] == component);
+		assert(mActiveComponents[idx] == component);
 
-		if (activeIdx != lastActiveIdx)
+		if (idx != lastIdx)
 		{
-			std::swap(mActiveComponents[activeIdx], mActiveComponents[lastActiveIdx]);
-			mActiveComponents[activeIdx]->setSceneManagerIdx(activeIdx);
+			std::swap(mActiveComponents[idx], mActiveComponents[lastIdx]);
+			mActiveComponents[idx]->setSceneManagerId(encodeComponentId(idx, ActiveList));
 		}
 
 		mActiveComponents.erase(mActiveComponents.end() - 1);
@@ -436,20 +464,57 @@ namespace bs
 
 	void SceneManager::removeFromInactiveList(const HComponent& component)
 	{
-		UINT32 inactiveIdx = component->getSceneManagerIdx();
-		UINT32 lastInactiveIdx = mInactiveComponents.back()->getSceneManagerIdx();
+		UINT32 listType;
+		UINT32 idx;
+		decodeComponentId(component->getSceneManagerId(), idx, listType);
 
-		assert(mInactiveComponents[inactiveIdx] == component);
+		UINT32 lastIdx;
+		decodeComponentId(mInactiveComponents.back()->getSceneManagerId(), lastIdx, listType);
 
-		if (inactiveIdx != lastInactiveIdx)
+		assert(mInactiveComponents[idx] == component);
+
+		if (idx != lastIdx)
 		{
-			std::swap(mInactiveComponents[inactiveIdx], mInactiveComponents[lastInactiveIdx]);
-			mInactiveComponents[inactiveIdx]->setSceneManagerIdx(inactiveIdx);
+			std::swap(mInactiveComponents[idx], mInactiveComponents[lastIdx]);
+			mInactiveComponents[idx]->setSceneManagerId(encodeComponentId(idx, InactiveList));
 		}
 
 		mInactiveComponents.erase(mInactiveComponents.end() - 1);
 	}
 
+	void SceneManager::removeFromUninitializedList(const HComponent& component)
+	{
+		UINT32 listType;
+		UINT32 idx;
+		decodeComponentId(component->getSceneManagerId(), idx, listType);
+
+		UINT32 lastIdx;
+		decodeComponentId(mUnintializedComponents.back()->getSceneManagerId(), lastIdx, listType);
+
+		assert(mUnintializedComponents[idx] == component);
+
+		if (idx != lastIdx)
+		{
+			std::swap(mUnintializedComponents[idx], mUnintializedComponents[lastIdx]);
+			mUnintializedComponents[idx]->setSceneManagerId(encodeComponentId(idx, UninitializedList));
+		}
+
+		mUnintializedComponents.erase(mUnintializedComponents.end() - 1);
+	}
+
+	UINT32 SceneManager::encodeComponentId(UINT32 idx, UINT32 type)
+	{
+		assert(idx <= (0x3FFFFFFF));
+
+		return (type << 30) | idx;
+	}
+
+	void SceneManager::decodeComponentId(UINT32 id, UINT32& idx, UINT32& type)
+	{
+		idx = id & 0x3FFFFFFF;
+		type = id >> 30;
+	}
+
 	void SceneManager::_update()
 	{
 		// Note: Eventually perform updates based on component types and/or on component priority. Right now we just

+ 2 - 0
Source/BansheeEngine/Source/BsCGUIWidget.cpp

@@ -11,6 +11,8 @@ namespace bs
 	CGUIWidget::CGUIWidget(const HSceneObject& parent, const SPtr<Camera>& camera)
 		:Component(parent), mCamera(camera), mParentHash((UINT32)-1)
 	{
+		setFlag(ComponentFlag::AlwaysRun, true);
+
 		mInternal = GUIWidget::create(camera);
 		mOwnerTargetResizedConn = mInternal->onOwnerTargetResized.connect(
 			std::bind(&CGUIWidget::ownerTargetResized, this));

+ 1 - 0
Source/BansheeEngine/Source/BsProfilerOverlay.cpp

@@ -294,6 +294,7 @@ namespace bs
 	ProfilerOverlay::ProfilerOverlay(const HSceneObject& parent, const SPtr<Camera>& target)
 		:Component(parent), mInternal(nullptr)
 	{
+		setFlag(ComponentFlag::AlwaysRun, true);
 		mInternal = bs_new<ProfilerOverlayInternal>(target);
 	}
 

+ 0 - 10
Source/SBansheeEngine/Include/BsManagedComponent.h

@@ -41,9 +41,6 @@ namespace bs
 		/**	Returns namespace and type name of the component in format "namespace.typename". */
 		const String& getManagedFullTypeName() const { return mFullTypeName; }
 
-		/** Returns true if the component is allowed to run when the game is not playing .*/
-		bool runInEditor() const { return mRunInEditor; }
-
 		/**
 		 * Serializes the internal managed component.
 		 *
@@ -67,15 +64,9 @@ namespace bs
 		 */
 		void restore(MonoObject* instance, const ComponentBackupData& data, bool missingType);
 
-		/**	Triggers the managed OnInitialize callback. */
-		void triggerOnInitialize();
-
 		/**	Triggers the managed OnReset callback. */
 		void triggerOnReset();
 
-		/**	Triggers the managed OnEnable callback. */
-		void triggerOnEnable();
-
 	private:
 		/**
 		 * Finalizes construction of the object. Must be called before use or when the managed component instance changes.
@@ -101,7 +92,6 @@ namespace bs
 		String mNamespace;
 		String mTypeName;
 		String mFullTypeName;
-		bool mRunInEditor;
 		bool mRequiresReset;
 
 		bool mMissingType;

+ 0 - 6
Source/SBansheeEngine/Include/BsScriptGameObjectManager.h

@@ -97,12 +97,6 @@ namespace bs
 		/**	Destroys and unregisters the specified ManagedComponent interop object. */
 		void destroyScriptComponent(ScriptComponentBase* component);
 
-		/** 
-		 * Sends OnInitialize/OnEnable events to all components that run only while the game is playing (ones without 
-		 * RunInEditor attribute). 
-		 */
-		void wakeRuntimeComponents();
-
 	private:
 		/**
 		 * Triggers OnReset methods on all registered managed components.

+ 20 - 44
Source/SBansheeEngine/Source/BsManagedComponent.cpp

@@ -17,7 +17,7 @@
 namespace bs
 {
 	ManagedComponent::ManagedComponent()
-		: mManagedInstance(nullptr), mManagedClass(nullptr), mRuntimeType(nullptr), mManagedHandle(0), mRunInEditor(false)
+		: mManagedInstance(nullptr), mManagedClass(nullptr), mRuntimeType(nullptr), mManagedHandle(0)
 		, mRequiresReset(true), mMissingType(false), mOnCreatedThunk(nullptr), mOnInitializedThunk(nullptr)
 		, mOnUpdateThunk(nullptr), mOnResetThunk(nullptr), mOnDestroyThunk(nullptr), mOnDisabledThunk(nullptr)
 		, mOnEnabledThunk(nullptr), mOnTransformChangedThunk(nullptr), mCalculateBoundsMethod(nullptr)
@@ -25,7 +25,7 @@ namespace bs
 
 	ManagedComponent::ManagedComponent(const HSceneObject& parent, MonoReflectionType* runtimeType)
 		: Component(parent), mManagedInstance(nullptr), mManagedClass(nullptr), mRuntimeType(runtimeType)
-		, mManagedHandle(0), mRunInEditor(false), mRequiresReset(true), mMissingType(false), mOnCreatedThunk(nullptr)
+		, mManagedHandle(0), mRequiresReset(true), mMissingType(false), mOnCreatedThunk(nullptr)
 		, mOnInitializedThunk(nullptr), mOnUpdateThunk(nullptr), mOnResetThunk(nullptr), mOnDestroyThunk(nullptr)
 		, mOnDisabledThunk(nullptr), mOnEnabledThunk(nullptr), mOnTransformChangedThunk(nullptr)
 		, mCalculateBoundsMethod(nullptr)
@@ -236,10 +236,10 @@ namespace bs
 			if (runInEditorAttrib == nullptr)
 				BS_EXCEPT(InvalidStateException, "Cannot find RunInEditor managed class.");
 
-			mRunInEditor = mManagedClass->getAttribute(runInEditorAttrib) != nullptr;
+			bool runInEditor = mManagedClass->getAttribute(runInEditorAttrib) != nullptr;
+			if (runInEditor)
+				setFlag(ComponentFlag::AlwaysRun, true);
 		}
-		else
-			mRunInEditor = false;
 	}
 
 	bool ManagedComponent::typeEquals(const Component& other)
@@ -280,9 +280,6 @@ namespace bs
 
 	void ManagedComponent::update()
 	{
-		if (PlayInEditorManager::instance().getState() != PlayInEditorState::Playing && !mRunInEditor)
-			return;
-
 		assert(mManagedInstance != nullptr);
 
 		if (mOnUpdateThunk != nullptr)
@@ -293,19 +290,6 @@ namespace bs
 		}
 	}
 
-	void ManagedComponent::triggerOnInitialize()
-	{
-		if (PlayInEditorManager::instance().getState() == PlayInEditorState::Stopped && !mRunInEditor)
-			return;
-
-		if (mOnInitializedThunk != nullptr)
-		{
-			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
-			// for some extra speed.
-			MonoUtil::invokeThunk(mOnInitializedThunk, mManagedInstance);
-		}
-	}
-
 	void ManagedComponent::triggerOnReset()
 	{
 		assert(mManagedInstance != nullptr);
@@ -320,21 +304,6 @@ namespace bs
 		mRequiresReset = false;
 	}
 
-	void ManagedComponent::triggerOnEnable()
-	{
-		if (PlayInEditorManager::instance().getState() == PlayInEditorState::Stopped && !mRunInEditor)
-			return;
-
-		assert(mManagedInstance != nullptr);
-
-		if (mOnEnabledThunk != nullptr)
-		{
-			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
-			// for some extra speed.
-			MonoUtil::invokeThunk(mOnEnabledThunk, mManagedInstance);
-		}
-	}
-
 	void ManagedComponent::_instantiate()
 	{
 		mObjInfo = nullptr;
@@ -396,7 +365,13 @@ namespace bs
 	{
 		assert(mManagedInstance != nullptr);
 
-		triggerOnInitialize();
+		if (mOnInitializedThunk != nullptr)
+		{
+			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
+			// for some extra speed.
+			MonoUtil::invokeThunk(mOnInitializedThunk, mManagedInstance);
+		}
+
 		triggerOnReset();
 	}
 
@@ -417,14 +392,18 @@ namespace bs
 
 	void ManagedComponent::onEnabled()
 	{
-		triggerOnEnable();
+		assert(mManagedInstance != nullptr);
+
+		if (mOnEnabledThunk != nullptr)
+		{
+			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
+			// for some extra speed.
+			MonoUtil::invokeThunk(mOnEnabledThunk, mManagedInstance);
+		}
 	}
 
 	void ManagedComponent::onDisabled()
 	{
-		if (PlayInEditorManager::instance().getState() == PlayInEditorState::Stopped && !mRunInEditor)
-			return;
-
 		assert(mManagedInstance != nullptr);
 
 		if (mOnDisabledThunk != nullptr)
@@ -437,9 +416,6 @@ namespace bs
 
 	void ManagedComponent::onTransformChanged(TransformChangedFlags flags)
 	{
-		if (PlayInEditorManager::instance().getState() == PlayInEditorState::Stopped && !mRunInEditor)
-			return;
-
 		if(mOnTransformChangedThunk != nullptr)
 		{
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this

+ 8 - 6
Source/SBansheeEngine/Source/BsPlayInEditorManager.cpp

@@ -19,7 +19,10 @@ namespace bs
 		if (!gApplication().isEditor())
 			mState = PlayInEditorState::Playing;
 		else
+		{
 			setSystemsPauseState(true);
+			gSceneManager().setComponentState(ComponentState::Stopped);
+		}
 	}
 
 	void PlayInEditorManager::setState(PlayInEditorState state)
@@ -50,19 +53,19 @@ namespace bs
 
 			setSystemsPauseState(true);
 
+			gSceneManager().setComponentState(ComponentState::Stopped);
 			mSavedScene->_instantiate();
 			gSceneManager()._setRootNode(mSavedScene);
+
 			mSavedScene = nullptr;
 		}
 			break;
 		case PlayInEditorState::Playing:
 		{
 			if (oldState == PlayInEditorState::Stopped)
-			{
 				saveSceneInMemory();
-				ScriptGameObjectManager::instance().wakeRuntimeComponents();
-			}
 
+			gSceneManager().setComponentState(ComponentState::Running);
 			setSystemsPauseState(false);
 			gAnimation().setPaused(false);
 		}
@@ -74,10 +77,9 @@ namespace bs
 			gAnimation().setPaused(true);
 
 			if (oldState == PlayInEditorState::Stopped)
-			{
 				saveSceneInMemory();
-				ScriptGameObjectManager::instance().wakeRuntimeComponents();
-			}
+
+			gSceneManager().setComponentState(ComponentState::Paused);
 		}
 			break;
 		default:

+ 0 - 22
Source/SBansheeEngine/Source/BsScriptGameObjectManager.cpp

@@ -193,28 +193,6 @@ namespace bs
 		}
 	}
 
-	void ScriptGameObjectManager::wakeRuntimeComponents()
-	{
-		for (auto& scriptObjectEntry : mScriptComponents)
-		{
-			ScriptComponentBase* scriptComponent = scriptObjectEntry.second;
-			HComponent component = scriptComponent->getNativeHandle();
-
-			if (component->getRTTI()->getRTTIId() == TID_ManagedComponent)
-			{
-				HManagedComponent managedComponent = static_object_cast<ManagedComponent>(component);
-
-				if (managedComponent.isDestroyed() || managedComponent->runInEditor())
-					continue;
-
-				managedComponent->triggerOnInitialize();
-
-				if (component->SO()->getActive())
-					managedComponent->triggerOnEnable();
-			}
-		}
-	}
-
 	void ScriptGameObjectManager::onGameObjectDestroyed(const HGameObject& go)
 	{
 		UINT64 instanceId = go.getInstanceId();