Browse Source

Merge branch 'master' into preview

BearishSun 9 years ago
parent
commit
b88dc6388f

+ 27 - 22
Source/ExampleProject/Include/CameraFlyer.h

@@ -9,35 +9,40 @@
 
 namespace BansheeEngine
 {
+	/** 
+	 * Component that controls movement and rotation of a Camera component. The Camera component must be attached to the 
+	 * same SceneObject this component is on.
+	 */
 	class CameraFlyer : public Component
 	{
 	public:
 		CameraFlyer(const HSceneObject& parent);
 
+		/** Triggered once per frame. Allows the component to handle input and move. */
 		virtual void update();
 
 	private:
-		float mCurrentSpeed;
-
-		Degree mPitch;
-		Degree mYaw;
-		bool mLastButtonState;
-
-		HCamera mCamera;
-
-		VirtualButton mMoveForward;
-		VirtualButton mMoveBack;
-		VirtualButton mMoveLeft;
-		VirtualButton mMoveRight;
-		VirtualButton mFastMove;
-		VirtualButton mRotateCam;
-		VirtualAxis mVerticalAxis;
-		VirtualAxis mHorizontalAxis;
-
-		static const float START_SPEED;
-		static const float TOP_SPEED;
-		static const float ACCELERATION;
-		static const float FAST_MODE_MULTIPLIER;
-		static const float ROTATION_SPEED; // Degrees/second
+		float mCurrentSpeed; /**< Current speed of the camera. */
+
+		Degree mPitch; /**< Current pitch rotation of the camera (looking up or down). */
+		Degree mYaw; /**< Current yar rotation of the camera (looking left or right). */
+		bool mLastButtonState; /**< Determines was the user rotating the camera last frame. */
+
+		HCamera mCamera; /**< Camera component that is influenced by the flyer. */
+
+		VirtualButton mMoveForward; /**< Key binding for moving the camera forward. */
+		VirtualButton mMoveBack; /**< Key binding for moving the camera backward. */
+		VirtualButton mMoveLeft; /**< Key binding for moving the camera left. */
+		VirtualButton mMoveRight; /**< Key binding for moving the camera right. */
+		VirtualButton mFastMove; /**< Key that speeds up movement while held. */
+		VirtualButton mRotateCam; /**< Key that allows camera to be rotated while held. */
+		VirtualAxis mVerticalAxis; /**< Input device axis used for controlling camera's pitch rotation (up/down). */
+		VirtualAxis mHorizontalAxis; /**< Input device axis used for controlling camera's yaw rotation (left/right). */
+
+		static const float START_SPEED; /**< Initial movement speed. */
+		static const float TOP_SPEED; /**< Maximum movement speed. */
+		static const float ACCELERATION; /**< Acceleration that determines how quickly to go from starting to top speed. */
+		static const float FAST_MODE_MULTIPLIER; /**< Multiplier applied to the speed when the fast move button is held. */
+		static const float ROTATION_SPEED; /**< Determines speed for rotation, in degrees per second. */
 	};
 }

+ 13 - 2
Source/ExampleProject/Source/CameraFlyer.cpp

@@ -6,9 +6,7 @@
 #include "BsMath.h"
 #include "BsSceneObject.h"
 #include "BsCCamera.h"
-#include "BsPlatform.h"
 #include "BsCursor.h"
-#include "BsDebug.h"
 
 namespace BansheeEngine
 {
@@ -18,6 +16,7 @@ namespace BansheeEngine
 	const float CameraFlyer::FAST_MODE_MULTIPLIER = 2.0f;
 	const float CameraFlyer::ROTATION_SPEED = 360.0f; // Degrees/second
 
+	/** Wraps an angle so it always stays in [0, 360) range. */
 	Degree wrapAngle(Degree angle)
 	{
 		if (angle.valueDegrees() < -360.0f)
@@ -32,11 +31,14 @@ namespace BansheeEngine
 	CameraFlyer::CameraFlyer(const HSceneObject& parent)
 		:Component(parent), mPitch(0.0f), mYaw(0.0f), mLastButtonState(false)
 	{
+		// Set a name for the component, so we can find it later if needed
 		setName("CameraFlyer");
 
+		// Find the camera component we're influencing (must be on the same SceneObject we're on)
 		mCamera = sceneObject()->getComponent<CCamera>();
 		mCamera->setNearClipDistance(5);
 
+		// Get handles for key bindings. Actual keys attached to these bindings will be registered during app start-up.
 		mMoveForward = VirtualButton("Forward");
 		mMoveBack = VirtualButton("Back");
 		mMoveLeft = VirtualButton("Left");
@@ -49,6 +51,7 @@ namespace BansheeEngine
 
 	void CameraFlyer::update()
 	{
+		// Check if any movement or rotation keys are being held
 		bool goingForward = gVirtualInput().isButtonHeld(mMoveForward);
 		bool goingBack = gVirtualInput().isButtonHeld(mMoveBack);
 		bool goingLeft = gVirtualInput().isButtonHeld(mMoveLeft);
@@ -56,6 +59,7 @@ namespace BansheeEngine
 		bool fastMove = gVirtualInput().isButtonHeld(mFastMove);
 		bool camRotating = gVirtualInput().isButtonHeld(mRotateCam);
 
+		// If switch to or from rotation mode, hide or show the cursor
 		if (camRotating != mLastButtonState)
 		{
 			if (camRotating)
@@ -66,6 +70,8 @@ namespace BansheeEngine
 			mLastButtonState = camRotating;
 		}
 
+		// If camera is rotating, apply new pitch/yaw rotation values depending on the amount of rotation from the
+		// vertical/horizontal axes.
 		float frameDelta = gTime().getFrameDelta();
 		if (camRotating)
 		{
@@ -87,20 +93,24 @@ namespace BansheeEngine
 			SO()->setRotation(camRot);
 		}
 
+		// If the movement button is pressed, determine direction to move in
 		Vector3 direction = Vector3::ZERO;
 		if (goingForward) direction += SO()->getForward();
 		if (goingBack) direction -= SO()->getForward();
 		if (goingRight) direction += SO()->getRight();
 		if (goingLeft) direction -= SO()->getRight();
 
+		// If a direction is chosen, normalize it to determine final direction.
 		if (direction.squaredLength() != 0)
 		{
 			direction.normalize();
 
+			// Apply fast move multiplier if the fast move button is held.
 			float multiplier = 1.0f;
 			if (fastMove)
 				multiplier = FAST_MODE_MULTIPLIER;
 
+			// Calculate current speed of the camera
 			mCurrentSpeed = Math::clamp(mCurrentSpeed + ACCELERATION * frameDelta, START_SPEED, TOP_SPEED);
 			mCurrentSpeed *= multiplier;
 		}
@@ -109,6 +119,7 @@ namespace BansheeEngine
 			mCurrentSpeed = 0.0f;
 		}
 
+		// If the current speed isn't too small, move the camera in the wanted direction
 		float tooSmall = std::numeric_limits<float>::epsilon();
 		if (mCurrentSpeed > tooSmall)
 		{

+ 71 - 26
Source/ExampleProject/Source/Main.cpp

@@ -2,8 +2,10 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include <windows.h>
 
+// Engine includes
 #include "BsApplication.h"
 #include "BsImporter.h"
+#include "BsResources.h"
 #include "BsTextureImportOptions.h"
 #include "BsMaterial.h"
 #include "BsShader.h"
@@ -13,10 +15,10 @@
 #include "BsCGUIWidget.h"
 #include "BsGUILayoutX.h"
 #include "BsGUILayoutY.h"
+#include "BsGUIPanel.h"
 #include "BsGUISpace.h"
 #include "BsGUILabel.h"
 #include "BsGUIButton.h"
-#include "BsGUIPanel.h"
 #include "BsRenderAPI.h"
 #include "BsGUIListBox.h"
 #include "BsBuiltinResources.h"
@@ -27,6 +29,7 @@
 #include "BsCoreThread.h"
 #include "BsProfilerOverlay.h"
 
+// Example includes
 #include "CameraFlyer.h"
 
 namespace BansheeEngine
@@ -38,7 +41,7 @@ namespace BansheeEngine
 	void setUpExample();
 
 	/** Import mesh/texture/GPU programs used by the example. */
-	void importAssets(HMesh& model, HTexture& texture, HShader& shader);
+	void loadAssets(HMesh& model, HTexture& texture, HShader& shader);
 
 	/** Create a material used by our example model. */
 	HMaterial createMaterial(const HTexture& texture, const HShader& shader);
@@ -135,7 +138,7 @@ namespace BansheeEngine
 		HTexture exampleTexture;
 		HShader exampleShader;
 
-		importAssets(exampleModel, exampleTexture, exampleShader);
+		loadAssets(exampleModel, exampleTexture, exampleShader);
 		HMaterial exampleMaterial = createMaterial(exampleTexture, exampleShader);
 
 		setUp3DScene(exampleModel, exampleMaterial);
@@ -143,46 +146,83 @@ namespace BansheeEngine
 		setUpInput();
 	}
 
-	void importAssets(HMesh& model, HTexture& texture, HShader& shader)
+	/**
+	 * Load the required resources. First try to load a pre-processed version of the resources. If they don't exist import
+	 * resources from the source formats into engine format, and save them for next time.
+	 */
+	void loadAssets(HMesh& model, HTexture& texture, HShader& shader)
 	{
-		// Import mesh, texture and shader from the disk. In a normal application you would want to save the imported assets
-		// so next time the application is ran you can just load them directly. This can be done with Resources::save/load.
-
-		// Import an FBX mesh.
-		model = Importer::instance().import<Mesh>(exampleModelPath);
+		// Set up paths to pre-processed versions of example resources.
+		Path exampleModelAssetPath = exampleModelPath;
+		Path exampleTextureAssetPath = exampleTexturePath;
+		Path exampleShaderAssetPath = exampleShaderPath;
+
+		exampleModelAssetPath.setExtension(exampleModelAssetPath.getExtension() + ".asset");
+		exampleTextureAssetPath.setExtension(exampleTextureAssetPath.getExtension() + ".asset");
+		exampleShaderAssetPath.setExtension(exampleShaderAssetPath.getExtension() + ".asset");
+
+		// Load an FBX mesh.
+		model = gResources().load<Mesh>(exampleModelAssetPath);
+		if(model == nullptr) // Mesh file doesn't exist, import from the source file.
+		{
+			model = gImporter().import<Mesh>(exampleModelPath);
 
-		// When importing you may specify optional import options that control how is the asset imported.
-		SPtr<ImportOptions> textureImportOptions = Importer::instance().createImportOptions(exampleTexturePath);
+			// Save for later use, so we don't have to import on the next run.
+			gResources().save(model, exampleModelAssetPath, true);
+		}
 
-		// rtti_is_of_type checks if the import options are of valid type, in case the provided path is pointing to a non-texture resource.
-		// This is similar to dynamic_cast but uses Banshee internal RTTI system for type checking.
-		if (rtti_is_of_type<TextureImportOptions>(textureImportOptions))
+		// Load an TGA texture.
+		texture = gResources().load<Texture>(exampleTextureAssetPath);
+		if (texture == nullptr) // Texture file doesn't exist, import from the source file.
 		{
-			TextureImportOptions* importOptions = static_cast<TextureImportOptions*>(textureImportOptions.get());
+			// When importing you may specify optional import options that control how is the asset imported.
+			SPtr<ImportOptions> textureImportOptions = Importer::instance().createImportOptions(exampleTexturePath);
+
+			// rtti_is_of_type checks if the import options are of valid type, in case the provided path is pointing to a non-texture resource.
+			// This is similar to dynamic_cast but uses Banshee internal RTTI system for type checking.
+			if (rtti_is_of_type<TextureImportOptions>(textureImportOptions))
+			{
+				TextureImportOptions* importOptions = static_cast<TextureImportOptions*>(textureImportOptions.get());
 
-			// We want maximum number of mipmaps to be generated
-			importOptions->setGenerateMipmaps(true);
+				// We want maximum number of mipmaps to be generated
+				importOptions->setGenerateMipmaps(true);
+
+				// The texture is in sRGB space
+				importOptions->setSRGB(true);
+			}
+
+			// Import texture with specified import options
+			texture = gImporter().import<Texture>(exampleTexturePath, textureImportOptions);
+
+			// Save for later use, so we don't have to import on the next run.
+			gResources().save(texture, exampleTextureAssetPath, true);
 		}
 
-		// Import texture with specified import options
-		texture = Importer::instance().import<Texture>(exampleTexturePath, textureImportOptions);
+		// Load a shader.
+		shader = gResources().load<Shader>(exampleShaderAssetPath);
+		if (shader == nullptr) // Mesh file doesn't exist, import from the source file.
+		{
+			shader = gImporter().import<Shader>(exampleShaderPath);
 
-		// Import shader
-		shader = Importer::instance().import<Shader>(exampleShaderPath);
+			// Save for later use, so we don't have to import on the next run.
+			gResources().save(shader, exampleShaderAssetPath, true);
+		}
 	}
 
+	/** Create a material using the provided shader, and assign the provided texture to it. */
 	HMaterial createMaterial(const HTexture& texture, const HShader& shader)
 	{
-		// And finally create a material with the newly created shader
+		// Create a material with the provided shader.
 		HMaterial exampleMaterial = Material::create(shader);
 
 		// And set the texture to be used by the "tex" shader parameter. We leave the "samp"
-		// parameter at its defaults.
+		// parameter at its defaults. These parameters are defined in the shader (.bsl) file.
 		exampleMaterial->setTexture("tex", texture);
 
 		return exampleMaterial;
 	}
 
+	/** Set up the 3D object used by the example, and the camera to view the world through. */
 	void setUp3DScene(const HMesh& mesh, const HMaterial& material)
 	{
 		/************************************************************************/
@@ -244,6 +284,7 @@ namespace BansheeEngine
 		sceneCameraSO->lookAt(Vector3(0, 0, 0));
 	}
 
+	/** Register mouse and keyboard inputs that will be used for controlling the camera. */
 	void setUpInput()
 	{
 		// Register input configuration
@@ -283,6 +324,7 @@ namespace BansheeEngine
 		VirtualInput::instance().onButtonUp.connect(&buttonUp);
 	}
 
+	/** Set up graphical user interface used by the example. */
 	void setUpGUI()
 	{
 		// Create a scene object that will contain GUI components
@@ -394,6 +436,7 @@ namespace BansheeEngine
 		videoModeListBox->onSelectionToggled.connect(&videoModeChanged);
 	}
 
+	/** Callback method that toggles between fullscreen and windowed modes. */
 	void toggleFullscreen()
 	{
 		SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
@@ -420,6 +463,7 @@ namespace BansheeEngine
 		fullscreen = !fullscreen;
 	}
 
+	/** Callback triggered wheneve the user resizes the example window. */
 	void renderWindowResized()
 	{
 		SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
@@ -434,6 +478,7 @@ namespace BansheeEngine
 		sceneCamera->setAspectRatio(rwProps.getWidth() / (float)rwProps.getHeight());
 	}
 
+	/** Callback triggered when the user selects a new video mode from the GUI drop down element. */
 	void videoModeChanged(UINT32 idx, bool enabled)
 	{
 		if (!enabled)
@@ -448,11 +493,11 @@ namespace BansheeEngine
 		}
 	}
 
+	/** Callback triggered when a user hits a button. */
 	void buttonUp(const VirtualButton& button, UINT32 deviceIdx)
 	{
-		// Check if the pressed button is one of the either buttons we defined
-		// in "setUpExample", and toggle profiler overlays accordingly.
-		// Device index is ignored for now, as it is assumed the user is using a single keyboard,
+		// Check if the pressed button is one of the either buttons we defined in "setUpExample", and toggle profiler
+		// overlays accordingly. Device index is ignored for now, as it is assumed the user is using a single keyboard,
 		// but if you wanted support for multiple gamepads you would check deviceIdx.
 		if (button == toggleCPUProfilerBtn)
 		{