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