Mercurial > hg > orthanc-stone
diff Samples/Sdl/RtViewer/RtViewerSdl.cpp @ 1404:3e644f6fadd4
Three-viewport is now OK in SDL and Wasm
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Wed, 29 Apr 2020 22:06:24 +0200 |
parents | 27e0a00bd3e8 |
children | 5d7ee14dc1eb |
line wrap: on
line diff
--- a/Samples/Sdl/RtViewer/RtViewerSdl.cpp Wed Apr 29 18:11:49 2020 +0200 +++ b/Samples/Sdl/RtViewer/RtViewerSdl.cpp Wed Apr 29 22:06:24 2020 +0200 @@ -18,7 +18,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ -#include "RtViewer.h" +#include "RtViewerApp.h" +#include "RtViewerView.h" #include "../SdlHelpers.h" // Stone of Orthanc includes @@ -61,10 +62,16 @@ namespace OrthancStone { - void RtViewerApp::CreateViewport() + void RtViewerView::EnableGLDebugOutput() + { + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(OpenGLMessageCallback, 0); + } + + boost::shared_ptr<IViewport> RtViewerView::CreateViewport(const std::string& canvasId) { // False means we do NOT let Windows treat this as a legacy application that needs to be scaled - viewport_ = SdlOpenGLViewport::Create("CT RTDOSE RTSTRUCT viewer", 1024, 1024, false); + return SdlOpenGLViewport::Create(canvasId, 1024, 1024, false); } void RtViewerApp::ProcessOptions(int argc, char* argv[]) @@ -113,25 +120,6 @@ { ProcessOptions(argc, argv); - { - std::unique_ptr<IViewport::ILock> 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); - } - /** Create the shared loaders context */ @@ -170,22 +158,44 @@ loadersContext->StartOracle(); + CreateLoaders(); + + /** + Create viewports + */ + CreateView("RtViewer Axial", VolumeProjection_Axial); + CreateView("RtViewer Coronal", VolumeProjection_Coronal); + CreateView("RtViewer Sagittal", VolumeProjection_Sagittal); + + for (size_t i = 0; i < views_.size(); ++i) + { + views_[i]->PrepareViewport(); + views_[i]->EnableGLDebugOutput(); + } + + DefaultViewportInteractor interactor; + /** 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(); + StartLoaders(); - DefaultViewportInteractor interactor; - boost::shared_ptr<SdlViewport> viewport = boost::dynamic_pointer_cast<SdlViewport>(viewport_); - - OrthancStoneHelpers::SdlRunLoop(viewport, interactor); - + std::vector<boost::shared_ptr<SdlViewport>> sdlViewports; + for(size_t i = 0; i < views_.size(); ++i) + { + boost::shared_ptr<RtViewerView> view = views_[i]; + boost::shared_ptr<IViewport> viewport = view->GetViewport(); + boost::shared_ptr<SdlViewport> sdlViewport = + boost::dynamic_pointer_cast<SdlViewport>(viewport); + sdlViewports.push_back(sdlViewport); + } + OrthancStoneHelpers::SdlRunLoop(sdlViewports, interactor); loadersContext->StopOracle(); } - void RtViewerApp::TakeScreenshot(const std::string& target, + void RtViewerView::TakeScreenshot(const std::string& target, unsigned int canvasWidth, unsigned int canvasHeight) { @@ -206,328 +216,6 @@ Orthanc::PngWriter writer; writer.WriteToFile(target, png); } - - -#if 0 - void RtViewerApp::HandleApplicationEvent( - const SDL_Event& event) - { - //DisplayInfoText(); - - std::unique_ptr<IViewport::ILock> 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<IViewport::ILock> 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<IViewport::ILock> 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)); - 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(); - - bool stopApplication = false; - - while (!stopApplication) - { - SDL_Event event; - while (!stopApplication && SDL_PollEvent(&event)) - { - if (event.type == SDL_QUIT) - { - stopApplication = true; - break; - } - else if (event.type == SDL_WINDOWEVENT && - event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) - { - DisableTracker(); - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_f: - // TODO: implement GetWindow to be able to do: - // viewport_->GetWindow().ToggleMaximize(); - ORTHANC_ASSERT(false, "Please implement GetWindow()"); - break; - case SDLK_q: - stopApplication = true; - break; - default: - break; - } - } - // the code above is rather application-neutral. - // the following call handles events specific to the application - HandleApplicationEvent(event); - } - SDL_Delay(1); - } - loadersContext_->StopOracle(); - } -#endif - -#if 0 - boost::shared_ptr<IFlexiblePointerTracker> RtViewerApp::CreateSuitableTracker( - const SDL_Event& event, - const PointerEvent& e) - { - std::unique_ptr<IViewport::ILock> 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<IFlexiblePointerTracker>(new PanSceneTracker - (viewport_, e)); - - case SDL_BUTTON_RIGHT: - return boost::shared_ptr<IFlexiblePointerTracker>(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<IFlexiblePointerTracker> 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<IFlexiblePointerTracker>(new RotateSceneTracker(viewport_, e)); - case RtViewerGuiTool_Pan: - return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker(viewport_, e)); - case RtViewerGuiTool_Zoom: - return boost::shared_ptr<IFlexiblePointerTracker>(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<IFlexiblePointerTracker>(new CreateLineMeasureTracker(viewport_, e)); - case RtViewerGuiTool_AngleMeasure: - return boost::shared_ptr<IFlexiblePointerTracker>(new CreateAngleMeasureTracker(viewport_, e)); - case RtViewerGuiTool_CircleMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr<IFlexiblePointerTracker>(); - case RtViewerGuiTool_EllipseMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr<IFlexiblePointerTracker>(); - default: - throw OrthancException(ErrorCode_InternalError, "Wrong tool!"); - } - } - } - default: - return boost::shared_ptr<IFlexiblePointerTracker>(); - } - } -#endif - } boost::weak_ptr<OrthancStone::RtViewerApp> g_app;