# HG changeset patch # User Alain Mazy # Date 1562683465 -7200 # Node ID 56e4e9281076d4957a7c24c785cd4c07c1501eef # Parent aad5ccf1be109f057ac15d44d057cca82d93342e sharing code between Qt/SDL BasiceScene sample diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Qt/BasicScene.cpp --- a/Samples/Qt/BasicScene.cpp Tue Jul 09 14:43:00 2019 +0200 +++ b/Samples/Qt/BasicScene.cpp Tue Jul 09 16:44:25 2019 +0200 @@ -51,99 +51,11 @@ #include #include -static const unsigned int FONT_SIZE = 32; -static const int LAYER_POSITION = 150; +#include "../Shared/SharedBasicScene.h" + using namespace OrthancStone; -void PrepareScene(boost::shared_ptr controller) -{ - Scene2D& scene(*controller->GetScene()); - // Texture of 2x2 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); - - uint8_t *p = reinterpret_cast(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast(i.GetRow(1)); - p[0] = 0; - p[1] = 0; - p[2] = 255; - - p[3] = 255; - p[4] = 0; - p[5] = 0; - - scene.SetLayer(12, new ColorTextureSceneLayer(i)); - - std::auto_ptr l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-3, 2); - l->SetPixelSpacing(1.5, 1); - l->SetAngle(20.0 / 180.0 * 3.14); - scene.SetLayer(14, l.release()); - } - - // Texture of 1x1 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 1, 1, false); - - uint8_t *p = reinterpret_cast(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - std::auto_ptr l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-2, 1); - l->SetAngle(20.0 / 180.0 * 3.14); - scene.SetLayer(13, l.release()); - } - - // Some lines - { - std::auto_ptr layer(new PolylineSceneLayer); - - layer->SetThickness(1); - - PolylineSceneLayer::Chain chain; - chain.push_back(ScenePoint2D(0 - 0.5, 0 - 0.5)); - chain.push_back(ScenePoint2D(0 - 0.5, 2 - 0.5)); - chain.push_back(ScenePoint2D(2 - 0.5, 2 - 0.5)); - chain.push_back(ScenePoint2D(2 - 0.5, 0 - 0.5)); - layer->AddChain(chain, true, 255, 0, 0); - - chain.clear(); - chain.push_back(ScenePoint2D(-5, -5)); - chain.push_back(ScenePoint2D(5, -5)); - chain.push_back(ScenePoint2D(5, 5)); - chain.push_back(ScenePoint2D(-5, 5)); - layer->AddChain(chain, true, 0, 255, 0); - - double dy = 1.01; - chain.clear(); - chain.push_back(ScenePoint2D(-4, -4)); - chain.push_back(ScenePoint2D(4, -4 + dy)); - chain.push_back(ScenePoint2D(-4, -4 + 2.0 * dy)); - chain.push_back(ScenePoint2D(4, 2)); - layer->AddChain(chain, false, 0, 0, 255); - -// layer->SetColor(0,255, 255); - scene.SetLayer(50, layer.release()); - } - - // Some text - { - std::auto_ptr layer(new TextSceneLayer); - layer->SetText("Hello"); - scene.SetLayer(100, layer.release()); - } -} static void GLAPIENTRY OpenGLMessageCallback(GLenum source, @@ -166,7 +78,6 @@ #include #include "BasicSceneWindow.h" -#include "Scene2DInteractor.h" int main(int argc, char* argv[]) { @@ -195,7 +106,7 @@ boost::shared_ptr compositor = boost::make_shared(window.GetOpenGlWidget(), *controller->GetScene()); compositor->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE, Orthanc::Encoding_Latin1); + BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); interactor->SetCompositor(compositor); window.GetOpenGlWidget().SetCompositor(compositor); diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Qt/CMakeLists.txt --- a/Samples/Qt/CMakeLists.txt Tue Jul 09 14:43:00 2019 +0200 +++ b/Samples/Qt/CMakeLists.txt Tue Jul 09 16:44:25 2019 +0200 @@ -73,8 +73,9 @@ add_executable(BasicScene BasicScene.cpp + ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.h + ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.cpp QStoneOpenGlWidget.cpp - Scene2DInteractor.cpp ${BASIC_SCENE_APPLICATIONS_SOURCES} ) diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Qt/QStoneOpenGlWidget.h --- a/Samples/Qt/QStoneOpenGlWidget.h Tue Jul 09 14:43:00 2019 +0200 +++ b/Samples/Qt/QStoneOpenGlWidget.h Tue Jul 09 16:44:25 2019 +0200 @@ -6,7 +6,7 @@ #include #include "../../Framework/OpenGL/IOpenGLContext.h" #include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "Scene2DInteractor.h" +#include "../../Applications/Generic/Scene2DInteractor.h" namespace OrthancStone { @@ -19,7 +19,8 @@ QStoneOpenGlWidget(QWidget *parent) : QOpenGLWidget(parent) { - setFocusPolicy(Qt::StrongFocus); + setFocusPolicy(Qt::StrongFocus); // to enable keyPressEvent + setMouseTracking(true); // to enable mouseMoveEvent event when no button is pressed } protected: diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Qt/Scene2DInteractor.cpp --- a/Samples/Qt/Scene2DInteractor.cpp Tue Jul 09 14:43:00 2019 +0200 +++ b/Samples/Qt/Scene2DInteractor.cpp Tue Jul 09 16:44:25 2019 +0200 @@ -2,6 +2,7 @@ #include "../../Framework/Scene2D/PanSceneTracker.h" #include "../../Framework/Scene2D/ZoomSceneTracker.h" +#include "../../Framework/Scene2D/RotateSceneTracker.h" namespace OrthancStone @@ -37,6 +38,7 @@ { if (event.button == GUIADAPTER_MOUSEBUTTON_LEFT) { + currentTracker_.reset(new RotateSceneTracker(viewportController_, pointerEvent)); } else if (event.button == GUIADAPTER_MOUSEBUTTON_MIDDLE) { diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Sdl/BasicScene.cpp --- a/Samples/Sdl/BasicScene.cpp Tue Jul 09 14:43:00 2019 +0200 +++ b/Samples/Sdl/BasicScene.cpp Tue Jul 09 16:44:25 2019 +0200 @@ -21,25 +21,14 @@ // From Stone #include "../../Applications/Sdl/SdlOpenGLWindow.h" -#include "../../Framework/Scene2D/CairoCompositor.h" -#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" #include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/Scene2D/PanSceneTracker.h" -#include "../../Framework/Scene2D/RotateSceneTracker.h" -#include "../../Framework/Scene2D/Scene2D.h" -#include "../../Framework/Scene2D/ZoomSceneTracker.h" -#include "../../Framework/Scene2DViewport/ViewportController.h" #include "../../Framework/Scene2DViewport/UndoStack.h" - #include "../../Framework/StoneInitialization.h" #include "../../Framework/Messages/MessageBroker.h" // From Orthanc framework #include #include -#include -#include -#include #include #include @@ -47,215 +36,55 @@ #include #include -static const unsigned int FONT_SIZE = 32; -static const int LAYER_POSITION = 150; + +#include "../Shared/SharedBasicScene.h" + +using namespace OrthancStone; -void PrepareScene(boost::shared_ptr controller) +boost::shared_ptr interactor; + +void HandleApplicationEvent(boost::shared_ptr controller, + const OrthancStone::OpenGLCompositor& compositor, + const SDL_Event& event) { using namespace OrthancStone; Scene2D& scene(*controller->GetScene()); - // Texture of 2x2 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); - - uint8_t *p = reinterpret_cast(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast(i.GetRow(1)); - p[0] = 0; - p[1] = 0; - p[2] = 255; - - p[3] = 255; - p[4] = 0; - p[5] = 0; - - scene.SetLayer(12, new ColorTextureSceneLayer(i)); - - std::auto_ptr l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-3, 2); - l->SetPixelSpacing(1.5, 1); - l->SetAngle(20.0 / 180.0 * M_PI); - scene.SetLayer(14, l.release()); - } - - // Texture of 1x1 size + if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEMOTION) { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 1, 1, false); - - uint8_t *p = reinterpret_cast(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - std::auto_ptr l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-2, 1); - l->SetAngle(20.0 / 180.0 * M_PI); - scene.SetLayer(13, l.release()); - } - - // Some lines - { - std::auto_ptr layer(new PolylineSceneLayer); - - layer->SetThickness(10); + // TODO: this code is copy/pasted from GuiAdapter::Run() -> find the right place + int scancodeCount = 0; + const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); + bool ctrlPressed(false); + bool shiftPressed(false); + bool altPressed(false); - PolylineSceneLayer::Chain chain; - chain.push_back(ScenePoint2D(0 - 0.5, 0 - 0.5)); - chain.push_back(ScenePoint2D(0 - 0.5, 2 - 0.5)); - chain.push_back(ScenePoint2D(2 - 0.5, 2 - 0.5)); - chain.push_back(ScenePoint2D(2 - 0.5, 0 - 0.5)); - layer->AddChain(chain, true, 255, 0, 0); + if (SDL_SCANCODE_LCTRL < scancodeCount && keyboardState[SDL_SCANCODE_LCTRL]) + ctrlPressed = true; + if (SDL_SCANCODE_RCTRL < scancodeCount && keyboardState[SDL_SCANCODE_RCTRL]) + ctrlPressed = true; + if (SDL_SCANCODE_LSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_LSHIFT]) + shiftPressed = true; + if (SDL_SCANCODE_RSHIFT < scancodeCount && keyboardState[SDL_SCANCODE_RSHIFT]) + shiftPressed = true; + if (SDL_SCANCODE_LALT < scancodeCount && keyboardState[SDL_SCANCODE_LALT]) + altPressed = true; - chain.clear(); - chain.push_back(ScenePoint2D(-5, -5)); - chain.push_back(ScenePoint2D(5, -5)); - chain.push_back(ScenePoint2D(5, 5)); - chain.push_back(ScenePoint2D(-5, 5)); - layer->AddChain(chain, true, 0, 255, 0); + GuiAdapterMouseEvent guiEvent; + ConvertFromPlatform(guiEvent, ctrlPressed, shiftPressed, altPressed, event); + PointerEvent pointerEvent; + pointerEvent.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - double dy = 1.01; - chain.clear(); - chain.push_back(ScenePoint2D(-4, -4)); - chain.push_back(ScenePoint2D(4, -4 + dy)); - chain.push_back(ScenePoint2D(-4, -4 + 2.0 * dy)); - chain.push_back(ScenePoint2D(4, 2)); - layer->AddChain(chain, false, 0, 0, 255); + interactor->OnMouseEvent(guiEvent, pointerEvent); + return; + } + else if ((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) && event.key.repeat == 0 /* Ignore key bounce */) + { + GuiAdapterKeyboardEvent guiEvent; + ConvertFromPlatform(guiEvent, event); - scene.SetLayer(50, layer.release()); + interactor->OnKeyboardEvent(guiEvent); } - // Some text - { - std::auto_ptr layer(new TextSceneLayer); - layer->SetText("Hello"); - scene.SetLayer(100, layer.release()); - } -} - - -void TakeScreenshot(const std::string& target, - const OrthancStone::Scene2D& scene, - unsigned int canvasWidth, - unsigned int canvasHeight) -{ - using namespace OrthancStone; - // Take a screenshot, then save it as PNG file - CairoCompositor compositor(scene, canvasWidth, canvasHeight); - compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1); - compositor.Refresh(); - - Orthanc::ImageAccessor canvas; - compositor.GetCanvas().GetReadOnlyAccessor(canvas); - - Orthanc::Image png(Orthanc::PixelFormat_RGB24, canvas.GetWidth(), canvas.GetHeight(), false); - Orthanc::ImageProcessing::Convert(png, canvas); - - Orthanc::PngWriter writer; - writer.WriteToFile(target, png); -} - - -void HandleApplicationEvent(boost::shared_ptr controller, - const OrthancStone::OpenGLCompositor& compositor, - const SDL_Event& event, - boost::shared_ptr& activeTracker) -{ - using namespace OrthancStone; - Scene2D& scene(*controller->GetScene()); - if (event.type == SDL_MOUSEMOTION) - { - int scancodeCount = 0; - const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); - - if (activeTracker.get() == NULL && - SDL_SCANCODE_LCTRL < scancodeCount && - keyboardState[SDL_SCANCODE_LCTRL]) - { - // The "left-ctrl" key is down, while no tracker is present - - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - - ScenePoint2D p = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); - - char buf[64]; - sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY()); - - if (scene.HasLayer(LAYER_POSITION)) - { - TextSceneLayer& layer = - dynamic_cast(scene.GetLayer(LAYER_POSITION)); - layer.SetText(buf); - layer.SetPosition(p.GetX(), p.GetY()); - } - else - { - std::auto_ptr - layer(new TextSceneLayer); - layer->SetColor(0, 255, 0); - layer->SetText(buf); - layer->SetBorder(20); - layer->SetAnchor(BitmapAnchor_BottomCenter); - layer->SetPosition(p.GetX(), p.GetY()); - scene.SetLayer(LAYER_POSITION, layer.release()); - } - } - else - { - scene.DeleteLayer(LAYER_POSITION); - } - } - else if (event.type == SDL_MOUSEBUTTONDOWN) - { - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - - switch (event.button.button) - { - case SDL_BUTTON_MIDDLE: - activeTracker = boost::make_shared(controller, e); - break; - - case SDL_BUTTON_RIGHT: - activeTracker = boost::make_shared(controller, - e, compositor.GetHeight()); - break; - - case SDL_BUTTON_LEFT: - activeTracker = boost::make_shared(controller, e); - break; - - default: - break; - } - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_s: - controller->FitContent(compositor.GetWidth(), - compositor.GetHeight()); - break; - - case SDLK_c: - TakeScreenshot("screenshot.png", scene, - compositor.GetWidth(), - compositor.GetHeight()); - break; - - default: - break; - } - } } @@ -279,7 +108,6 @@ void Run(boost::shared_ptr controller) { - using namespace OrthancStone; SdlOpenGLWindow window("Hello", 1024, 768); controller->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); @@ -287,16 +115,15 @@ glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); - OpenGLCompositor compositor(window, *controller->GetScene()); - compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE, Orthanc::Encoding_Latin1); - - boost::shared_ptr tracker; + boost::shared_ptr compositor(new OpenGLCompositor(window, *controller->GetScene())); + compositor->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); + interactor->SetCompositor(compositor); bool stop = false; while (!stop) { - compositor.Refresh(); + compositor->Refresh(); SDL_Event event; while (!stop && @@ -307,33 +134,10 @@ stop = true; break; } - else if (event.type == SDL_MOUSEMOTION) - { - if (tracker) - { - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates( - event.button.x, event.button.y)); - tracker->PointerMove(e); - } - } - else if (event.type == SDL_MOUSEBUTTONUP) - { - if (tracker) - { - PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates( - event.button.x, event.button.y)); - tracker->PointerUp(e); - if(!tracker->IsAlive()) - tracker.reset(); - } - } else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { - tracker.reset(); - compositor.UpdateSize(); + compositor->UpdateSize(); } else if (event.type == SDL_KEYDOWN && event.key.repeat == 0 /* Ignore key bounce */) @@ -353,11 +157,12 @@ } } - HandleApplicationEvent(controller, compositor, event, tracker); + HandleApplicationEvent(controller, *compositor, event); } SDL_Delay(1); } + interactor.reset(); } @@ -380,6 +185,7 @@ boost::shared_ptr undoStack(new UndoStack); boost::shared_ptr controller = boost::make_shared( undoStack, boost::ref(broker)); + interactor.reset(new BasicScene2DInteractor(controller)); PrepareScene(controller); Run(controller); } diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Sdl/CMakeLists.txt --- a/Samples/Sdl/CMakeLists.txt Tue Jul 09 14:43:00 2019 +0200 +++ b/Samples/Sdl/CMakeLists.txt Tue Jul 09 16:44:25 2019 +0200 @@ -66,6 +66,8 @@ add_executable(BasicScene BasicScene.cpp + ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.h + ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.cpp ) target_link_libraries(BasicScene OrthancStone) diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Shared/RadiographyEditorApp.cpp --- a/Samples/Shared/RadiographyEditorApp.cpp Tue Jul 09 14:43:00 2019 +0200 +++ b/Samples/Shared/RadiographyEditorApp.cpp Tue Jul 09 16:44:25 2019 +0200 @@ -31,6 +31,7 @@ #include "../../Framework/Scene2D/ZoomSceneTracker.h" #include "../../Framework/Scene2DViewport/CreateAngleMeasureTracker.h" #include "../../Framework/Scene2DViewport/CreateLineMeasureTracker.h" +#include "../../Framework/Scene2DViewport/UndoStack.h" #include "../../Framework/StoneInitialization.h" // From Orthanc framework @@ -610,7 +611,8 @@ compositorFactory_(compositorFactory), currentTool_(GuiTool_Rotate) { - controller_ = boost::shared_ptr(new ViewportController(IObserver::GetBroker())); + boost::shared_ptr undoStack(new UndoStack); + controller_ = boost::shared_ptr(new ViewportController(undoStack, IObserver::GetBroker())); controller_->RegisterObserverCallback( new Callable diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Shared/SharedBasicScene.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Samples/Shared/SharedBasicScene.cpp Tue Jul 09 16:44:25 2019 +0200 @@ -0,0 +1,268 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#include "SharedBasicScene.h" + +// From Stone +#include "../../Framework/Scene2D/Scene2D.h" +#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" +#include "../../Framework/Scene2D/PolylineSceneLayer.h" +#include "../../Framework/Scene2D/TextSceneLayer.h" + +#include "../../Framework/Scene2D/PanSceneTracker.h" +#include "../../Framework/Scene2D/ZoomSceneTracker.h" +#include "../../Framework/Scene2D/RotateSceneTracker.h" + +#include "../../Framework/Scene2D/CairoCompositor.h" + +// From Orthanc framework +#include +#include +#include + +using namespace OrthancStone; + +const unsigned int BASIC_SCENE_FONT_SIZE = 32; +const int BASIC_SCENE_LAYER_POSITION = 150; + +void PrepareScene(boost::shared_ptr controller) +{ + Scene2D& scene(*controller->GetScene()); + // Texture of 2x2 size + { + Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); + + uint8_t *p = reinterpret_cast(i.GetRow(0)); + p[0] = 255; + p[1] = 0; + p[2] = 0; + + p[3] = 0; + p[4] = 255; + p[5] = 0; + + p = reinterpret_cast(i.GetRow(1)); + p[0] = 0; + p[1] = 0; + p[2] = 255; + + p[3] = 255; + p[4] = 0; + p[5] = 0; + + scene.SetLayer(12, new ColorTextureSceneLayer(i)); + + std::auto_ptr l(new ColorTextureSceneLayer(i)); + l->SetOrigin(-3, 2); + l->SetPixelSpacing(1.5, 1); + l->SetAngle(20.0 / 180.0 * 3.14); + scene.SetLayer(14, l.release()); + } + + // Texture of 1x1 size + { + Orthanc::Image i(Orthanc::PixelFormat_RGB24, 1, 1, false); + + uint8_t *p = reinterpret_cast(i.GetRow(0)); + p[0] = 255; + p[1] = 0; + p[2] = 0; + + std::auto_ptr l(new ColorTextureSceneLayer(i)); + l->SetOrigin(-2, 1); + l->SetAngle(20.0 / 180.0 * 3.14); + scene.SetLayer(13, l.release()); + } + + // Some lines + { + std::auto_ptr layer(new PolylineSceneLayer); + + layer->SetThickness(1); + + PolylineSceneLayer::Chain chain; + chain.push_back(ScenePoint2D(0 - 0.5, 0 - 0.5)); + chain.push_back(ScenePoint2D(0 - 0.5, 2 - 0.5)); + chain.push_back(ScenePoint2D(2 - 0.5, 2 - 0.5)); + chain.push_back(ScenePoint2D(2 - 0.5, 0 - 0.5)); + layer->AddChain(chain, true, 255, 0, 0); + + chain.clear(); + chain.push_back(ScenePoint2D(-5, -5)); + chain.push_back(ScenePoint2D(5, -5)); + chain.push_back(ScenePoint2D(5, 5)); + chain.push_back(ScenePoint2D(-5, 5)); + layer->AddChain(chain, true, 0, 255, 0); + + double dy = 1.01; + chain.clear(); + chain.push_back(ScenePoint2D(-4, -4)); + chain.push_back(ScenePoint2D(4, -4 + dy)); + chain.push_back(ScenePoint2D(-4, -4 + 2.0 * dy)); + chain.push_back(ScenePoint2D(4, 2)); + layer->AddChain(chain, false, 0, 0, 255); + + // layer->SetColor(0,255, 255); + scene.SetLayer(50, layer.release()); + } + + // Some text + { + std::auto_ptr layer(new TextSceneLayer); + layer->SetText("Hello"); + scene.SetLayer(100, layer.release()); + } +} + +void TakeScreenshot(const std::string& target, + const OrthancStone::Scene2D& scene, + unsigned int canvasWidth, + unsigned int canvasHeight) +{ + using namespace OrthancStone; + // Take a screenshot, then save it as PNG file + CairoCompositor compositor(scene, canvasWidth, canvasHeight); + compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); + compositor.Refresh(); + + Orthanc::ImageAccessor canvas; + compositor.GetCanvas().GetReadOnlyAccessor(canvas); + + Orthanc::Image png(Orthanc::PixelFormat_RGB24, canvas.GetWidth(), canvas.GetHeight(), false); + Orthanc::ImageProcessing::Convert(png, canvas); + + Orthanc::PngWriter writer; + writer.WriteToFile(target, png); +} + +void ShowCursorInfo(Scene2D& scene, const PointerEvent& pointerEvent) +{ + ScenePoint2D p = pointerEvent.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); + + char buf[64]; + sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY()); + + if (scene.HasLayer(BASIC_SCENE_LAYER_POSITION)) + { + TextSceneLayer& layer = + dynamic_cast(scene.GetLayer(BASIC_SCENE_LAYER_POSITION)); + layer.SetText(buf); + layer.SetPosition(p.GetX(), p.GetY()); + } + else + { + std::auto_ptr + layer(new TextSceneLayer); + layer->SetColor(0, 255, 0); + layer->SetText(buf); + layer->SetBorder(20); + layer->SetAnchor(BitmapAnchor_BottomCenter); + layer->SetPosition(p.GetX(), p.GetY()); + scene.SetLayer(BASIC_SCENE_LAYER_POSITION, layer.release()); + } +} + + + +bool BasicScene2DInteractor::OnMouseEvent(const GuiAdapterMouseEvent& event, const PointerEvent& pointerEvent) +{ + if (currentTracker_.get() != NULL) + { + switch (event.type) + { + case GUIADAPTER_EVENT_MOUSEUP: + { + currentTracker_->PointerUp(pointerEvent); + if (!currentTracker_->IsAlive()) + { + currentTracker_.reset(); + } + };break; + case GUIADAPTER_EVENT_MOUSEMOVE: + { + currentTracker_->PointerMove(pointerEvent); + };break; + } + return true; + } + else if (event.type == GUIADAPTER_EVENT_MOUSEDOWN) + { + if (event.button == GUIADAPTER_MOUSEBUTTON_LEFT) + { + currentTracker_.reset(new RotateSceneTracker(viewportController_, pointerEvent)); + } + else if (event.button == GUIADAPTER_MOUSEBUTTON_MIDDLE) + { + currentTracker_.reset(new PanSceneTracker(viewportController_, pointerEvent)); + } + else if (event.button == GUIADAPTER_MOUSEBUTTON_RIGHT && compositor_.get() != NULL) + { + currentTracker_.reset(new ZoomSceneTracker(viewportController_, pointerEvent, compositor_->GetHeight())); + } + } + else if (event.type == GUIADAPTER_EVENT_MOUSEMOVE) + { + if (showCursorInfo_) + { + Scene2D& scene(*(viewportController_->GetScene())); + ShowCursorInfo(scene, pointerEvent); + } + return true; + } + return false; +} + +bool BasicScene2DInteractor::OnKeyboardEvent(const GuiAdapterKeyboardEvent& guiEvent) +{ + if (guiEvent.type == GUIADAPTER_EVENT_KEYDOWN) + { + switch (guiEvent.sym[0]) + { + case 's': + { + viewportController_->FitContent(compositor_->GetWidth(), compositor_->GetHeight()); + return true; + }; + case 'c': + { + Scene2D& scene(*(viewportController_->GetScene())); + TakeScreenshot("screenshot.png", scene, compositor_->GetWidth(), compositor_->GetHeight()); + return true; + } + case 'd': + { + showCursorInfo_ = !showCursorInfo_; + if (!showCursorInfo_) + { + Scene2D& scene(*(viewportController_->GetScene())); + scene.DeleteLayer(BASIC_SCENE_LAYER_POSITION); + } + + return true; + } + } + } + return false; +} + +bool BasicScene2DInteractor::OnWheelEvent(const GuiAdapterWheelEvent& guiEvent) +{ + return false; +} diff -r aad5ccf1be10 -r 56e4e9281076 Samples/Shared/SharedBasicScene.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Samples/Shared/SharedBasicScene.h Tue Jul 09 16:44:25 2019 +0200 @@ -0,0 +1,54 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#pragma once + +#include +#include "../../Framework/Scene2DViewport/ViewportController.h" + +extern const unsigned int BASIC_SCENE_FONT_SIZE; +extern const int BASIC_SCENE_LAYER_POSITION; + +extern void PrepareScene(boost::shared_ptr controller); +extern void TakeScreenshot(const std::string& target, + const OrthancStone::Scene2D& scene, + unsigned int canvasWidth, + unsigned int canvasHeight); + + +#include "../../Applications/Generic/Scene2DInteractor.h" +#include "../../Framework/Scene2DViewport/IFlexiblePointerTracker.h" + + +class BasicScene2DInteractor : public OrthancStone::Scene2DInteractor +{ + boost::shared_ptr currentTracker_; + bool showCursorInfo_; +public: + BasicScene2DInteractor(boost::shared_ptr viewportController) : + Scene2DInteractor(viewportController), + showCursorInfo_(false) + {} + + virtual bool OnMouseEvent(const OrthancStone::GuiAdapterMouseEvent& event, const OrthancStone::PointerEvent& pointerEvent) override; + virtual bool OnKeyboardEvent(const OrthancStone::GuiAdapterKeyboardEvent& guiEvent); + virtual bool OnWheelEvent(const OrthancStone::GuiAdapterWheelEvent& guiEvent); +}; +