1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #include "RenderAPI/BsRenderWindow.h" |
4 | #include "CoreThread/BsCoreThread.h" |
5 | #include "Managers/BsRenderWindowManager.h" |
6 | #include "RenderAPI/BsViewport.h" |
7 | #include "Platform/BsPlatform.h" |
8 | #include "Private/RTTI/BsRenderTargetRTTI.h" |
9 | |
10 | namespace bs |
11 | { |
12 | RenderWindowProperties::RenderWindowProperties(const RENDER_WINDOW_DESC& desc) |
13 | { |
14 | width = desc.videoMode.width; |
15 | height = desc.videoMode.height; |
16 | hwGamma = desc.gamma; |
17 | vsync = desc.vsync; |
18 | vsyncInterval = desc.vsyncInterval; |
19 | multisampleCount = desc.multisampleCount; |
20 | left = desc.left; |
21 | top = desc.top; |
22 | isFullScreen = desc.fullscreen; |
23 | isHidden = desc.hidden; |
24 | isModal = desc.modal; |
25 | isWindow = true; |
26 | requiresTextureFlipping = false; |
27 | } |
28 | |
29 | void RenderWindow::destroy() |
30 | { |
31 | RenderWindowManager::instance().notifyWindowDestroyed(this); |
32 | |
33 | RenderTarget::destroy(); |
34 | } |
35 | |
36 | RenderWindow::RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId) |
37 | :mDesc(desc), mWindowId(windowId) |
38 | { |
39 | |
40 | } |
41 | |
42 | void RenderWindow::resize(UINT32 width, UINT32 height) |
43 | { |
44 | std::function<void(SPtr<ct::RenderWindow>, UINT32, UINT32)> resizeFunc = |
45 | [](SPtr<ct::RenderWindow> renderWindow, UINT32 width, UINT32 height) |
46 | { |
47 | renderWindow->resize(width, height); |
48 | }; |
49 | |
50 | gCoreThread().queueCommand(std::bind(resizeFunc, getCore(), width, height)); |
51 | gCoreThread().submit(true); |
52 | |
53 | { |
54 | ScopedSpinLock lock(getCore()->mLock); |
55 | const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties(); |
56 | RenderWindowProperties& mutableProps = getMutableProperties(); |
57 | |
58 | mutableProps.width = syncedProps.width; |
59 | mutableProps.height = syncedProps.height; |
60 | } |
61 | } |
62 | |
63 | void RenderWindow::move(INT32 left, INT32 top) |
64 | { |
65 | std::function<void(SPtr<ct::RenderWindow>, INT32, INT32)> moveFunc = |
66 | [](SPtr<ct::RenderWindow> renderWindow, INT32 left, INT32 top) |
67 | { |
68 | renderWindow->move(left, top); |
69 | }; |
70 | |
71 | gCoreThread().queueCommand(std::bind(moveFunc, getCore(), left, top)); |
72 | gCoreThread().submit(true); |
73 | |
74 | { |
75 | ScopedSpinLock lock(getCore()->mLock); |
76 | const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties(); |
77 | RenderWindowProperties& mutableProps = getMutableProperties(); |
78 | |
79 | mutableProps.left = syncedProps.left; |
80 | mutableProps.top = syncedProps.top; |
81 | } |
82 | } |
83 | |
84 | void RenderWindow::hide() |
85 | { |
86 | std::function<void(SPtr<ct::RenderWindow>)> hideFunc = |
87 | [](SPtr<ct::RenderWindow> renderWindow) |
88 | { |
89 | renderWindow->setHidden(true); |
90 | }; |
91 | |
92 | getMutableProperties().isHidden = true; |
93 | |
94 | gCoreThread().queueCommand(std::bind(hideFunc, getCore())); |
95 | } |
96 | |
97 | void RenderWindow::show() |
98 | { |
99 | std::function<void(SPtr<ct::RenderWindow>)> showFunc = |
100 | [](SPtr<ct::RenderWindow> renderWindow) |
101 | { |
102 | renderWindow->setHidden(false); |
103 | }; |
104 | |
105 | getMutableProperties().isHidden = false; |
106 | |
107 | gCoreThread().queueCommand(std::bind(showFunc, getCore())); |
108 | } |
109 | |
110 | void RenderWindow::minimize() |
111 | { |
112 | std::function<void(SPtr<ct::RenderWindow>)> minimizeFunc = |
113 | [](SPtr<ct::RenderWindow> renderWindow) |
114 | { |
115 | renderWindow->minimize(); |
116 | }; |
117 | |
118 | getMutableProperties().isMaximized = false; |
119 | |
120 | gCoreThread().queueCommand(std::bind(minimizeFunc, getCore())); |
121 | } |
122 | |
123 | void RenderWindow::maximize() |
124 | { |
125 | std::function<void(SPtr<ct::RenderWindow>)> maximizeFunc = |
126 | [](SPtr<ct::RenderWindow> renderWindow) |
127 | { |
128 | renderWindow->maximize(); |
129 | }; |
130 | |
131 | getMutableProperties().isMaximized = true; |
132 | |
133 | gCoreThread().queueCommand(std::bind(maximizeFunc, getCore())); |
134 | gCoreThread().submit(true); |
135 | |
136 | { |
137 | ScopedSpinLock lock(getCore()->mLock); |
138 | const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties(); |
139 | RenderWindowProperties& mutableProps = getMutableProperties(); |
140 | |
141 | mutableProps.width = syncedProps.width; |
142 | mutableProps.height = syncedProps.height; |
143 | } |
144 | } |
145 | |
146 | void RenderWindow::restore() |
147 | { |
148 | std::function<void(SPtr<ct::RenderWindow>)> restoreFunc = |
149 | [](SPtr<ct::RenderWindow> renderWindow) |
150 | { |
151 | renderWindow->restore(); |
152 | }; |
153 | |
154 | getMutableProperties().isMaximized = false; |
155 | |
156 | gCoreThread().queueCommand(std::bind(restoreFunc, getCore())); |
157 | gCoreThread().submit(true); |
158 | |
159 | { |
160 | ScopedSpinLock lock(getCore()->mLock); |
161 | const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties(); |
162 | RenderWindowProperties& mutableProps = getMutableProperties(); |
163 | |
164 | mutableProps.width = syncedProps.width; |
165 | mutableProps.height = syncedProps.height; |
166 | } |
167 | } |
168 | |
169 | void RenderWindow::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx) |
170 | { |
171 | std::function<void(SPtr<ct::RenderWindow>, UINT32, UINT32, float, UINT32)> fullscreenFunc = |
172 | [](SPtr<ct::RenderWindow> renderWindow, UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx) |
173 | { |
174 | renderWindow->setFullscreen(width, height, refreshRate, monitorIdx); |
175 | }; |
176 | |
177 | gCoreThread().queueCommand(std::bind(fullscreenFunc, getCore(), width, height, refreshRate, monitorIdx)); |
178 | gCoreThread().submit(true); |
179 | |
180 | { |
181 | ScopedSpinLock lock(getCore()->mLock); |
182 | const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties(); |
183 | RenderWindowProperties& mutableProps = getMutableProperties(); |
184 | |
185 | mutableProps.width = syncedProps.width; |
186 | mutableProps.height = syncedProps.height; |
187 | } |
188 | } |
189 | |
190 | void RenderWindow::setFullscreen(const VideoMode& mode) |
191 | { |
192 | std::function<void(SPtr<ct::RenderWindow>, const VideoMode&)> fullscreenFunc = |
193 | [](SPtr<ct::RenderWindow> renderWindow, const VideoMode& mode) |
194 | { |
195 | renderWindow->setFullscreen(mode); |
196 | }; |
197 | |
198 | gCoreThread().queueCommand(std::bind(fullscreenFunc, getCore(), std::cref(mode))); |
199 | gCoreThread().submit(true); |
200 | |
201 | { |
202 | ScopedSpinLock lock(getCore()->mLock); |
203 | const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties(); |
204 | RenderWindowProperties& mutableProps = getMutableProperties(); |
205 | |
206 | mutableProps.width = syncedProps.width; |
207 | mutableProps.height = syncedProps.height; |
208 | } |
209 | } |
210 | |
211 | void RenderWindow::setWindowed(UINT32 width, UINT32 height) |
212 | { |
213 | std::function<void(SPtr<ct::RenderWindow>, UINT32, UINT32)> windowedFunc = |
214 | [](SPtr<ct::RenderWindow> renderWindow, UINT32 width, UINT32 height) |
215 | { |
216 | renderWindow->setWindowed(width, height); |
217 | }; |
218 | |
219 | gCoreThread().queueCommand(std::bind(windowedFunc, getCore(), width, height)); |
220 | gCoreThread().submit(true); |
221 | |
222 | { |
223 | ScopedSpinLock lock(getCore()->mLock); |
224 | const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties(); |
225 | RenderWindowProperties& mutableProps = getMutableProperties(); |
226 | |
227 | mutableProps.width = syncedProps.width; |
228 | mutableProps.height = syncedProps.height; |
229 | } |
230 | } |
231 | |
232 | SPtr<ct::RenderWindow> RenderWindow::getCore() const |
233 | { |
234 | return std::static_pointer_cast<ct::RenderWindow>(mCoreSpecific); |
235 | } |
236 | |
237 | SPtr<RenderWindow> RenderWindow::create(RENDER_WINDOW_DESC& desc, SPtr<RenderWindow> parentWindow) |
238 | { |
239 | return RenderWindowManager::instance().create(desc, parentWindow); |
240 | } |
241 | |
242 | RenderWindowProperties& RenderWindow::getMutableProperties() |
243 | { |
244 | return const_cast<RenderWindowProperties&>(getProperties()); |
245 | } |
246 | |
247 | const RenderWindowProperties& RenderWindow::getProperties() const |
248 | { |
249 | return static_cast<const RenderWindowProperties&>(getPropertiesInternal()); |
250 | } |
251 | |
252 | void RenderWindow::_notifyWindowEvent(WindowEventType type) |
253 | { |
254 | THROW_IF_CORE_THREAD; |
255 | |
256 | ct::RenderWindow* coreWindow = getCore().get(); |
257 | RenderWindowProperties& syncProps = coreWindow->getSyncedProperties(); |
258 | RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties()); |
259 | |
260 | switch(type) |
261 | { |
262 | case WindowEventType::Resized: |
263 | { |
264 | _windowMovedOrResized(); |
265 | |
266 | { |
267 | ScopedSpinLock lock(coreWindow->mLock); |
268 | syncProps.width = props.width; |
269 | syncProps.height = props.height; |
270 | } |
271 | |
272 | ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow); |
273 | RenderWindowManager::instance().notifyMovedOrResized(coreWindow); |
274 | |
275 | break; |
276 | } |
277 | case WindowEventType::Moved: |
278 | { |
279 | _windowMovedOrResized(); |
280 | |
281 | { |
282 | ScopedSpinLock lock(coreWindow->mLock); |
283 | syncProps.top = props.top; |
284 | syncProps.left = props.left; |
285 | } |
286 | |
287 | ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow); |
288 | RenderWindowManager::instance().notifyMovedOrResized(coreWindow); |
289 | |
290 | break; |
291 | } |
292 | case WindowEventType::FocusReceived: |
293 | { |
294 | { |
295 | ScopedSpinLock lock(coreWindow->mLock); |
296 | syncProps.hasFocus = true; |
297 | } |
298 | |
299 | props.hasFocus = true; |
300 | |
301 | ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow); |
302 | RenderWindowManager::instance().notifyFocusReceived(coreWindow); |
303 | break; |
304 | } |
305 | case WindowEventType::FocusLost: |
306 | { |
307 | { |
308 | ScopedSpinLock lock(coreWindow->mLock); |
309 | syncProps.hasFocus = false; |
310 | } |
311 | |
312 | props.hasFocus = false; |
313 | |
314 | ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow); |
315 | RenderWindowManager::instance().notifyFocusLost(coreWindow); |
316 | break; |
317 | } |
318 | case WindowEventType::Minimized: |
319 | { |
320 | { |
321 | ScopedSpinLock lock(coreWindow->mLock); |
322 | syncProps.isMaximized = false; |
323 | } |
324 | |
325 | props.isMaximized = false; |
326 | |
327 | ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow); |
328 | break; |
329 | } |
330 | case WindowEventType::Maximized: |
331 | { |
332 | { |
333 | ScopedSpinLock lock(coreWindow->mLock); |
334 | syncProps.isMaximized = true; |
335 | } |
336 | |
337 | props.isMaximized = true; |
338 | |
339 | ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow); |
340 | break; |
341 | } |
342 | case WindowEventType::Restored: |
343 | { |
344 | { |
345 | ScopedSpinLock lock(coreWindow->mLock); |
346 | syncProps.isMaximized = false; |
347 | } |
348 | |
349 | props.isMaximized = false; |
350 | |
351 | ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow); |
352 | break; |
353 | } |
354 | case WindowEventType::MouseLeft: |
355 | { |
356 | RenderWindowManager::instance().notifyMouseLeft(coreWindow); |
357 | break; |
358 | } |
359 | case WindowEventType::CloseRequested: |
360 | { |
361 | RenderWindowManager::instance().notifyCloseRequested(coreWindow); |
362 | break; |
363 | } |
364 | } |
365 | } |
366 | |
367 | /************************************************************************/ |
368 | /* SERIALIZATION */ |
369 | /************************************************************************/ |
370 | |
371 | RTTITypeBase* RenderWindow::getRTTIStatic() |
372 | { |
373 | return RenderWindowRTTI::instance(); |
374 | } |
375 | |
376 | RTTITypeBase* RenderWindow::getRTTI() const |
377 | { |
378 | return RenderWindow::getRTTIStatic(); |
379 | } |
380 | |
381 | namespace ct |
382 | { |
383 | RenderWindow::RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId) |
384 | :mDesc(desc), mWindowId(windowId) |
385 | { |
386 | RenderWindowManager::instance().windowCreated(this); |
387 | } |
388 | |
389 | RenderWindow::~RenderWindow() |
390 | { |
391 | RenderWindowManager::instance().windowDestroyed(this); |
392 | } |
393 | |
394 | void RenderWindow::setHidden(bool hidden) |
395 | { |
396 | THROW_IF_NOT_CORE_THREAD; |
397 | |
398 | RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties()); |
399 | |
400 | props.isHidden = hidden; |
401 | { |
402 | ScopedSpinLock lock(mLock); |
403 | getSyncedProperties().isHidden = hidden; |
404 | } |
405 | |
406 | bs::RenderWindowManager::instance().notifySyncDataDirty(this); |
407 | } |
408 | |
409 | void RenderWindow::setActive(bool state) |
410 | { |
411 | THROW_IF_NOT_CORE_THREAD; |
412 | } |
413 | |
414 | void RenderWindow::_notifyWindowEvent(WindowEventType type) |
415 | { |
416 | THROW_IF_NOT_CORE_THREAD; |
417 | |
418 | RenderWindowProperties& syncProps = getSyncedProperties(); |
419 | RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties()); |
420 | |
421 | switch(type) |
422 | { |
423 | case WindowEventType::Resized: |
424 | { |
425 | _windowMovedOrResized(); |
426 | |
427 | { |
428 | ScopedSpinLock lock(mLock); |
429 | syncProps.width = props.width; |
430 | syncProps.height = props.height; |
431 | } |
432 | |
433 | bs::RenderWindowManager::instance().notifySyncDataDirty(this); |
434 | bs::RenderWindowManager::instance().notifyMovedOrResized(this); |
435 | |
436 | break; |
437 | } |
438 | case WindowEventType::Moved: |
439 | { |
440 | _windowMovedOrResized(); |
441 | |
442 | { |
443 | ScopedSpinLock lock(mLock); |
444 | syncProps.top = props.top; |
445 | syncProps.left = props.left; |
446 | } |
447 | |
448 | bs::RenderWindowManager::instance().notifySyncDataDirty(this); |
449 | bs::RenderWindowManager::instance().notifyMovedOrResized(this); |
450 | |
451 | break; |
452 | } |
453 | case WindowEventType::FocusReceived: |
454 | { |
455 | { |
456 | ScopedSpinLock lock(mLock); |
457 | syncProps.hasFocus = true; |
458 | } |
459 | |
460 | props.hasFocus = true; |
461 | |
462 | bs::RenderWindowManager::instance().notifySyncDataDirty(this); |
463 | bs::RenderWindowManager::instance().notifyFocusReceived(this); |
464 | break; |
465 | } |
466 | case WindowEventType::FocusLost: |
467 | { |
468 | { |
469 | ScopedSpinLock lock(mLock); |
470 | syncProps.hasFocus = false; |
471 | } |
472 | |
473 | props.hasFocus = false; |
474 | |
475 | bs::RenderWindowManager::instance().notifySyncDataDirty(this); |
476 | bs::RenderWindowManager::instance().notifyFocusLost(this); |
477 | break; |
478 | } |
479 | case WindowEventType::Minimized: |
480 | { |
481 | { |
482 | ScopedSpinLock lock(mLock); |
483 | syncProps.isMaximized = false; |
484 | } |
485 | |
486 | props.isMaximized = false; |
487 | |
488 | bs::RenderWindowManager::instance().notifySyncDataDirty(this); |
489 | break; |
490 | } |
491 | case WindowEventType::Maximized: |
492 | { |
493 | { |
494 | ScopedSpinLock lock(mLock); |
495 | syncProps.isMaximized = true; |
496 | } |
497 | |
498 | props.isMaximized = true; |
499 | |
500 | bs::RenderWindowManager::instance().notifySyncDataDirty(this); |
501 | break; |
502 | } |
503 | case WindowEventType::Restored: |
504 | { |
505 | { |
506 | ScopedSpinLock lock(mLock); |
507 | syncProps.isMaximized = false; |
508 | } |
509 | |
510 | props.isMaximized = false; |
511 | |
512 | bs::RenderWindowManager::instance().notifySyncDataDirty(this); |
513 | break; |
514 | } |
515 | case WindowEventType::MouseLeft: |
516 | { |
517 | bs::RenderWindowManager::instance().notifyMouseLeft(this); |
518 | break; |
519 | } |
520 | case WindowEventType::CloseRequested: |
521 | { |
522 | bs::RenderWindowManager::instance().notifyCloseRequested(this); |
523 | break; |
524 | } |
525 | } |
526 | } |
527 | |
528 | const RenderWindowProperties& RenderWindow::getProperties() const |
529 | { |
530 | return static_cast<const RenderWindowProperties&>(getPropertiesInternal()); |
531 | } |
532 | } |
533 | } |
534 | |