1 /*!
2 	@file
3 	@author		Evmenov Georgiy
4 	@date		01/2008
5 	@module
6 */
7 
8 #pragma once
9 #include <Ogre.h>
10 #include <MyGUI.h>
11 #include "RenderBox.h"
12 #include "Def_Str.h"
13 
14 namespace wraps
15 {
16 
17 	class RenderBoxScene : public RenderBox /*Canvas*/
18 	{
19 	public:
RenderBoxScene()20 		RenderBoxScene() :
21 			mScene(nullptr),
22 			mNode(nullptr),
23 			mCameraNode(nullptr),
24 			//mCamera(nullptr),
25 			mEntity(nullptr),
26 			mAnimationState(nullptr),
27 			mRotationSpeed(RENDER_BOX_AUTO_ROTATION_SPEED),
28 			mMouseRotation(false),
29 			mLastPointerX(0),
30 			mMousePressed(false),
31 			mAutoRotation(false),
32 			mFrameAdvise(false)
33 		{
34 		}
35 
~RenderBoxScene()36 		virtual ~RenderBoxScene()
37 		{
38 		}
39 
40 		/** default RenderBox autorotation speed (if enabled) */
41 		enum { RENDER_BOX_AUTO_ROTATION_SPEED = 20 };
42 
43 
44 		/** Add mesh to scene and remove previous one
45 			@param
46 				_meshName The name of the Mesh it is to be based on (e.g. 'ogrehead.mesh').
47 			returns mesh size
48 		*/
49 		Ogre::Vector3 injectObject(const Ogre::String& _meshName, const Ogre::Vector3& _position = Ogre::Vector3::ZERO, const Ogre::Quaternion& _orientation = Ogre::Quaternion::IDENTITY, const Ogre::Vector3& _scale = Ogre::Vector3::UNIT_SCALE)
50 		{
51 			clearScene();
52 
53 			static size_t num = 0;
54 			mEntity = mScene->createEntity(MyGUI::utility::toString(this, "_RenderBoxMesh_", _meshName, num++), _meshName);
55 			Ogre::SceneNode* node = mNode->createChildSceneNode(_position, _orientation);
56 			node->attachObject(mEntity);
57 
58 			updateViewport();
59 			return mEntity->getBoundingBox().getSize();  ///
60 		}
61 
62 		/** Run mesh animation if animation with such name exist (else print warning in log).
63 			To stop animation use empty string.
64 		*/
setAnimation(const Ogre::String & _value)65 		void setAnimation(const Ogre::String& _value)
66 		{
67 			if (mEntity == nullptr)
68 				return;
69 
70 			try
71 			{
72 				mAnimationState = mEntity->getAnimationState(_value);
73 				mAnimationState->setEnabled(true);
74 				mAnimationState->setLoop(true);
75 				mAnimationState->setWeight(1);
76 			}
77 			catch (Ogre::ItemIdentityException& _e)
78 			{
79 				MYGUI_LOG(Warning, _e.getDescription());
80 			}
81 
82 			frameAdvise(needFrameUpdate());
83 		}
84 
85 		/** Clear scene */
clearScene()86 		void clearScene()
87 		{
88 			setRotationAngle(Ogre::Degree(0));
89 
90 			if (mScene)
91 			{
92 				mScene->destroyAllEntities();
93 				mNode->removeAndDestroyAllChildren();
94 			}
95 
96 			mEntity = nullptr;
97 			mAnimationState = nullptr;
98 		}
99 
100 		/** Set speed of entity rotation.
101 			@param
102 				_speed of rotation in degrees per second.
103 		*/
104 		void setAutoRotationSpeed(int _value = RENDER_BOX_AUTO_ROTATION_SPEED)
105 		{
106 			mRotationSpeed = _value;
107 		}
108 
109 		/** Get speed of entity rotation.*/
getAutoRotationSpeed()110 		int getAutoRotationSpeed()
111 		{
112 			return mRotationSpeed;
113 		}
114 
115 		/** Enable or disable auto rotation */
setAutoRotation(bool _value)116 		void setAutoRotation(bool _value)
117 		{
118 			mAutoRotation = _value;
119 			frameAdvise(needFrameUpdate());
120 		}
121 
122 		/** Get auto rotation flag */
getAutoRotation()123 		bool getAutoRotation()
124 		{
125 			return mAutoRotation;
126 		}
127 
128 		/** Set start rotation angle of entity. */
setRotationAngle(const Ogre::Degree & _value)129 		void setRotationAngle(const Ogre::Degree& _value)
130 		{
131 			if (mNode)
132 			{
133 				mNode->resetOrientation();
134 				mNode->yaw(Ogre::Radian(_value));
135 			}
136 		}
137 
138 		/** Get rotation angle of entity. */
getRotationAngle()139 		Ogre::Degree getRotationAngle()
140 		{
141 			return Ogre::Degree(mNode->getOrientation().getYaw());
142 		}
143 
144 		/** Set possibility to rotate mesh by mouse drag. */
setMouseRotation(bool _value)145 		void setMouseRotation(bool _value)
146 		{
147 			mMouseRotation = _value;
148 		}
149 
150 		/** Get mouse rotation flag */
getMouseRotation()151 		bool getMouseRotation()
152 		{
153 			return mMouseRotation;
154 		}
155 
setCanvas(MyGUI::Canvas * _value)156 		virtual void setCanvas(MyGUI::Canvas* _value)
157 		{
158 			RenderBox::setCanvas(_value);
159 
160 			mCanvas->eventMouseDrag += newDelegate(this, &RenderBoxScene::notifyMouseDrag);
161 			mCanvas->eventMouseButtonPressed += newDelegate(this, &RenderBoxScene::notifyMouseButtonPressed);
162 			mCanvas->eventMouseButtonReleased += newDelegate(this, &RenderBoxScene::notifyMouseButtonReleased);
163 
164 			createScene();
165 		}
166 
destroy()167 		virtual void destroy()
168 		{
169 			clearScene();
170 
171 			if (mCanvas)
172 			{
173 				frameAdvise(false);
174 
175 				mCanvas->eventMouseDrag -= newDelegate(this, &RenderBoxScene::notifyMouseDrag);
176 				mCanvas->eventMouseButtonPressed -= newDelegate(this, &RenderBoxScene::notifyMouseButtonPressed);
177 				mCanvas->eventMouseButtonReleased -= newDelegate(this, &RenderBoxScene::notifyMouseButtonReleased);
178 				mCanvas = nullptr;
179 
180 				Ogre::Root* root = Ogre::Root::getSingletonPtr();
181 				if (root && mScene)
182 					root->destroySceneManager(mScene);
183 				mScene = nullptr;
184 				mNode = nullptr;
185 			}
186 
187 			RenderBox::destroy();
188 		}
189 
190 	private:
notifyMouseDrag(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)191 		void notifyMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
192 		{
193 			if (mMouseRotation)
194 			{
195 				if (mNode)
196 					mNode->yaw(Ogre::Radian(Ogre::Degree((float)_left - mLastPointerX)));
197 				mLastPointerX = _left;
198 			}
199 		}
200 
notifyMouseButtonPressed(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)201 		void notifyMouseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
202 		{
203 			if (mMouseRotation)
204 			{
205 				if (_id == MyGUI::MouseButton::Left)
206 				{
207 					const MyGUI::IntPoint& point = MyGUI::InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
208 					mLastPointerX = point.left;
209 					mMousePressed = true;
210 				}
211 				if (_id == MyGUI::MouseButton::Right)
212 				{
213 					const MyGUI::IntPoint& point = MyGUI::InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Right);
214 					mLastPointerX = point.left;
215 					mMousePressed = true;
216 				}
217 			}
218 		}
219 
notifyMouseButtonReleased(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)220 		void notifyMouseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
221 		{
222 			mMousePressed = false;
223 		}
224 
frameAdvise(bool _advise)225 		void frameAdvise(bool _advise)
226 		{
227 			if (_advise && !mFrameAdvise && needFrameUpdate())
228 			{
229 				MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &RenderBoxScene::frameEntered);
230 				mFrameAdvise = true;
231 			}
232 			else if (!_advise && mFrameAdvise && !needFrameUpdate())
233 			{
234 				MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &RenderBoxScene::frameEntered);
235 				mFrameAdvise = false;
236 			}
237 		}
238 
frameEntered(float _time)239 		void frameEntered(float _time)
240 		{
241 			if (!mMousePressed)
242 			{
243 				if (mAutoRotation && mNode)
244 					mNode->yaw(Ogre::Radian(Ogre::Degree(_time * mRotationSpeed)));
245 			}
246 			if (mAnimationState)
247 				mAnimationState->addTime(_time);
248 		}
249 
needFrameUpdate()250 		bool needFrameUpdate()
251 		{
252 			return mAutoRotation || mAnimationState;
253 		}
254 
255 
256 		void createScene();
257 
258 		void updateViewport();
259 
260 
requestUpdateCanvas(MyGUI::Canvas * _canvas,MyGUI::Canvas::Event _event)261 		virtual void requestUpdateCanvas(MyGUI::Canvas* _canvas, MyGUI::Canvas::Event _event)
262 		{
263 			RenderBox::requestUpdateCanvas(_canvas, _event);
264 
265 			updateViewport();
266 		}
267 
268 	public:
269 		Ogre::SceneManager* mScene;
270 		Ogre::SceneNode* mNode;
271 		Ogre::SceneNode* mCameraNode;
272 		//Ogre::Camera* mCamera;
273 	private:
274 		Ogre::Entity* mEntity;
275 		Ogre::AnimationState* mAnimationState;
276 
277 		int mRotationSpeed;
278 		bool mMouseRotation;
279 		int mLastPointerX;
280 		bool mMousePressed;
281 		bool mAutoRotation;
282 
283 		bool mFrameAdvise;
284 	};
285 
286 } // namespace wraps
287