Mercurial > hg > orthanc-stone
comparison Samples/Common/RtViewer.cpp @ 1392:ffdb82850e98
Sdl run loop in /Common (might revert if need to customize)
Segregation ongoing between sdl wasm
Both samples ok SDL msvc v141 x64
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Tue, 28 Apr 2020 13:52:21 +0200 |
parents | 5c83be3a6be5 |
children | 27e0a00bd3e8 |
comparison
equal
deleted
inserted
replaced
1391:32272ecfc6c2 | 1392:ffdb82850e98 |
---|---|
20 | 20 |
21 // Sample app | 21 // Sample app |
22 #include "RtViewer.h" | 22 #include "RtViewer.h" |
23 | 23 |
24 // Stone of Orthanc | 24 // Stone of Orthanc |
25 #include <Framework/OpenGL/SdlOpenGLContext.h> | |
26 #include <Framework/StoneInitialization.h> | 25 #include <Framework/StoneInitialization.h> |
27 #include <Framework/Scene2D/CairoCompositor.h> | 26 #include <Framework/Scene2D/CairoCompositor.h> |
28 #include <Framework/Scene2D/ColorTextureSceneLayer.h> | 27 #include <Framework/Scene2D/ColorTextureSceneLayer.h> |
29 #include <Framework/Scene2D/OpenGLCompositor.h> | 28 #include <Framework/Scene2D/OpenGLCompositor.h> |
30 #include <Framework/Scene2D/PanSceneTracker.h> | 29 #include <Framework/Scene2D/PanSceneTracker.h> |
174 Scene2D& scene = controller.GetScene(); | 173 Scene2D& scene = controller.GetScene(); |
175 | 174 |
176 scene.DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); | 175 scene.DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); |
177 } | 176 } |
178 | 177 |
179 void RtViewerApp::HandleApplicationEvent( | 178 |
180 const SDL_Event& event) | |
181 { | |
182 //DisplayInfoText(); | |
183 | |
184 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); | |
185 ViewportController& controller = lock->GetController(); | |
186 Scene2D& scene = controller.GetScene(); | |
187 ICompositor& compositor = lock->GetCompositor(); | |
188 | |
189 if (event.type == SDL_MOUSEMOTION) | |
190 { | |
191 int scancodeCount = 0; | |
192 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); | |
193 | |
194 if (activeTracker_.get() == NULL && | |
195 SDL_SCANCODE_LALT < scancodeCount && | |
196 keyboardState[SDL_SCANCODE_LALT]) | |
197 { | |
198 // The "left-ctrl" key is down, while no tracker is present | |
199 // Let's display the info text | |
200 PointerEvent e; | |
201 e.AddPosition(compositor.GetPixelCenterCoordinates( | |
202 event.button.x, event.button.y)); | |
203 | |
204 DisplayFloatingCtrlInfoText(e); | |
205 } | |
206 else | |
207 { | |
208 HideInfoText(); | |
209 //LOG(TRACE) << "(event.type == SDL_MOUSEMOTION)"; | |
210 if (activeTracker_.get() != NULL) | |
211 { | |
212 //LOG(TRACE) << "(activeTracker_.get() != NULL)"; | |
213 PointerEvent e; | |
214 e.AddPosition(compositor.GetPixelCenterCoordinates( | |
215 event.button.x, event.button.y)); | |
216 | |
217 //LOG(TRACE) << "event.button.x = " << event.button.x << " " << | |
218 // "event.button.y = " << event.button.y; | |
219 LOG(TRACE) << "activeTracker_->PointerMove(e); " << | |
220 e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); | |
221 | |
222 activeTracker_->PointerMove(e); | |
223 if (!activeTracker_->IsAlive()) | |
224 activeTracker_.reset(); | |
225 } | |
226 } | |
227 } | |
228 else if (event.type == SDL_MOUSEBUTTONUP) | |
229 { | |
230 if (activeTracker_) | |
231 { | |
232 PointerEvent e; | |
233 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); | |
234 activeTracker_->PointerUp(e); | |
235 if (!activeTracker_->IsAlive()) | |
236 activeTracker_.reset(); | |
237 } | |
238 } | |
239 else if (event.type == SDL_MOUSEBUTTONDOWN) | |
240 { | |
241 PointerEvent e; | |
242 e.AddPosition(compositor.GetPixelCenterCoordinates( | |
243 event.button.x, event.button.y)); | |
244 if (activeTracker_) | |
245 { | |
246 activeTracker_->PointerDown(e); | |
247 if (!activeTracker_->IsAlive()) | |
248 activeTracker_.reset(); | |
249 } | |
250 else | |
251 { | |
252 // we ATTEMPT to create a tracker if need be | |
253 activeTracker_ = CreateSuitableTracker(event, e); | |
254 } | |
255 } | |
256 else if (event.type == SDL_KEYDOWN && | |
257 event.key.repeat == 0 /* Ignore key bounce */) | |
258 { | |
259 switch (event.key.keysym.sym) | |
260 { | |
261 case SDLK_ESCAPE: | |
262 if (activeTracker_) | |
263 { | |
264 activeTracker_->Cancel(); | |
265 if (!activeTracker_->IsAlive()) | |
266 activeTracker_.reset(); | |
267 } | |
268 break; | |
269 | |
270 case SDLK_r: | |
271 UpdateLayers(); | |
272 { | |
273 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); | |
274 lock->Invalidate(); | |
275 } | |
276 break; | |
277 | |
278 case SDLK_s: | |
279 compositor.FitContent(scene); | |
280 break; | |
281 | |
282 case SDLK_t: | |
283 if (!activeTracker_) | |
284 SelectNextTool(); | |
285 else | |
286 { | |
287 LOG(WARNING) << "You cannot change the active tool when an interaction" | |
288 " is taking place"; | |
289 } | |
290 break; | |
291 | |
292 case SDLK_z: | |
293 LOG(TRACE) << "SDLK_z has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; | |
294 if (event.key.keysym.mod & KMOD_CTRL) | |
295 { | |
296 if (controller.CanUndo()) | |
297 { | |
298 LOG(TRACE) << "Undoing..."; | |
299 controller.Undo(); | |
300 } | |
301 else | |
302 { | |
303 LOG(WARNING) << "Nothing to undo!!!"; | |
304 } | |
305 } | |
306 break; | |
307 | |
308 case SDLK_y: | |
309 LOG(TRACE) << "SDLK_y has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; | |
310 if (event.key.keysym.mod & KMOD_CTRL) | |
311 { | |
312 if (controller.CanRedo()) | |
313 { | |
314 LOG(TRACE) << "Redoing..."; | |
315 controller.Redo(); | |
316 } | |
317 else | |
318 { | |
319 LOG(WARNING) << "Nothing to redo!!!"; | |
320 } | |
321 } | |
322 break; | |
323 | |
324 case SDLK_c: | |
325 TakeScreenshot( | |
326 "screenshot.png", | |
327 compositor.GetCanvasWidth(), | |
328 compositor.GetCanvasHeight()); | |
329 break; | |
330 | |
331 default: | |
332 break; | |
333 } | |
334 } | |
335 else if (viewport_->IsRefreshEvent(event)) | |
336 { | |
337 // the viewport has been invalidated and requires repaint | |
338 viewport_->Paint(); | |
339 } | |
340 } | |
341 | 179 |
342 void RtViewerApp::OnSceneTransformChanged( | 180 void RtViewerApp::OnSceneTransformChanged( |
343 const ViewportController::SceneTransformChanged& message) | 181 const ViewportController::SceneTransformChanged& message) |
344 { | 182 { |
345 DisplayInfoText(); | 183 DisplayInfoText(); |
401 } | 239 } |
402 } | 240 } |
403 lock->Invalidate(); | 241 lock->Invalidate(); |
404 } | 242 } |
405 | 243 |
406 boost::shared_ptr<IFlexiblePointerTracker> RtViewerApp::CreateSuitableTracker( | |
407 const SDL_Event& event, | |
408 const PointerEvent& e) | |
409 { | |
410 std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); | |
411 ViewportController& controller = lock->GetController(); | |
412 Scene2D& scene = controller.GetScene(); | |
413 ICompositor& compositor = lock->GetCompositor(); | |
414 | |
415 using namespace Orthanc; | |
416 | |
417 switch (event.button.button) | |
418 { | |
419 case SDL_BUTTON_MIDDLE: | |
420 return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker | |
421 (viewport_, e)); | |
422 | |
423 case SDL_BUTTON_RIGHT: | |
424 return boost::shared_ptr<IFlexiblePointerTracker>(new ZoomSceneTracker | |
425 (viewport_, e, compositor.GetCanvasHeight())); | |
426 | |
427 case SDL_BUTTON_LEFT: | |
428 { | |
429 //LOG(TRACE) << "CreateSuitableTracker: case SDL_BUTTON_LEFT:"; | |
430 // TODO: we need to iterate on the set of measuring tool and perform | |
431 // a hit test to check if a tracker needs to be created for edition. | |
432 // Otherwise, depending upon the active tool, we might want to create | |
433 // a "measuring tool creation" tracker | |
434 | |
435 // TODO: if there are conflicts, we should prefer a tracker that | |
436 // pertains to the type of measuring tool currently selected (TBD?) | |
437 boost::shared_ptr<IFlexiblePointerTracker> hitTestTracker = TrackerHitTest(e); | |
438 | |
439 if (hitTestTracker != NULL) | |
440 { | |
441 //LOG(TRACE) << "hitTestTracker != NULL"; | |
442 return hitTestTracker; | |
443 } | |
444 else | |
445 { | |
446 switch (currentTool_) | |
447 { | |
448 case RtViewerGuiTool_Rotate: | |
449 //LOG(TRACE) << "Creating RotateSceneTracker"; | |
450 return boost::shared_ptr<IFlexiblePointerTracker>(new RotateSceneTracker(viewport_, e)); | |
451 case RtViewerGuiTool_Pan: | |
452 return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker(viewport_, e)); | |
453 case RtViewerGuiTool_Zoom: | |
454 return boost::shared_ptr<IFlexiblePointerTracker>(new ZoomSceneTracker(viewport_, e, compositor.GetCanvasHeight())); | |
455 //case GuiTool_AngleMeasure: | |
456 // return new AngleMeasureTracker(GetScene(), e); | |
457 //case GuiTool_CircleMeasure: | |
458 // return new CircleMeasureTracker(GetScene(), e); | |
459 //case GuiTool_EllipseMeasure: | |
460 // return new EllipseMeasureTracker(GetScene(), e); | |
461 case RtViewerGuiTool_LineMeasure: | |
462 return boost::shared_ptr<IFlexiblePointerTracker>(new CreateLineMeasureTracker(viewport_, e)); | |
463 case RtViewerGuiTool_AngleMeasure: | |
464 return boost::shared_ptr<IFlexiblePointerTracker>(new CreateAngleMeasureTracker(viewport_, e)); | |
465 case RtViewerGuiTool_CircleMeasure: | |
466 LOG(ERROR) << "Not implemented yet!"; | |
467 return boost::shared_ptr<IFlexiblePointerTracker>(); | |
468 case RtViewerGuiTool_EllipseMeasure: | |
469 LOG(ERROR) << "Not implemented yet!"; | |
470 return boost::shared_ptr<IFlexiblePointerTracker>(); | |
471 default: | |
472 throw OrthancException(ErrorCode_InternalError, "Wrong tool!"); | |
473 } | |
474 } | |
475 } | |
476 default: | |
477 return boost::shared_ptr<IFlexiblePointerTracker>(); | |
478 } | |
479 } | |
480 | 244 |
481 | 245 |
482 RtViewerApp::RtViewerApp() | 246 RtViewerApp::RtViewerApp() |
483 : currentTool_(RtViewerGuiTool_Rotate) | 247 : currentTool_(RtViewerGuiTool_Rotate) |
484 , undoStack_(new UndoStack) | 248 , undoStack_(new UndoStack) |
791 infoTextMap_.erase(key); | 555 infoTextMap_.erase(key); |
792 else | 556 else |
793 infoTextMap_[key] = value; | 557 infoTextMap_[key] = value; |
794 DisplayInfoText(); | 558 DisplayInfoText(); |
795 } | 559 } |
796 | |
797 } | 560 } |
798 | 561 |
799 | |
800 boost::weak_ptr<OrthancStone::RtViewerApp> g_app; | |
801 | |
802 void RtViewer_SetInfoDisplayMessage(std::string key, std::string value) | |
803 { | |
804 boost::shared_ptr<OrthancStone::RtViewerApp> app = g_app.lock(); | |
805 if (app) | |
806 { | |
807 app->SetInfoDisplayMessage(key, value); | |
808 } | |
809 } | |
810 | |
811 /** | |
812 * IMPORTANT: The full arguments to "main()" are needed for SDL on | |
813 * Windows. Otherwise, one gets the linking error "undefined reference | |
814 * to `SDL_main'". https://wiki.libsdl.org/FAQWindows | |
815 **/ | |
816 int main(int argc, char* argv[]) | |
817 { | |
818 using namespace OrthancStone; | |
819 | |
820 StoneInitialize(); | |
821 | |
822 try | |
823 { | |
824 boost::shared_ptr<RtViewerApp> app = RtViewerApp::Create(); | |
825 g_app = app; | |
826 app->RunSdl(argc,argv); | |
827 } | |
828 catch (Orthanc::OrthancException& e) | |
829 { | |
830 LOG(ERROR) << "EXCEPTION: " << e.What(); | |
831 } | |
832 | |
833 StoneFinalize(); | |
834 | |
835 return 0; | |
836 } | |
837 | |
838 |