Pārlūkot izejas kodu

Added rigidbody and character controller inspectors

BearishSun 9 gadi atpakaļ
vecāks
revīzija
c5da0a1495

+ 106 - 0
BansheeEngine/Include/BsGameResourceManager.h

@@ -0,0 +1,106 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	/** 
+	 * Provides a way to map one resource path to another path. Useful if the resources are being referenced using a path
+	 * that is not the path to their physical location.
+	 */
+	class BS_EXPORT ResourceMapping : public IReflectable
+	{
+	public:
+		/** Returns the resource path map. */
+		const UnorderedMap<Path, Path>& getMap() const { return mMapping; }
+
+		/** Adds a new entry to the resource map. Translated from path @from to path @to. */
+		void add(const Path& from, const Path& to);
+
+		/** Creates a new empty resource mapping. */
+		static SPtr<ResourceMapping> create();
+	private:
+		UnorderedMap<Path, Path> mMapping;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ResourceMappingRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		RTTITypeBase* getRTTI() const override;
+	};
+
+	/** Interface that can be implemented by the resource loaders required by GameResourceManager. */
+	class BS_EXPORT IGameResourceLoader
+	{
+	public:
+		virtual ~IGameResourceLoader() { }
+
+		/**	Loads the resource at the specified path. */
+		virtual HResource load(const Path& path, bool keepLoaded) const = 0;
+
+		/** @copydoc GameResourceManager::setMapping */
+		virtual void setMapping(const SPtr<ResourceMapping>& mapping) { }
+	};
+
+	/**	Handles loading of game resources when the standalone game is running. */
+	class BS_EXPORT StandaloneResourceLoader : public IGameResourceLoader
+	{
+	public:
+		/** @copydoc IGameResourceLoader::load */
+		HResource load(const Path& path, bool keepLoaded) const override;
+
+		/** @copydoc IGameResourceLoader::setMapping */
+		void setMapping(const SPtr<ResourceMapping>& mapping) override;
+
+	private:
+		UnorderedMap<Path, Path> mMapping;
+	};
+
+	/**
+	 * Keeps track of resources that can be dynamically loaded during runtime. These resources will be packed with the game
+	 * build so that they're available on demand.
+	 *
+	 * Internal resource handle can be overridden so that editor or other systems can handle resource loading more directly.
+	 */
+	class BS_EXPORT GameResourceManager : public Module<GameResourceManager>
+	{
+	public:
+		GameResourceManager();
+
+		/**
+		 * Loads the resource at the specified path.
+		 * 			
+		 * @see	Resources::load
+		 */
+		HResource load(const Path& path, bool keepLoaded) const;	
+
+		/** @copydoc load */
+		template <class T>
+		ResourceHandle<T> load(const Path& filePath, bool keepLoaded)
+		{
+			return static_resource_cast<T>(load(filePath, keepLoaded));
+		}
+
+		/** 
+		 * Sets an optional mapping that be applied to any path provided to load(). This allows you to reference files
+		 * using different names and/or folder structure than they are actually in.
+		 *
+		 * For example normally in script code you would reference resources based on their path relative to the project
+		 * resoruces folder, but in standalone there is no such folder and we need to map the values.
+		 *
+		 * Provided paths should be relative to the working directory.
+		 */
+		void setMapping(const SPtr<ResourceMapping>& mapping);
+
+		/** Sets the resource loader implementation that determines how are the paths provided to load() loaded. */
+		void setLoader(const SPtr<IGameResourceLoader>& loader);
+
+	private:
+		SPtr<IGameResourceLoader> mLoader;
+	};
+}

+ 167 - 0
MBansheeEditor/Inspectors/CharacterControllerInspector.cs

@@ -0,0 +1,167 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="CharacterController"/> component.
+    /// </summary>
+    [CustomInspector(typeof(CharacterController))]
+    internal class CharacterControllerInspector : Inspector
+    {
+        private GUIFloatField radiusField = new GUIFloatField(new LocEdString("Radius"));
+        private GUIFloatField heightField = new GUIFloatField(new LocEdString("Height"));
+        private GUIVector3Field upField = new GUIVector3Field(new LocEdString("Up"));
+        private GUIFloatField contactOffsetField = new GUIFloatField(new LocEdString("Contact offset"));
+        private GUIFloatField minMoveDistanceField = new GUIFloatField(new LocEdString("Min. move distance"));
+
+        private GUIEnumField climbingModeField = new GUIEnumField(typeof (CharacterClimbingMode),
+            new LocEdString("Climbing mode"));
+        private GUIFloatField stepOffsetField = new GUIFloatField(new LocEdString("Step offset"));
+        
+        private GUIEnumField nonWalkableModeField = new GUIEnumField(typeof (CharacterNonWalkableMode),
+            new LocEdString("Non-walkable mode"));
+        private GUISliderField slopeLimitField = new GUISliderField(0, 180, new LocEdString("Slope limit"));
+
+        private GUIListBoxField layerField = new GUIListBoxField(Layers.Names, false, new LocEdString("Layer"));
+
+        private ulong layersValue = 0;
+        private InspectableState modifyState;
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            BuildGUI();
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            CharacterController controller = InspectedObject as CharacterController;
+            if (controller == null)
+                return InspectableState.NotModified;
+
+            radiusField.Value = controller.Radius;
+            heightField.Value = controller.Height;
+            upField.Value = controller.Up;
+            contactOffsetField.Value = controller.ContactOffset;
+            minMoveDistanceField.Value = controller.MinMoveDistance;
+            climbingModeField.Value = (ulong)controller.ClimbingMode;
+            stepOffsetField.Value = controller.StepOffset;
+            nonWalkableModeField.Value = (ulong)controller.NonWalkableMode;
+            slopeLimitField.Value = controller.SlopeLimit.Degrees;
+
+            if (layersValue != controller.Layer)
+            {
+                bool[] states = new bool[64];
+                for (int i = 0; i < states.Length; i++)
+                    states[i] = (controller.Layer & Layers.Values[i]) == Layers.Values[i];
+
+                layerField.States = states;
+                layersValue = controller.Layer;
+            }
+
+            InspectableState oldState = modifyState;
+            if (modifyState.HasFlag(InspectableState.Modified))
+                modifyState = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Recreates all the GUI elements used by this inspector.
+        /// </summary>
+        private void BuildGUI()
+        {
+            CharacterController controller = InspectedObject as CharacterController;
+            if (controller == null)
+                return;
+
+            radiusField.OnChanged += x => { controller.Radius = x; MarkAsModified(); };
+            radiusField.OnConfirmed += ConfirmModify;
+            radiusField.OnFocusLost += ConfirmModify;
+
+            heightField.OnChanged += x => { controller.Height = x; MarkAsModified(); };
+            heightField.OnConfirmed += ConfirmModify;
+            heightField.OnFocusLost += ConfirmModify;
+
+            upField.OnChanged += x => { controller.Up = x; MarkAsModified(); };
+            upField.OnConfirmed += ConfirmModify;
+            upField.OnFocusLost += ConfirmModify;
+
+            contactOffsetField.OnChanged += x => { controller.ContactOffset = x; MarkAsModified(); };
+            contactOffsetField.OnConfirmed += ConfirmModify;
+            contactOffsetField.OnFocusLost += ConfirmModify;
+
+            minMoveDistanceField.OnChanged += x => { controller.MinMoveDistance = x; MarkAsModified(); };
+            minMoveDistanceField.OnConfirmed += ConfirmModify;
+            minMoveDistanceField.OnFocusLost += ConfirmModify;
+
+            climbingModeField.OnSelectionChanged += x =>
+            {
+                controller.ClimbingMode = (CharacterClimbingMode)x;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            stepOffsetField.OnChanged += x => { controller.StepOffset = x; MarkAsModified(); };
+            stepOffsetField.OnConfirmed += ConfirmModify;
+            stepOffsetField.OnFocusLost += ConfirmModify;
+
+            nonWalkableModeField.OnSelectionChanged += x =>
+            {
+                controller.NonWalkableMode = (CharacterNonWalkableMode)x;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            slopeLimitField.OnChanged += x => { controller.SlopeLimit = new Degree(x); MarkAsModified(); };
+            slopeLimitField.OnFocusLost += ConfirmModify;
+
+            layerField.OnSelectionChanged += x =>
+            {
+                ulong layer = 0;
+                bool[] states = layerField.States;
+                for (int i = 0; i < states.Length; i++)
+                    layer |= states[i] ? Layers.Values[i] : 0;
+
+                layersValue = layer;
+                controller.Layer = layer;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            Layout.AddElement(radiusField);
+            Layout.AddElement(heightField);
+            Layout.AddElement(upField);
+            Layout.AddElement(contactOffsetField);
+            Layout.AddElement(minMoveDistanceField);
+            Layout.AddElement(climbingModeField);
+            Layout.AddElement(stepOffsetField);
+            Layout.AddElement(nonWalkableModeField);
+            Layout.AddElement(slopeLimitField);
+            Layout.AddElement(layerField);
+        }
+
+        /// <summary>
+        /// Marks the contents of the inspector as modified.
+        /// </summary>
+        protected void MarkAsModified()
+        {
+            modifyState |= InspectableState.ModifyInProgress;
+        }
+
+        /// <summary>
+        /// Confirms any queued modifications.
+        /// </summary>
+        protected void ConfirmModify()
+        {
+            if (modifyState.HasFlag(InspectableState.ModifyInProgress))
+                modifyState |= InspectableState.Modified;
+        }
+    }
+}

+ 152 - 0
MBansheeEditor/Inspectors/RigidbodyInspector.cs

@@ -0,0 +1,152 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="Rigidbody"/> component.
+    /// </summary>
+    [CustomInspector(typeof(Rigidbody))]
+    internal class RigidbodyInspector : Inspector
+    {
+        private GUIToggleField kinematicField = new GUIToggleField(new LocEdString("Kinematic"));
+        private GUIToggleField applyGravityField = new GUIToggleField(new LocEdString("Apply gravity"));
+        private GUIToggleField automaticMassField = new GUIToggleField(new LocEdString("Calculate mass"));
+        private GUIFloatField massField = new GUIFloatField("Mass");
+        private GUIFloatField linearDragField = new GUIFloatField("Linear drag");
+        private GUIFloatField angularDragField = new GUIFloatField("Angular drag");
+        private GUIEnumField interpolationModeField = new GUIEnumField(typeof (RigidbodyInterpolationMode),
+            new LocEdString("Interpolation mode"));
+        private GUIEnumField reportModeField = new GUIEnumField(typeof (CollisionReportMode),
+            new LocEdString("Collision report mode"));
+        private GUIToggleField ccdField = new GUIToggleField("Continous");
+
+        private InspectableState modifyState;
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            BuildGUI();
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            Rigidbody body = InspectedObject as Rigidbody;
+            if (body == null)
+                return InspectableState.NotModified;
+
+            kinematicField.Value = body.Kinematic;
+            applyGravityField.Value = body.UseGravity;
+            automaticMassField.Value = (body.Flags & RigidbodyFlag.AutoMass) != 0;
+            massField.Value = body.Mass;
+            linearDragField.Value = body.Drag;
+            angularDragField.Value = body.AngularDrag;
+            interpolationModeField.Value = (ulong)body.InterpolationMode;
+            reportModeField.Value = (ulong) body.CollisionReportMode;
+            ccdField.Value = (body.Flags & RigidbodyFlag.CCD) != 0;
+
+            massField.Active = (body.Flags & RigidbodyFlag.AutoMass) == 0;
+            
+            InspectableState oldState = modifyState;
+            if (modifyState.HasFlag(InspectableState.Modified))
+                modifyState = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Recreates all the GUI elements used by this inspector.
+        /// </summary>
+        private void BuildGUI()
+        {
+            Rigidbody body = InspectedObject as Rigidbody;
+            if (body == null)
+                return;
+
+            kinematicField.OnChanged += x => { body.Kinematic = x; MarkAsModified(); ConfirmModify(); };
+            applyGravityField.OnChanged += x => { body.UseGravity = x; MarkAsModified(); ConfirmModify(); };
+            automaticMassField.OnChanged += x =>
+            {
+                if (x)
+                    body.Flags |= RigidbodyFlag.AutoMass;
+                else
+                    body.Flags &= ~RigidbodyFlag.AutoMass;
+
+                massField.Active = !x;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            massField.OnChanged += x => { body.Mass = x; MarkAsModified(); };
+            massField.OnConfirmed += ConfirmModify;
+            massField.OnFocusLost += ConfirmModify;
+
+            linearDragField.OnChanged += x => { body.Drag = x; MarkAsModified(); };
+            linearDragField.OnConfirmed += ConfirmModify;
+            linearDragField.OnFocusLost += ConfirmModify;
+
+            angularDragField.OnChanged += x => { body.AngularDrag = x; MarkAsModified(); };
+            angularDragField.OnConfirmed += ConfirmModify;
+            angularDragField.OnFocusLost += ConfirmModify;
+
+            interpolationModeField.OnSelectionChanged += x =>
+            {
+                body.InterpolationMode = (RigidbodyInterpolationMode)x;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            reportModeField.OnSelectionChanged += x =>
+            {
+                body.CollisionReportMode = (CollisionReportMode) x;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            ccdField.OnChanged += x =>
+            {
+                if (x)
+                    body.Flags |= RigidbodyFlag.CCD;
+                else
+                    body.Flags &= ~RigidbodyFlag.CCD;
+
+                MarkAsModified();
+                ConfirmModify();
+            };
+
+            massField.Active = (body.Flags & RigidbodyFlag.AutoMass) == 0;
+
+            Layout.AddElement(kinematicField);
+            Layout.AddElement(applyGravityField);
+            Layout.AddElement(automaticMassField);
+            Layout.AddElement(massField);
+            Layout.AddElement(linearDragField);
+            Layout.AddElement(angularDragField);
+            Layout.AddElement(interpolationModeField);
+            Layout.AddElement(reportModeField);
+            Layout.AddElement(ccdField);
+        }
+        
+        /// <summary>
+        /// Marks the contents of the inspector as modified.
+        /// </summary>
+        protected void MarkAsModified()
+        {
+            modifyState |= InspectableState.ModifyInProgress;
+        }
+
+        /// <summary>
+        /// Confirms any queued modifications.
+        /// </summary>
+        protected void ConfirmModify()
+        {
+            if (modifyState.HasFlag(InspectableState.ModifyInProgress))
+                modifyState |= InspectableState.Modified;
+        }
+    }
+}

+ 2 - 0
MBansheeEditor/MBansheeEditor.csproj

@@ -49,6 +49,7 @@
     <Compile Include="EditorPersistentData.cs" />
     <Compile Include="Inspectors\BoxColliderInspector.cs" />
     <Compile Include="Inspectors\CapsuleColliderInspector.cs" />
+    <Compile Include="Inspectors\CharacterControllerInspector.cs" />
     <Compile Include="Inspectors\ColliderInspector.cs" />
     <Compile Include="Inspectors\D6JointInspector.cs" />
     <Compile Include="Inspectors\DistanceJointInspector.cs" />
@@ -61,6 +62,7 @@
     <Compile Include="Inspectors\PhysicsMaterialInspector.cs" />
     <Compile Include="Inspectors\PhysicsMeshInspector.cs" />
     <Compile Include="Inspectors\PlaneColliderInspector.cs" />
+    <Compile Include="Inspectors\RigidbodyInspector.cs" />
     <Compile Include="Inspectors\SliderJointInspector.cs" />
     <Compile Include="Inspectors\SphereColliderInspector.cs" />
     <Compile Include="Inspectors\SphericalJointInspector.cs" />

+ 1 - 0
MBansheeEngine/Physics/Rigidbody.cs

@@ -753,6 +753,7 @@ namespace BansheeEngine
     /// <summary>
     /// Flags that control options of a Rigidbody object.
     /// </summary>
+    [Flags]
     public enum RigidbodyFlag
     {
         /// <summary>