# HG changeset patch # User Benjamin Golinvaux # Date 1588074741 -7200 # Node ID ffdb82850e983078a9a9f0790a961e27c166c1d1 # Parent 32272ecfc6c2995ae4928b20d1f1af8e30e5fd41 Sdl run loop in /Common (might revert if need to customize) Segregation ongoing between sdl wasm Both samples ok SDL msvc v141 x64 diff -r 32272ecfc6c2 -r ffdb82850e98 Samples/Common/RtViewer.cpp --- a/Samples/Common/RtViewer.cpp Tue Apr 28 13:26:41 2020 +0200 +++ b/Samples/Common/RtViewer.cpp Tue Apr 28 13:52:21 2020 +0200 @@ -22,7 +22,6 @@ #include "RtViewer.h" // Stone of Orthanc -#include #include #include #include @@ -176,168 +175,7 @@ scene.DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); } - void RtViewerApp::HandleApplicationEvent( - const SDL_Event& event) - { - //DisplayInfoText(); - std::unique_ptr lock(viewport_->Lock()); - ViewportController& controller = lock->GetController(); - Scene2D& scene = controller.GetScene(); - ICompositor& compositor = lock->GetCompositor(); - - if (event.type == SDL_MOUSEMOTION) - { - int scancodeCount = 0; - const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - - if (activeTracker_.get() == NULL && - SDL_SCANCODE_LALT < scancodeCount && - keyboardState[SDL_SCANCODE_LALT]) - { - // The "left-ctrl" key is down, while no tracker is present - // Let's display the info text - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates( - event.button.x, event.button.y)); - - DisplayFloatingCtrlInfoText(e); - } - else - { - HideInfoText(); - //LOG(TRACE) << "(event.type == SDL_MOUSEMOTION)"; - if (activeTracker_.get() != NULL) - { - //LOG(TRACE) << "(activeTracker_.get() != NULL)"; - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates( - event.button.x, event.button.y)); - - //LOG(TRACE) << "event.button.x = " << event.button.x << " " << - // "event.button.y = " << event.button.y; - LOG(TRACE) << "activeTracker_->PointerMove(e); " << - e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); - - activeTracker_->PointerMove(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - } - } - else if (event.type == SDL_MOUSEBUTTONUP) - { - if (activeTracker_) - { - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - activeTracker_->PointerUp(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - } - else if (event.type == SDL_MOUSEBUTTONDOWN) - { - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates( - event.button.x, event.button.y)); - if (activeTracker_) - { - activeTracker_->PointerDown(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - else - { - // we ATTEMPT to create a tracker if need be - activeTracker_ = CreateSuitableTracker(event, e); - } - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_ESCAPE: - if (activeTracker_) - { - activeTracker_->Cancel(); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - break; - - case SDLK_r: - UpdateLayers(); - { - std::unique_ptr lock(viewport_->Lock()); - lock->Invalidate(); - } - break; - - case SDLK_s: - compositor.FitContent(scene); - break; - - case SDLK_t: - if (!activeTracker_) - SelectNextTool(); - else - { - LOG(WARNING) << "You cannot change the active tool when an interaction" - " is taking place"; - } - break; - - case SDLK_z: - LOG(TRACE) << "SDLK_z has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; - if (event.key.keysym.mod & KMOD_CTRL) - { - if (controller.CanUndo()) - { - LOG(TRACE) << "Undoing..."; - controller.Undo(); - } - else - { - LOG(WARNING) << "Nothing to undo!!!"; - } - } - break; - - case SDLK_y: - LOG(TRACE) << "SDLK_y has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; - if (event.key.keysym.mod & KMOD_CTRL) - { - if (controller.CanRedo()) - { - LOG(TRACE) << "Redoing..."; - controller.Redo(); - } - else - { - LOG(WARNING) << "Nothing to redo!!!"; - } - } - break; - - case SDLK_c: - TakeScreenshot( - "screenshot.png", - compositor.GetCanvasWidth(), - compositor.GetCanvasHeight()); - break; - - default: - break; - } - } - else if (viewport_->IsRefreshEvent(event)) - { - // the viewport has been invalidated and requires repaint - viewport_->Paint(); - } - } void RtViewerApp::OnSceneTransformChanged( const ViewportController::SceneTransformChanged& message) @@ -403,80 +241,6 @@ lock->Invalidate(); } - boost::shared_ptr RtViewerApp::CreateSuitableTracker( - const SDL_Event& event, - const PointerEvent& e) - { - std::unique_ptr lock(viewport_->Lock()); - ViewportController& controller = lock->GetController(); - Scene2D& scene = controller.GetScene(); - ICompositor& compositor = lock->GetCompositor(); - - using namespace Orthanc; - - switch (event.button.button) - { - case SDL_BUTTON_MIDDLE: - return boost::shared_ptr(new PanSceneTracker - (viewport_, e)); - - case SDL_BUTTON_RIGHT: - return boost::shared_ptr(new ZoomSceneTracker - (viewport_, e, compositor.GetCanvasHeight())); - - case SDL_BUTTON_LEFT: - { - //LOG(TRACE) << "CreateSuitableTracker: case SDL_BUTTON_LEFT:"; - // TODO: we need to iterate on the set of measuring tool and perform - // a hit test to check if a tracker needs to be created for edition. - // Otherwise, depending upon the active tool, we might want to create - // a "measuring tool creation" tracker - - // TODO: if there are conflicts, we should prefer a tracker that - // pertains to the type of measuring tool currently selected (TBD?) - boost::shared_ptr hitTestTracker = TrackerHitTest(e); - - if (hitTestTracker != NULL) - { - //LOG(TRACE) << "hitTestTracker != NULL"; - return hitTestTracker; - } - else - { - switch (currentTool_) - { - case RtViewerGuiTool_Rotate: - //LOG(TRACE) << "Creating RotateSceneTracker"; - return boost::shared_ptr(new RotateSceneTracker(viewport_, e)); - case RtViewerGuiTool_Pan: - return boost::shared_ptr(new PanSceneTracker(viewport_, e)); - case RtViewerGuiTool_Zoom: - return boost::shared_ptr(new ZoomSceneTracker(viewport_, e, compositor.GetCanvasHeight())); - //case GuiTool_AngleMeasure: - // return new AngleMeasureTracker(GetScene(), e); - //case GuiTool_CircleMeasure: - // return new CircleMeasureTracker(GetScene(), e); - //case GuiTool_EllipseMeasure: - // return new EllipseMeasureTracker(GetScene(), e); - case RtViewerGuiTool_LineMeasure: - return boost::shared_ptr(new CreateLineMeasureTracker(viewport_, e)); - case RtViewerGuiTool_AngleMeasure: - return boost::shared_ptr(new CreateAngleMeasureTracker(viewport_, e)); - case RtViewerGuiTool_CircleMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr(); - case RtViewerGuiTool_EllipseMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr(); - default: - throw OrthancException(ErrorCode_InternalError, "Wrong tool!"); - } - } - } - default: - return boost::shared_ptr(); - } - } RtViewerApp::RtViewerApp() @@ -793,46 +557,5 @@ infoTextMap_[key] = value; DisplayInfoText(); } - -} - - -boost::weak_ptr g_app; - -void RtViewer_SetInfoDisplayMessage(std::string key, std::string value) -{ - boost::shared_ptr app = g_app.lock(); - if (app) - { - app->SetInfoDisplayMessage(key, value); - } } -/** - * IMPORTANT: The full arguments to "main()" are needed for SDL on - * Windows. Otherwise, one gets the linking error "undefined reference - * to `SDL_main'". https://wiki.libsdl.org/FAQWindows - **/ -int main(int argc, char* argv[]) -{ - using namespace OrthancStone; - - StoneInitialize(); - - try - { - boost::shared_ptr app = RtViewerApp::Create(); - g_app = app; - app->RunSdl(argc,argv); - } - catch (Orthanc::OrthancException& e) - { - LOG(ERROR) << "EXCEPTION: " << e.What(); - } - - StoneFinalize(); - - return 0; -} - - diff -r 32272ecfc6c2 -r ffdb82850e98 Samples/Sdl/RtViewer/RtViewerSdl.cpp --- a/Samples/Sdl/RtViewer/RtViewerSdl.cpp Tue Apr 28 13:26:41 2020 +0200 +++ b/Samples/Sdl/RtViewer/RtViewerSdl.cpp Tue Apr 28 13:52:21 2020 +0200 @@ -19,9 +19,13 @@ **/ #include "RtViewer.h" +#include "../SdlHelpers.h" #include "SampleHelpers.h" #include +#include + +#include #include #include @@ -130,6 +134,214 @@ compositor.SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_1, Orthanc::Encoding_Latin1); } + + /** + Create the shared loaders context + */ + loadersContext_.reset(new GenericLoadersContext(1, 4, 1)); + loadersContext_->StartOracle(); + + /** + It is very important that the Oracle (responsible for network I/O) be started before creating and firing the + loaders, for any command scheduled by the loader before the oracle is started will be lost. + */ + PrepareLoadersAndSlicers(); + + OrthancStone::DefaultViewportInteractor interactor; + + OrthancStoneHelpers::SdlRunLoop(viewport_, interactor); + + loadersContext_->StopOracle(); + } + +#if 0 + void RtViewerApp::HandleApplicationEvent( + const SDL_Event& event) + { + //DisplayInfoText(); + + std::unique_ptr lock(viewport_->Lock()); + ViewportController& controller = lock->GetController(); + Scene2D& scene = controller.GetScene(); + ICompositor& compositor = lock->GetCompositor(); + + if (event.type == SDL_MOUSEMOTION) + { + int scancodeCount = 0; + const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); + + if (activeTracker_.get() == NULL && + SDL_SCANCODE_LALT < scancodeCount && + keyboardState[SDL_SCANCODE_LALT]) + { + // The "left-ctrl" key is down, while no tracker is present + // Let's display the info text + PointerEvent e; + e.AddPosition(compositor.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + + DisplayFloatingCtrlInfoText(e); + } + else + { + HideInfoText(); + //LOG(TRACE) << "(event.type == SDL_MOUSEMOTION)"; + if (activeTracker_.get() != NULL) + { + //LOG(TRACE) << "(activeTracker_.get() != NULL)"; + PointerEvent e; + e.AddPosition(compositor.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + + //LOG(TRACE) << "event.button.x = " << event.button.x << " " << + // "event.button.y = " << event.button.y; + LOG(TRACE) << "activeTracker_->PointerMove(e); " << + e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); + + activeTracker_->PointerMove(e); + if (!activeTracker_->IsAlive()) + activeTracker_.reset(); + } + } + } + else if (event.type == SDL_MOUSEBUTTONUP) + { + if (activeTracker_) + { + PointerEvent e; + e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); + activeTracker_->PointerUp(e); + if (!activeTracker_->IsAlive()) + activeTracker_.reset(); + } + } + else if (event.type == SDL_MOUSEBUTTONDOWN) + { + PointerEvent e; + e.AddPosition(compositor.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + if (activeTracker_) + { + activeTracker_->PointerDown(e); + if (!activeTracker_->IsAlive()) + activeTracker_.reset(); + } + else + { + // we ATTEMPT to create a tracker if need be + activeTracker_ = CreateSuitableTracker(event, e); + } + } + else if (event.type == SDL_KEYDOWN && + event.key.repeat == 0 /* Ignore key bounce */) + { + switch (event.key.keysym.sym) + { + case SDLK_ESCAPE: + if (activeTracker_) + { + activeTracker_->Cancel(); + if (!activeTracker_->IsAlive()) + activeTracker_.reset(); + } + break; + + case SDLK_r: + UpdateLayers(); + { + std::unique_ptr lock(viewport_->Lock()); + lock->Invalidate(); + } + break; + + case SDLK_s: + compositor.FitContent(scene); + break; + + case SDLK_t: + if (!activeTracker_) + SelectNextTool(); + else + { + LOG(WARNING) << "You cannot change the active tool when an interaction" + " is taking place"; + } + break; + + case SDLK_z: + LOG(TRACE) << "SDLK_z has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; + if (event.key.keysym.mod & KMOD_CTRL) + { + if (controller.CanUndo()) + { + LOG(TRACE) << "Undoing..."; + controller.Undo(); + } + else + { + LOG(WARNING) << "Nothing to undo!!!"; + } + } + break; + + case SDLK_y: + LOG(TRACE) << "SDLK_y has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; + if (event.key.keysym.mod & KMOD_CTRL) + { + if (controller.CanRedo()) + { + LOG(TRACE) << "Redoing..."; + controller.Redo(); + } + else + { + LOG(WARNING) << "Nothing to redo!!!"; + } + } + break; + + case SDLK_c: + TakeScreenshot( + "screenshot.png", + compositor.GetCanvasWidth(), + compositor.GetCanvasHeight()); + break; + + default: + break; + } + } + else if (viewport_->IsRefreshEvent(event)) + { + // the viewport has been invalidated and requires repaint + viewport_->Paint(); + } + } +#endif + +#if 0 + void RtViewerApp::RunSdl(int argc, char* argv[]) + { + ProcessOptions(argc, argv); + + { + std::unique_ptr lock(viewport_->Lock()); + ViewportController& controller = lock->GetController(); + Scene2D& scene = controller.GetScene(); + ICompositor& compositor = lock->GetCompositor(); + + // False means we do NOT let a hi-DPI aware desktop managedr treat this as a legacy application that requires + // scaling. + controller.FitContent(compositor.GetCanvasWidth(), compositor.GetCanvasHeight()); + + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(OpenGLMessageCallback, 0); + + compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + FONT_SIZE_0, Orthanc::Encoding_Latin1); + compositor.SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, + FONT_SIZE_1, Orthanc::Encoding_Latin1); + } //////// from loader loadersContext_.reset(new GenericLoadersContext(1, 4, 1)); @@ -183,4 +395,113 @@ } loadersContext_->StopOracle(); } +#endif + +#if 0 + boost::shared_ptr RtViewerApp::CreateSuitableTracker( + const SDL_Event& event, + const PointerEvent& e) + { + std::unique_ptr lock(viewport_->Lock()); + ViewportController& controller = lock->GetController(); + Scene2D& scene = controller.GetScene(); + ICompositor& compositor = lock->GetCompositor(); + + using namespace Orthanc; + + switch (event.button.button) + { + case SDL_BUTTON_MIDDLE: + return boost::shared_ptr(new PanSceneTracker + (viewport_, e)); + + case SDL_BUTTON_RIGHT: + return boost::shared_ptr(new ZoomSceneTracker + (viewport_, e, compositor.GetCanvasHeight())); + + case SDL_BUTTON_LEFT: + { + //LOG(TRACE) << "CreateSuitableTracker: case SDL_BUTTON_LEFT:"; + // TODO: we need to iterate on the set of measuring tool and perform + // a hit test to check if a tracker needs to be created for edition. + // Otherwise, depending upon the active tool, we might want to create + // a "measuring tool creation" tracker + + // TODO: if there are conflicts, we should prefer a tracker that + // pertains to the type of measuring tool currently selected (TBD?) + boost::shared_ptr hitTestTracker = TrackerHitTest(e); + + if (hitTestTracker != NULL) + { + //LOG(TRACE) << "hitTestTracker != NULL"; + return hitTestTracker; + } + else + { + switch (currentTool_) + { + case RtViewerGuiTool_Rotate: + //LOG(TRACE) << "Creating RotateSceneTracker"; + return boost::shared_ptr(new RotateSceneTracker(viewport_, e)); + case RtViewerGuiTool_Pan: + return boost::shared_ptr(new PanSceneTracker(viewport_, e)); + case RtViewerGuiTool_Zoom: + return boost::shared_ptr(new ZoomSceneTracker(viewport_, e, compositor.GetCanvasHeight())); + //case GuiTool_AngleMeasure: + // return new AngleMeasureTracker(GetScene(), e); + //case GuiTool_CircleMeasure: + // return new CircleMeasureTracker(GetScene(), e); + //case GuiTool_EllipseMeasure: + // return new EllipseMeasureTracker(GetScene(), e); + case RtViewerGuiTool_LineMeasure: + return boost::shared_ptr(new CreateLineMeasureTracker(viewport_, e)); + case RtViewerGuiTool_AngleMeasure: + return boost::shared_ptr(new CreateAngleMeasureTracker(viewport_, e)); + case RtViewerGuiTool_CircleMeasure: + LOG(ERROR) << "Not implemented yet!"; + return boost::shared_ptr(); + case RtViewerGuiTool_EllipseMeasure: + LOG(ERROR) << "Not implemented yet!"; + return boost::shared_ptr(); + default: + throw OrthancException(ErrorCode_InternalError, "Wrong tool!"); + } + } + } + default: + return boost::shared_ptr(); + } + } +#endif + } + +boost::weak_ptr g_app; + +/** + * IMPORTANT: The full arguments to "main()" are needed for SDL on + * Windows. Otherwise, one gets the linking error "undefined reference + * to `SDL_main'". https://wiki.libsdl.org/FAQWindows + **/ +int main(int argc, char* argv[]) +{ + using namespace OrthancStone; + + StoneInitialize(); + + try + { + boost::shared_ptr app = RtViewerApp::Create(); + g_app = app; + app->RunSdl(argc,argv); + } + catch (Orthanc::OrthancException& e) + { + LOG(ERROR) << "EXCEPTION: " << e.What(); + } + + StoneFinalize(); + + return 0; +} + diff -r 32272ecfc6c2 -r ffdb82850e98 Samples/Sdl/SdlHelpers.h --- a/Samples/Sdl/SdlHelpers.h Tue Apr 28 13:26:41 2020 +0200 +++ b/Samples/Sdl/SdlHelpers.h Tue Apr 28 13:52:21 2020 +0200 @@ -4,6 +4,10 @@ # error This file cannot be used if ORTHANC_ENABLE_SDL != 1 #endif +#include + +#include + #include #include @@ -11,6 +15,7 @@ namespace OrthancStoneHelpers { + inline OrthancStone::KeyboardModifiers GetKeyboardModifiers(const uint8_t* keyboardState, const int scancodeCount) { @@ -93,5 +98,121 @@ p.SetControlModifier(modifiers & KeyboardModifiers_Control); p.SetShiftModifier(modifiers & KeyboardModifiers_Shift); } + + + inline void SdlRunLoop(boost::shared_ptr viewport, + OrthancStone::IViewportInteractor& interactor) + { + using namespace OrthancStone; + { + int scancodeCount = 0; + const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); + + bool stop = false; + while (!stop) + { + bool paint = false; + SDL_Event event; + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + stop = true; + break; + } + else if (viewport->IsRefreshEvent(event)) + { + paint = true; + } + else if (event.type == SDL_WINDOWEVENT && + (event.window.event == SDL_WINDOWEVENT_RESIZED || + event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)) + { + viewport->UpdateSize(event.window.data1, event.window.data2); + } + else if (event.type == SDL_WINDOWEVENT && + (event.window.event == SDL_WINDOWEVENT_SHOWN || + event.window.event == SDL_WINDOWEVENT_EXPOSED)) + { + paint = true; + } + else if (event.type == SDL_KEYDOWN && + event.key.repeat == 0 /* Ignore key bounce */) + { + switch (event.key.keysym.sym) + { + case SDLK_f: + viewport->ToggleMaximize(); + break; + + case SDLK_s: + { + std::unique_ptr lock(viewport->Lock()); + lock->GetCompositor().FitContent(lock->GetController().GetScene()); + lock->Invalidate(); + } + break; + + case SDLK_q: + stop = true; + break; + + default: + break; + } + } + else if (event.type == SDL_MOUSEBUTTONDOWN || + event.type == SDL_MOUSEMOTION || + event.type == SDL_MOUSEBUTTONUP) + { + std::auto_ptr lock(viewport->Lock()); + if (lock->HasCompositor()) + { + OrthancStone::PointerEvent p; + OrthancStoneHelpers::GetPointerEvent(p, lock->GetCompositor(), + event, keyboardState, scancodeCount); + + switch (event.type) + { + case SDL_MOUSEBUTTONDOWN: + lock->GetController().HandleMousePress(interactor, p, + lock->GetCompositor().GetCanvasWidth(), + lock->GetCompositor().GetCanvasHeight()); + lock->Invalidate(); + break; + + case SDL_MOUSEMOTION: + if (lock->GetController().HandleMouseMove(p)) + { + lock->Invalidate(); + } + break; + + case SDL_MOUSEBUTTONUP: + lock->GetController().HandleMouseRelease(p); + lock->Invalidate(); + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + } + } + } + + if (paint) + { + viewport->Paint(); + } + + // Small delay to avoid using 100% of CPU + SDL_Delay(1); + } + } + } + + + + } diff -r 32272ecfc6c2 -r ffdb82850e98 Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp --- a/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp Tue Apr 28 13:26:41 2020 +0200 +++ b/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp Tue Apr 28 13:52:21 2020 +0200 @@ -117,6 +117,11 @@ OrthancStone::DefaultViewportInteractor interactor; +#if 1 + OrthancStoneHelpers::SdlRunLoop(viewport, interactor); + +#else + { int scancodeCount = 0; const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); @@ -218,7 +223,7 @@ SDL_Delay(1); } } - +#endif context.StopOracle(); } } diff -r 32272ecfc6c2 -r ffdb82850e98 Samples/Sdl/SingleFrameViewer/SimpleViewer.cpp --- a/Samples/Sdl/SingleFrameViewer/SimpleViewer.cpp Tue Apr 28 13:26:41 2020 +0200 +++ b/Samples/Sdl/SingleFrameViewer/SimpleViewer.cpp Tue Apr 28 13:52:21 2020 +0200 @@ -1,3 +1,4 @@ +#error TO BE DELETED #include "SdlSimpleViewerApplication.h"