SO3Engine
SO3ObjWindowWidget.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
38#include "SO3Renderer/SO3Root.h"
40
41namespace SO3
42{
43
44SObjWindowWidget::SObjWindowWidget(SScene* targetScene, const std::string& bitmapWidgetName, const int& xPos, const int& yPos, const unsigned short& widgetWidth, const unsigned short& widgetHeight, SViewPort* targetViewport, const unsigned int& widgetZOrder) : SWidget(targetScene, bitmapWidgetName, xPos, yPos, widgetWidth, widgetHeight, targetViewport, widgetZOrder, SO3_OBJ_WINDOW_WIDGET_TYPE)
45{
47}
48
49SObjWindowWidget::SObjWindowWidget(SScene* targetScene, const std::string& bitmapWidgetName, const int& xPos, const int& yPos, const unsigned short& widgetWidth, const unsigned short& widgetHeight, SViewPort* targetViewport) : SWidget(targetScene, bitmapWidgetName, xPos, yPos, widgetWidth, widgetHeight, targetViewport, SO3_OBJ_WINDOW_WIDGET_TYPE)
50{
52}
53
54SObjWindowWidget::SObjWindowWidget(SScene* targetScene, const std::string& bitmapWidgetName, const unsigned short& widgetWidth, const unsigned short& widgetHeight, SMaterial* targetMaterial, const unsigned short& targetTechnique, const unsigned short& targetPass, const unsigned short& targetTextureUnit) : SWidget(targetScene, bitmapWidgetName, widgetWidth, widgetHeight, targetMaterial, targetTechnique, targetPass, targetTextureUnit, SO3_OBJ_WINDOW_WIDGET_TYPE)
55{
57}
58
60{
61 targetWindowHandle = 0;
62 lastWindowWithBordersWidth = -1;
63 lastWindowWithBordersHeight = -1;
64 targetWindowDC = 0;
65 memoryBitmapDC = 0;
66 memoryBitmap = 0;
67 pixelsData = 0;
68 drawBorders = false;
69}
70
72{
73 // Clean
74 DestroyDevicesContexts();
75 DestroyMemoryBitmap();
76}
77
78void SObjWindowWidget::SetTargetWindow(const ScolWindowHandle& targetWindowHandlePtr)
79{
80 // Associate with the window
81 assert(targetWindowHandle == 0);
82 targetWindowHandle = targetWindowHandlePtr;
83}
84
85void SObjWindowWidget::LoadURL(const std::string& url)
86{
87 // Throw exception, catch in scol bind, and return nil.
89 OGRE_EXCEPT(Ogre::Exception::ERR_NOT_IMPLEMENTED, "Cannot directly load an URL in a ObjWindow widget, use \"UpdateRawData\" function!", "SObjWindowWidget::LoadURL");
90}
91
92void SObjWindowWidget::LoadFile(const std::string& file)
93{
94 // Throw exception, catch in scol bind, and return nil.
96 OGRE_EXCEPT(Ogre::Exception::ERR_NOT_IMPLEMENTED, "Cannot directly load a file directly in a ObjWindow widget, use \"UpdateRawData\" function!", "SObjWindowWidget::LoadFile");
97}
98
99void SObjWindowWidget::InjectMouseMove(const int& xPos, const int& yPos, const MouseButtonId& button)
100{
101 if(CheckWindowIsStillValid())
102 {
103 // Push event to target window
104 //WPARAM wparam = static_cast <WPARAM> (button);
105 InjectMouseMessage(xPos, yPos, WM_MOUSEMOVE/*, wparam*/);
106 }
107}
108
109void SObjWindowWidget::InjectMouseWheel(const int& scrollX, const int& scrollY, const int& relativeScroll)
110{
111 if(CheckWindowIsStillValid())
112 {
113 // Push event to target window
114 InjectMouseMessage(scrollX, scrollY, WM_MOUSEHWHEEL, MAKEWPARAM(0, relativeScroll));
115 }
116}
117
118void SObjWindowWidget::InjectMouseDown(const int& xPos, const int& yPos, const MouseButtonId& button)
119{
120 if(CheckWindowIsStillValid())
121 {
122 // Push event to target window
123 switch(button)
124 {
126 InjectMouseMessage(xPos, yPos, WM_LBUTTONDOWN);
127 break;
129 InjectMouseMessage(xPos, yPos, WM_MBUTTONDOWN);
130 break;
132 InjectMouseMessage(xPos, yPos, WM_RBUTTONDOWN);
133 break;
134 }
135 }
136}
137
138void SObjWindowWidget::InjectMouseUp(const int& xPos, const int& yPos, const MouseButtonId& button)
139{
140 if(CheckWindowIsStillValid())
141 {
142 // Push event to target window
143 switch(button)
144 {
146 InjectMouseMessage(xPos, yPos, WM_LBUTTONUP);
147 break;
149 InjectMouseMessage(xPos, yPos, WM_MBUTTONUP);
150 break;
152 InjectMouseMessage(xPos, yPos, WM_RBUTTONUP);
153 break;
154 }
155 }
156}
157
158void SObjWindowWidget::InjectTouchAdd(const int& xPos, const int& yPos, const int& touchid)
159{
160 // Nothing to do
161}
162
164{
165 // Nothing to do
166}
167
168void SObjWindowWidget::InjectTouchUpdate(const int& xPos, const int& yPos, const int& vx, const int& vy, const int& touchid)
169{
170 // Nothing to do
171}
172
173void SObjWindowWidget::InjectKeyEvent(const UINT& msg, const ScolWindowHandle& hwnd, const WPARAM& wParam, const LPARAM& lParam)
174{
175 if(CheckWindowIsStillValid())
176 {
177 // Push event to target window
178 PostMessage(targetWindowHandle, msg, wParam, lParam);
179 }
180}
181
182void SObjWindowWidget::InjectTextEvent(const std::string& utf8)
183{
184 // Nothing to do
185}
186
187void SObjWindowWidget::SetFocusImpl(const bool& focusOnWidget)
188{
189 if(CheckWindowIsStillValid())
190 {
191 /*if(focusOnWidget)
192 SetFocus(targetWindowHandle);
193 else
194 SetFocus(SRoot::getSingleton().GetRootWindowHandle());*/
195 }
196}
197
198void SObjWindowWidget::SetTransparencyImpl(const bool& enableTransparency)
199{
200 // Nothing to do
201}
202
203void SObjWindowWidget::RunScriptFunction(const std::string& functionName, const std::vector<std::string>& argumentList)
204{
205 // Nothing to do, no script for objWindow!
206}
207
208void SObjWindowWidget::SetKeyboardEnableImpl(const bool& enableKeyboardOnWidget)
209{
210 // Nothing to do
211}
212
213void SObjWindowWidget::SetMouseEnableImpl(const bool& enableMouseOnWidget)
214{
215 // Nothing to do
216}
217
218void SObjWindowWidget::SetSizeImpl(const unsigned short& newWidth, const unsigned short& newHeight)
219{
220 // Nothing to do
221}
222
223bool SObjWindowWidget::CheckPixelAlpha(const int& posX, const int& posY)
224{
225 return false;
226}
227
229{
230 return drawBorders;
231}
232
233void SObjWindowWidget::SetBorderVisible(const bool& drawBordersEnable)
234{
235 drawBorders = drawBordersEnable;
236}
237
238void SObjWindowWidget::InjectMouseMessage(const int& xPos, const int& yPos, const unsigned int& message, const WPARAM& wParam)
239{
240 if(CheckWindowIsStillValid())
241 {
242 // Get target window rectangle
243 WINDOWINFO parentWindowInfos;
244 GetWindowInfo(targetWindowHandle, &parentWindowInfos);
245
246 // Recompute real window coordonates
247 POINT localPosition;
248 if(drawBorders)
249 {
250 localPosition.x = static_cast<int>((static_cast<long>(xPos) * (parentWindowInfos.rcWindow.right - parentWindowInfos.rcWindow.left) / static_cast<long>(width)) - (parentWindowInfos.rcClient.left - parentWindowInfos.rcWindow.left));
251 localPosition.y = static_cast<int>((static_cast<long>(yPos) * (parentWindowInfos.rcWindow.bottom - parentWindowInfos.rcWindow.top) / static_cast<long>(height)) - (parentWindowInfos.rcClient.top - parentWindowInfos.rcWindow.top));
252 }
253 else
254 {
255 localPosition.x = static_cast<int>(static_cast<long>(xPos) * (parentWindowInfos.rcClient.right - parentWindowInfos.rcClient.left) / static_cast<long>(width));
256 localPosition.y = static_cast<int>(static_cast<long>(yPos) * (parentWindowInfos.rcClient.bottom - parentWindowInfos.rcClient.top) / static_cast<long>(height));
257 }
258
259 // Find the child window that is under the mouse coordinates
260 WINDOWINFO chilWindowInfos;
261 ScolWindowHandle childWindowHandle = 0;
262 ScolWindowHandle lastChildWindowHandle = 0;
263 do
264 {
265 // Store infos about parent for later use. No need to do it for first pass, as we already have information of targetWindowHandle in parentWindowInfos.
266 if(lastChildWindowHandle == 0)
267 lastChildWindowHandle = targetWindowHandle;
268 else
269 GetWindowInfo(lastChildWindowHandle, &parentWindowInfos);
270
271 // Get child
272 childWindowHandle = ChildWindowFromPoint(lastChildWindowHandle, localPosition);
273 if(childWindowHandle == 0)
274 lastChildWindowHandle = 0;
275
276 // If different than the last
277 if(childWindowHandle != lastChildWindowHandle)
278 {
279 // Get infos about the child
280 GetWindowInfo(childWindowHandle, &chilWindowInfos);
281
282 // Re-compute local position
283 localPosition.x = localPosition.x - (chilWindowInfos.rcWindow.left - parentWindowInfos.rcClient.left);
284 localPosition.y = localPosition.y - (chilWindowInfos.rcWindow.top - parentWindowInfos.rcClient.top);
285 lastChildWindowHandle = childWindowHandle;
286 childWindowHandle = 0;
287 }
288 }while (childWindowHandle != lastChildWindowHandle);
289
290 // If the position is not over the target window (mouse move message for example)
291 if(lastChildWindowHandle == 0)
292 lastChildWindowHandle = targetWindowHandle;
293
294 // Post message
295 SetCapture(targetWindowHandle);
296 SendMessage(lastChildWindowHandle, WM_SETCURSOR, (WPARAM)(0), (LPARAM)(MAKELONG(HTCLIENT, message)));
297 SendMessage(lastChildWindowHandle, message, wParam, MAKELPARAM(localPosition.x, localPosition.y));
298 ReleaseCapture();
299 }
300}
301
303{
304 if(CheckWindowIsStillValid())
305 {
306 // Get target window informations
307 WINDOWINFO targetWindowInfos;
308 GetWindowInfo(targetWindowHandle, &targetWindowInfos);
309
310 // Compute render size
311 long targetWindowWithBordersWidth = targetWindowInfos.rcWindow.right - targetWindowInfos.rcWindow.left;
312 long targetWindowWithBordersHeight = targetWindowInfos.rcWindow.bottom - targetWindowInfos.rcWindow.top;
313
314 // Size has changed, need to update the device context and the bitmap too
315 if((lastWindowWithBordersWidth != targetWindowWithBordersWidth) || (lastWindowWithBordersHeight != targetWindowWithBordersHeight))
316 {
317 CreateDevicesContexts();
318 CreateMemoryBitmap(targetWindowWithBordersWidth, targetWindowWithBordersHeight);
319
320 // Update windows bound
321 lastWindowWithBordersWidth = targetWindowWithBordersWidth;
322 lastWindowWithBordersHeight = targetWindowWithBordersHeight;
323 }
324
325 // Paint the window to the bitmap
326 if((targetWindowDC != 0) && (memoryBitmapDC != 0) && (memoryBitmap != 0) && (pixelsData!=0))
327 {
328 // Prepare render flags
329 LPARAM printFlags = 0|PRF_CHILDREN|PRF_CLIENT|PRF_ERASEBKGND|PRF_OWNED|PRF_NONCLIENT;
330
331 // Paint
332 SelectObject(memoryBitmapDC, memoryBitmap);
333 //PrintWindow(targetWindowHandle, memoryBitmapDC, 0);
334 SendMessage(targetWindowHandle, WM_PRINT, (WPARAM)memoryBitmapDC, printFlags);
335
336 // Create an Ogre pixel box with window data for easy streching.
337 Ogre::PixelBox scolPixelBox(targetWindowWithBordersWidth, targetWindowWithBordersHeight, 1, Ogre::PF_BYTE_BGR, pixelsData);
338
339 // Remove window borders
340 if(!drawBorders)
341 {
342 long targetWindowWithoutBordersWidth = targetWindowInfos.rcClient.right - targetWindowInfos.rcClient.left;
343 long targetWindowWithoutBordersHeight = targetWindowInfos.rcClient.bottom - targetWindowInfos.rcClient.top;
344 long xOffset = targetWindowInfos.rcClient.left - targetWindowInfos.rcWindow.left;
345 long yOffsetTop = targetWindowInfos.rcClient.top - targetWindowInfos.rcWindow.top;
346 Ogre::Box windowRectWithoutBorders(xOffset, yOffsetTop, targetWindowWithoutBordersWidth + xOffset, targetWindowWithoutBordersHeight + yOffsetTop);
347 scolPixelBox = scolPixelBox.getSubVolume(windowRectWithoutBorders);
348 }
349
350 // Lock Ogre's pixel buffer and get a pixel box
351 Ogre::HardwarePixelBufferSharedPtr pixelBuffer = renderingTexture->getBuffer();
352 pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
353 const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
354
355 // Streching obj window bitmap data to Ogre texture size. Nb that the scale function takes an optional filter parameter if we wants other filtering than bilinear
356 Ogre::Image::scale(scolPixelBox, pixelBox);
357
358 // No mipmap generation with widget.
359 pixelBuffer->unlock();
360 }
361 }
362}
363
364void SObjWindowWidget::CreateDevicesContexts()
365{
366 if(CheckWindowIsStillValid())
367 {
368 // Clean if necessary
369 DestroyDevicesContexts();
370
371 // Get target window DC
372 targetWindowDC = GetWindowDC(targetWindowHandle);
373 memoryBitmapDC = CreateCompatibleDC(targetWindowDC);
374 }
375}
376
377void SObjWindowWidget::DestroyDevicesContexts()
378{
379 // Release Devices contexts
380 if(memoryBitmapDC)
381 {
382 DeleteDC(memoryBitmapDC);
383 memoryBitmapDC = 0;
384 }
385
386 if(CheckWindowIsStillValid())
387 {
388 if(targetWindowDC)
389 {
390 ReleaseDC(targetWindowHandle, targetWindowDC);
391 targetWindowDC = 0;
392 }
393 }
394}
395
396void SObjWindowWidget::CreateMemoryBitmap(const long& targetWindowWidth, const long& targetWindowHeight)
397{
398 if(CheckWindowIsStillValid())
399 {
400 // Clean if necessary
401 DestroyMemoryBitmap();
402
403 if(targetWindowDC)
404 {
405 // Configure bitmap
406 BITMAPINFOHEADER infoHeader;
407 infoHeader.biSize = sizeof(BITMAPINFOHEADER);
408 infoHeader.biWidth = targetWindowWidth;
409 infoHeader.biHeight = -targetWindowHeight; // Negate here to avoid the "upside down" rendering.
410 infoHeader.biPlanes = 1;
411 infoHeader.biBitCount = 32;
412 infoHeader.biCompression = BI_RGB;
413
414 // dibsection information
415 BITMAPINFO info;
416 info.bmiHeader = infoHeader;
417
418 // Create bitmap
419 memoryBitmap = CreateDIBSection(targetWindowDC, &info, DIB_RGB_COLORS, (void**)&pixelsData, 0, 0);
420 }
421 }
422}
423
424void SObjWindowWidget::DestroyMemoryBitmap()
425{
426 if(memoryBitmap)
427 {
428 // Release bitmap
429 DeleteObject(memoryBitmap);
430 memoryBitmap = 0;
431 pixelsData = 0;
432 }
433}
434
435bool SObjWindowWidget::CheckWindowIsStillValid()
436{
437 bool stillValid = false;
438 if(targetWindowHandle)
439 {
440 if(IsWindow(targetWindowHandle))
441 stillValid = true;
442 else
443 targetWindowHandle = 0;
444 }
445 return stillValid;
446}
447
448bool SObjWindowWidget::GetMinimizeMaximizeAnimation()
449{
450 ANIMATIONINFO animationInfo;
451 animationInfo.cbSize = sizeof(ANIMATIONINFO);
452 SystemParametersInfo(SPI_GETANIMATION, animationInfo.cbSize, &animationInfo, 0);
453
454 // Zero value indicates no animation and a non-zero value indicates that animation is enabled
455 if (animationInfo.iMinAnimate == 0)
456 return false;
457 else
458 return true;
459}
460
461void SObjWindowWidget::SetMinimizeMaximizeAnimation(const bool& status)
462{
463 // Zero value indicates no animation and a non-zero value indicates that animation is enabled
464 if (status != GetMinimizeMaximizeAnimation())
465 {
466 // Convert bool to int safely
467 int intStatus = 0;
468 if(status)
469 intStatus = 1;
470
471 // Set new value
472 ANIMATIONINFO animationInfo;
473 animationInfo.cbSize = sizeof(ANIMATIONINFO);
474 animationInfo.iMinAnimate = intStatus;
475 SystemParametersInfo(SPI_SETANIMATION, animationInfo.cbSize, &animationInfo, SPIF_SENDCHANGE);
476 }
477}
478
479}
unsigned int UINT
Definition SO3Android.h:58
virtual void SetSizeImpl(const unsigned short &newWidth, const unsigned short &newHeight)
virtual void InjectTouchUpdate(const int &xPos, const int &yPos, const int &vx, const int &vy, const int &touchid)
virtual void InjectMouseWheel(const int &scrollX, const int &scrollY, const int &relativeScroll)
virtual void InjectTextEvent(const std::string &utf8)
virtual void SetFocusImpl(const bool &focusOnWidget)
virtual bool CheckPixelAlpha(const int &posX, const int &posY)
virtual void SetKeyboardEnableImpl(const bool &enableKeyboardOnWidget)
virtual void InjectMouseUp(const int &xPos, const int &yPos, const MouseButtonId &button)
void SetBorderVisible(const bool &drawBordersEnable)
virtual void InjectKeyEvent(const UINT &msg, const ScolWindowHandle &hwnd, const WPARAM &wParam, const LPARAM &lParam)
virtual void InjectTouchRemove(const int &touchid)
virtual void InjectMouseMove(const int &xPos, const int &yPos, const MouseButtonId &button)
virtual void SetMouseEnableImpl(const bool &enableMouseOnWidget)
virtual void SetTransparencyImpl(const bool &enableTransparency)
virtual void InjectTouchAdd(const int &xPos, const int &yPos, const int &touchid)
void SetTargetWindow(const ScolWindowHandle &targetWindowHandlePtr)
virtual void RunScriptFunction(const std::string &functionName, const std::vector< std::string > &argumentList)
virtual void LoadURL(const std::string &url)
virtual void InjectMouseDown(const int &xPos, const int &yPos, const MouseButtonId &button)
SObjWindowWidget(SScene *targetScene, const std::string &bitmapWidgetName, const int &xPos, const int &yPos, const unsigned short &widgetWidth, const unsigned short &widgetHeight, SViewPort *targetViewport, const unsigned int &widgetZOrder)
virtual void LoadFile(const std::string &file)
unsigned short width
Definition SO3Widget.h:80
Ogre::TexturePtr renderingTexture
Definition SO3Widget.h:88
unsigned short height
Definition SO3Widget.h:81
void _FireOnLoadError(SWidget *targetedWidget, const int &errorCode, const std::string &failedUrl)
static SWidgetManager & getSingleton()
@ MOUSE_RIGHT_BUTTON
@ MOUSE_MIDDLE_BUTTON
@ MOUSE_LEFT_BUTTON