Mercurial > hg > orthanc-stone
changeset 916:a911f5bb48da am-dev
MultiPlatform Basic Scene sample (so far: SDL + Qt)
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Fri, 19 Jul 2019 15:06:36 +0200 |
parents | 912cc77be3b4 |
children | 878763ce66af |
files | Applications/Generic/Scene2DInteractor.h Framework/Scene2DViewport/ViewportController.cpp Framework/Scene2DViewport/ViewportController.h Samples/MultiPlatform/BasicScene/BasicScene.cpp Samples/MultiPlatform/BasicScene/BasicScene.h Samples/MultiPlatform/BasicScene/mainQt.cpp Samples/MultiPlatform/BasicScene/mainSdl.cpp Samples/Qt/BasicScene.cpp Samples/Qt/BasicSceneWindow.cpp Samples/Qt/BasicSceneWindow.h Samples/Qt/CMakeLists.txt Samples/Qt/QStoneOpenGlWidget.cpp Samples/Qt/QStoneOpenGlWidget.h Samples/Sdl/CMakeLists.txt Samples/Sdl/TrackerSampleApp.h Samples/Shared/RadiographyEditorApp.cpp Samples/Shared/RadiographyEditorApp.h Samples/Shared/SharedBasicScene.cpp Samples/Shared/SharedBasicScene.h |
diffstat | 19 files changed, 686 insertions(+), 1436 deletions(-) [+] |
line wrap: on
line diff
--- a/Applications/Generic/Scene2DInteractor.h Fri Jul 19 11:40:45 2019 +0200 +++ b/Applications/Generic/Scene2DInteractor.h Fri Jul 19 15:06:36 2019 +0200 @@ -21,7 +21,7 @@ #include "../../Framework/Scene2D/PointerEvent.h" #include "../../Framework/Scene2DViewport/ViewportController.h" -#include "../../Framework/Scene2D/Internals/CompositorHelper.h" +//#include "../../Framework/Scene2D/Internals/CompositorHelper.h" #include "GuiAdapter.h" @@ -32,17 +32,17 @@ { protected: boost::shared_ptr<ViewportController> viewportController_; - boost::shared_ptr<ICompositor> compositor_; +// boost::shared_ptr<ICompositor> compositor_; public: Scene2DInteractor(boost::shared_ptr<ViewportController> viewportController) : viewportController_(viewportController) {} - void SetCompositor(boost::shared_ptr<ICompositor> compositor) - { - compositor_ = compositor; - } +// void SetCompositor(boost::shared_ptr<ICompositor> compositor) +// { +// compositor_ = compositor; +// } virtual bool OnMouseEvent(const GuiAdapterMouseEvent& guiEvent, const PointerEvent& pointerEvent) = 0; // returns true if it has handled the event virtual bool OnKeyboardEvent(const GuiAdapterKeyboardEvent& guiEvent) = 0; // returns true if it has handled the event
--- a/Framework/Scene2DViewport/ViewportController.cpp Fri Jul 19 11:40:45 2019 +0200 +++ b/Framework/Scene2DViewport/ViewportController.cpp Fri Jul 19 15:06:36 2019 +0200 @@ -161,6 +161,12 @@ BroadcastMessage(SceneTransformChanged(*this)); } + void ViewportController::FitContent() + { + viewport_.GetScene().FitContent(viewport_.GetCanvasWidth(), viewport_.GetCanvasHeight()); + BroadcastMessage(SceneTransformChanged(*this)); + } + void ViewportController::AddMeasureTool(boost::shared_ptr<MeasureTool> measureTool) { ORTHANC_ASSERT(std::find(measureTools_.begin(), measureTools_.end(), measureTool)
--- a/Framework/Scene2DViewport/ViewportController.h Fri Jul 19 11:40:45 2019 +0200 +++ b/Framework/Scene2DViewport/ViewportController.h Fri Jul 19 15:06:36 2019 +0200 @@ -120,6 +120,7 @@ /** Forwarded to the underlying scene, and broadcasted to the observers */ void FitContent(unsigned int canvasWidth, unsigned int canvasHeight); + void FitContent(); /** Adds a new measure tool */ void AddMeasureTool(boost::shared_ptr<MeasureTool> measureTool);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Samples/MultiPlatform/BasicScene/BasicScene.cpp Fri Jul 19 15:06:36 2019 +0200 @@ -0,0 +1,275 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#include "BasicScene.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 <Core/Images/Image.h> +#include <Core/Images/ImageProcessing.h> +#include <Core/Images/PngWriter.h> + +using namespace OrthancStone; + +const unsigned int BASIC_SCENE_FONT_SIZE = 32; +const int BASIC_SCENE_LAYER_POSITION = 150; + +void PrepareScene(Scene2D& scene) +{ + //Scene2D& scene(*controller->GetScene()); + // Texture of 2x2 size + { + Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); + + uint8_t *p = reinterpret_cast<uint8_t*>(i.GetRow(0)); + p[0] = 255; + p[1] = 0; + p[2] = 0; + + p[3] = 0; + p[4] = 255; + p[5] = 0; + + p = reinterpret_cast<uint8_t*>(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<ColorTextureSceneLayer> 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<uint8_t*>(i.GetRow(0)); + p[0] = 255; + p[1] = 0; + p[2] = 0; + + std::auto_ptr<ColorTextureSceneLayer> 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<PolylineSceneLayer> 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<TextSceneLayer> layer(new TextSceneLayer); + layer->SetText("Hello"); + scene.SetLayer(100, layer.release()); + } +} + +#if ORTHANC_SANDBOXED == 0 +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); +} +#endif + +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<TextSceneLayer&>(scene.GetLayer(BASIC_SCENE_LAYER_POSITION)); + layer.SetText(buf); + layer.SetPosition(p.GetX(), p.GetY()); + } + else + { + std::auto_ptr<TextSceneLayer> + 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; + default: + return false; + } + 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) + { + currentTracker_.reset(new ZoomSceneTracker(viewportController_, pointerEvent, viewportController_->GetViewport().GetCanvasHeight())); + } + } + 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(viewportController_->GetViewport().GetCanvasWidth(), viewportController_->GetViewport().GetCanvasHeight()); + viewportController_->FitContent(); + return true; + }; +#if ORTHANC_SANDBOXED == 0 + case 'c': + { + Scene2D& scene(viewportController_->GetScene()); + TakeScreenshot("screenshot.png", scene, viewportController_->GetViewport().GetCanvasWidth(), viewportController_->GetViewport().GetCanvasHeight()); + return true; + } +#endif + 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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Samples/MultiPlatform/BasicScene/BasicScene.h Fri Jul 19 15:06:36 2019 +0200 @@ -0,0 +1,55 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include "Framework/Scene2DViewport/ViewportController.h" +#include "Framework/Scene2D/Scene2D.h" + +extern const unsigned int BASIC_SCENE_FONT_SIZE; +extern const int BASIC_SCENE_LAYER_POSITION; + +extern void PrepareScene(OrthancStone::Scene2D& scene); +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<OrthancStone::IFlexiblePointerTracker> currentTracker_; + bool showCursorInfo_; +public: + BasicScene2DInteractor(boost::shared_ptr<OrthancStone::ViewportController> viewportController) : + Scene2DInteractor(viewportController), + showCursorInfo_(false) + {} + + virtual bool OnMouseEvent(const OrthancStone::GuiAdapterMouseEvent& event, const OrthancStone::PointerEvent& pointerEvent) override; + virtual bool OnKeyboardEvent(const OrthancStone::GuiAdapterKeyboardEvent& guiEvent) override; + virtual bool OnWheelEvent(const OrthancStone::GuiAdapterWheelEvent& guiEvent) override; +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Samples/MultiPlatform/BasicScene/mainQt.cpp Fri Jul 19 15:06:36 2019 +0200 @@ -0,0 +1,103 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#define GLEW_STATIC 1 +// From Stone +#include "../../Framework/OpenGL/OpenGLIncludes.h" +#include "../../Applications/Sdl/SdlWindow.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 <Core/Logging.h> +#include <Core/OrthancException.h> +#include <Core/Images/Image.h> +#include <Core/Images/ImageProcessing.h> +#include <Core/Images/PngWriter.h> + +#include <boost/make_shared.hpp> +#include <boost/ref.hpp> +#include "EmbeddedResources.h" + +#include <stdio.h> +#include <QDebug> +#include <QWindow> + +#include "BasicScene.h" + + +using namespace OrthancStone; + + + +static void GLAPIENTRY OpenGLMessageCallback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam ) +{ + if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) + { + fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", + ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), + type, severity, message ); + } +} + +extern void InitGL(); + +#include <QApplication> +#include "BasicSceneWindow.h" + +int main(int argc, char* argv[]) +{ + QApplication a(argc, argv); + + OrthancStone::Samples::BasicSceneWindow window; + window.show(); + window.GetOpenGlWidget().Init(); + + MessageBroker broker; + boost::shared_ptr<UndoStack> undoStack(new UndoStack); + boost::shared_ptr<ViewportController> controller = boost::make_shared<ViewportController>(undoStack, boost::ref(broker), window.GetOpenGlWidget()); + PrepareScene(controller->GetScene()); + + window.GetOpenGlWidget().GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); + + boost::shared_ptr<OrthancStone::Scene2DInteractor> interactor(new BasicScene2DInteractor(controller)); + window.GetOpenGlWidget().SetInteractor(interactor); + + controller->FitContent(); + + return a.exec(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Samples/MultiPlatform/BasicScene/mainSdl.cpp Fri Jul 19 15:06:36 2019 +0200 @@ -0,0 +1,199 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + + +// From Stone +#include "Framework/Viewport/SdlViewport.h" +#include "Framework/Scene2D/OpenGLCompositor.h" +#include "Framework/Scene2DViewport/UndoStack.h" +#include "Framework/StoneInitialization.h" +#include "Framework/Messages/MessageBroker.h" + +// From Orthanc framework +#include <Core/Logging.h> +#include <Core/OrthancException.h> + +#include <boost/make_shared.hpp> +#include <boost/ref.hpp> + +#include <SDL.h> +#include <stdio.h> + + +#include "BasicScene.h" + +using namespace OrthancStone; + +boost::shared_ptr<BasicScene2DInteractor> interactor; + +void HandleApplicationEvent(boost::shared_ptr<OrthancStone::ViewportController> controller, + const SDL_Event& event) +{ + using namespace OrthancStone; + Scene2D& scene(controller->GetScene()); + if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEMOTION) + { + // 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); + + 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; + + GuiAdapterMouseEvent guiEvent; + ConvertFromPlatform(guiEvent, ctrlPressed, shiftPressed, altPressed, event); + PointerEvent pointerEvent; + pointerEvent.AddPosition(controller->GetViewport().GetPixelCenterCoordinates(event.button.x, event.button.y)); + + 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); + + interactor->OnKeyboardEvent(guiEvent); + } + +} + + +static void GLAPIENTRY +OpenGLMessageCallback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam ) +{ + if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) + { + fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", + ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), + type, severity, message ); + } +} + + +void Run(boost::shared_ptr<OrthancStone::ViewportController> controller) +{ + SdlViewport& sdlViewport = dynamic_cast<SdlViewport&>(controller->GetViewport()); + + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(OpenGLMessageCallback, 0); + + controller->GetViewport().GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); + + controller->GetViewport().Refresh(); + controller->FitContent(); + + + bool stop = false; + while (!stop) + { + controller->GetViewport().Refresh(); + + SDL_Event event; + while (!stop && + SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + stop = true; + break; + } + else if (event.type == SDL_WINDOWEVENT && + event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) + { + sdlViewport.UpdateSize(event.window.data1, event.window.data2); + } + else if (event.type == SDL_KEYDOWN && + event.key.repeat == 0 /* Ignore key bounce */) + { + switch (event.key.keysym.sym) + { + case SDLK_f: + sdlViewport.GetWindow().ToggleMaximize(); + break; + + case SDLK_q: + stop = true; + break; + + default: + break; + } + } + + HandleApplicationEvent(controller, event); + } + + SDL_Delay(1); + } + interactor.reset(); +} + + + + +/** + * 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(); + Orthanc::Logging::EnableInfoLevel(true); + + try + { + SdlOpenGLViewport viewport("Hello", 1024, 768); + MessageBroker broker; + boost::shared_ptr<UndoStack> undoStack(new UndoStack); + boost::shared_ptr<ViewportController> controller = boost::make_shared<ViewportController>(undoStack, boost::ref(broker), viewport); + interactor.reset(new BasicScene2DInteractor(controller)); + PrepareScene(controller->GetScene()); + Run(controller); + } + catch (Orthanc::OrthancException& e) + { + LOG(ERROR) << "EXCEPTION: " << e.What(); + } + + StoneFinalize(); + + return 0; +}
--- a/Samples/Qt/BasicScene.cpp Fri Jul 19 11:40:45 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/** - * 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 <http://www.gnu.org/licenses/>. - **/ - -#define GLEW_STATIC 1 -// From Stone -#include "../../Framework/OpenGL/OpenGLIncludes.h" -#include "../../Applications/Sdl/SdlWindow.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 <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> - -#include <boost/make_shared.hpp> -#include <boost/ref.hpp> -#include "EmbeddedResources.h" - -//#include <SDL.h> -#include <stdio.h> -#include <QDebug> -#include <QWindow> - -#include "../Shared/SharedBasicScene.h" - - -using namespace OrthancStone; - - - -static void GLAPIENTRY OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam ) -{ - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) - { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), - type, severity, message ); - } -} - -extern void InitGL(); - -#include <QApplication> -#include "BasicSceneWindow.h" - -int main(int argc, char* argv[]) -{ - { - QApplication a(argc, argv); - - QSurfaceFormat requestedFormat; - requestedFormat.setVersion( 2, 0 ); - - OrthancStone::Samples::BasicSceneWindow window; - window.show(); - - MessageBroker broker; - boost::shared_ptr<UndoStack> undoStack(new UndoStack); - boost::shared_ptr<ViewportController> controller = boost::make_shared<ViewportController>( - undoStack, boost::ref(broker)); - PrepareScene(controller->GetScene()); - - boost::shared_ptr<OrthancStone::Scene2DInteractor> interactor(new BasicScene2DInteractor(controller)); - window.GetOpenGlWidget().SetInteractor(interactor); - - QOpenGLContext * context = new QOpenGLContext; - context->setFormat( requestedFormat ); - context->create(); - context->makeCurrent(window.GetOpenGlWidget().context()->surface()); - - boost::shared_ptr<OpenGLCompositor> compositor = boost::make_shared<OpenGLCompositor>(window.GetOpenGlWidget(), *controller->GetScene()); - compositor->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - BASIC_SCENE_FONT_SIZE, Orthanc::Encoding_Latin1); - - interactor->SetCompositor(compositor); - window.GetOpenGlWidget().SetCompositor(compositor); - - return a.exec(); - } -}
--- a/Samples/Qt/BasicSceneWindow.cpp Fri Jul 19 11:40:45 2019 +0200 +++ b/Samples/Qt/BasicSceneWindow.cpp Fri Jul 19 15:06:36 2019 +0200 @@ -49,10 +49,5 @@ return *(ui_->centralWidget); } - void BasicSceneWindow::SetCompositor(boost::shared_ptr<OrthancStone::OpenGLCompositor> compositor) - { - ui_->centralWidget->SetCompositor(compositor); - } - } }
--- a/Samples/Qt/BasicSceneWindow.h Fri Jul 19 11:40:45 2019 +0200 +++ b/Samples/Qt/BasicSceneWindow.h Fri Jul 19 15:06:36 2019 +0200 @@ -48,8 +48,6 @@ ~BasicSceneWindow(); QStoneOpenGlWidget& GetOpenGlWidget(); - - void SetCompositor(boost::shared_ptr<OpenGLCompositor> compositor); }; } }
--- a/Samples/Qt/CMakeLists.txt Fri Jul 19 11:40:45 2019 +0200 +++ b/Samples/Qt/CMakeLists.txt Fri Jul 19 15:06:36 2019 +0200 @@ -71,14 +71,13 @@ QStoneOpenGlWidget.h ) -add_executable(BasicScene - BasicScene.cpp - ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.h - ${CMAKE_CURRENT_LIST_DIR}/../Shared/SharedBasicScene.cpp +add_executable(MpBasicScene + ${CMAKE_CURRENT_LIST_DIR}/../MultiPlatform/BasicScene/BasicScene.h + ${CMAKE_CURRENT_LIST_DIR}/../MultiPlatform/BasicScene/BasicScene.cpp + ${CMAKE_CURRENT_LIST_DIR}/../MultiPlatform/BasicScene/mainQt.cpp QStoneOpenGlWidget.cpp ${BASIC_SCENE_APPLICATIONS_SOURCES} ) -target_include_directories(BasicScene PUBLIC ${CMAKE_SOURCE_DIR} ${STONE_SOURCES_DIR}) - -target_link_libraries(BasicScene OrthancStone) +target_include_directories(MpBasicScene PUBLIC ${CMAKE_SOURCE_DIR} ${ORTHANC_STONE_ROOT}) +target_link_libraries(MpBasicScene OrthancStone)
--- a/Samples/Qt/QStoneOpenGlWidget.cpp Fri Jul 19 11:40:45 2019 +0200 +++ b/Samples/Qt/QStoneOpenGlWidget.cpp Fri Jul 19 15:06:36 2019 +0200 @@ -66,7 +66,7 @@ { OrthancStone::GuiAdapterMouseEvent guiEvent; PointerEvent pointerEvent; - ConvertFromPlatform(guiEvent, pointerEvent, *qtEvent, *viewport_); + ConvertFromPlatform(guiEvent, pointerEvent, *qtEvent, *this); guiEvent.type = guiEventType; if (sceneInteractor_.get() != NULL && compositor_.get() != NULL)
--- a/Samples/Qt/QStoneOpenGlWidget.h Fri Jul 19 11:40:45 2019 +0200 +++ b/Samples/Qt/QStoneOpenGlWidget.h Fri Jul 19 15:06:36 2019 +0200 @@ -2,29 +2,45 @@ #include "../../Framework/OpenGL/OpenGLIncludes.h" #include <QOpenGLWidget> #include <QOpenGLFunctions> +#include <QOpenGLContext> #include <boost/shared_ptr.hpp> #include "../../Framework/OpenGL/IOpenGLContext.h" #include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/Viewport/IViewport.h" +#include "../../Framework/Viewport/ViewportBase.h" #include "../../Applications/Generic/Scene2DInteractor.h" namespace OrthancStone { - class QStoneOpenGlWidget : public QOpenGLWidget, public OrthancStone::OpenGL::IOpenGLContext + class QStoneOpenGlWidget : + public QOpenGLWidget, + public OpenGL::IOpenGLContext, + public ViewportBase { - boost::shared_ptr<IViewport> viewport_; - boost::shared_ptr<OrthancStone::OpenGLCompositor> compositor_; + std::unique_ptr<OrthancStone::OpenGLCompositor> compositor_; boost::shared_ptr<Scene2DInteractor> sceneInteractor_; + QOpenGLContext openGlContext_; public: QStoneOpenGlWidget(QWidget *parent) : - QOpenGLWidget(parent) + QOpenGLWidget(parent), + ViewportBase("QtStoneOpenGlWidget") // TODO: we shall be able to define a name but construction time is too early ! { setFocusPolicy(Qt::StrongFocus); // to enable keyPressEvent setMouseTracking(true); // to enable mouseMoveEvent event when no button is pressed } + void Init() + { + QSurfaceFormat requestedFormat; + requestedFormat.setVersion( 2, 0 ); + openGlContext_.setFormat( requestedFormat ); + openGlContext_.create(); + openGlContext_.makeCurrent(context()->surface()); + + compositor_.reset(new OpenGLCompositor(*this, GetScene())); + } + protected: //**** QWidget overrides @@ -55,14 +71,15 @@ } public: + void SetInteractor(boost::shared_ptr<Scene2DInteractor> sceneInteractor) { sceneInteractor_ = sceneInteractor; } - void SetCompositor(boost::shared_ptr<OrthancStone::OpenGLCompositor> compositor) + virtual ICompositor& GetCompositor() { - compositor_ = compositor; + return *compositor_; } protected:
--- a/Samples/Sdl/CMakeLists.txt Fri Jul 19 11:40:45 2019 +0200 +++ b/Samples/Sdl/CMakeLists.txt Fri Jul 19 15:06:36 2019 +0200 @@ -110,19 +110,20 @@ target_link_libraries(FusionMprSdl OrthancStone) # -# RadiographyEditor +# Multiplatform Basic Scene # -LIST(APPEND RADIOGRAPHY_EDITOR_SOURCE "../Shared/RadiographyEditorApp.cpp") -LIST(APPEND RADIOGRAPHY_EDITOR_SOURCE "../Shared/RadiographyEditorApp.h") -LIST(APPEND RADIOGRAPHY_EDITOR_SOURCE "RadiographyEditor.cpp") +LIST(APPEND MP_BASIC_SCENE_SOURCE "../MultiPlatform/BasicScene/BasicScene.cpp") +LIST(APPEND MP_BASIC_SCENE_SOURCE "../MultiPlatform/BasicScene/BasicScene.h") +LIST(APPEND MP_BASIC_SCENE_SOURCE "../MultiPlatform/BasicScene/mainSdl.cpp") if (MSVC AND MSVC_VERSION GREATER 1700) - LIST(APPEND RADIOGRAPHY_EDITOR_SOURCE "cpp.hint") + LIST(APPEND MP_BASIC_SCENE_SOURCE "cpp.hint") endif() -add_executable(RadiographyEditor - ${RADIOGRAPHY_EDITOR_SOURCE} +add_executable(MpBasicScene + ${MP_BASIC_SCENE_SOURCE} ) -target_link_libraries(RadiographyEditor OrthancStone) +target_include_directories(MpBasicScene PUBLIC ${ORTHANC_STONE_ROOT}) +target_link_libraries(MpBasicScene OrthancStone)
--- a/Samples/Sdl/TrackerSampleApp.h Fri Jul 19 11:40:45 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.h Fri Jul 19 15:06:36 2019 +0200 @@ -142,7 +142,7 @@ GuiTool currentTool_; boost::shared_ptr<UndoStack> undoStack_; - SdlViewport viewport_; + SdlOpenGLViewport viewport_; }; }
--- a/Samples/Shared/RadiographyEditorApp.cpp Fri Jul 19 11:40:45 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,786 +0,0 @@ -/** - * 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 <http://www.gnu.org/licenses/>. - **/ - -#include "RadiographyEditorApp.h" - -#include "../../Applications/Sdl/SdlOpenGLWindow.h" - -#include "../../Framework/Scene2D/CairoCompositor.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" -#include "../../Framework/Scene2D/PanSceneTracker.h" -#include "../../Framework/Scene2D/RotateSceneTracker.h" -#include "../../Framework/Scene2D/Scene2D.h" -#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 -#include <Core/Logging.h> -#include <Core/OrthancException.h> -#include <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> - -#include <boost/ref.hpp> -#include <boost/make_shared.hpp> -#include <SDL.h> - -#include <stdio.h> - -namespace OrthancStone -{ - const char* MeasureToolToString(size_t i) - { - static const char* descs[] = { - "GuiTool_Rotate", - "GuiTool_Pan", - "GuiTool_Zoom", - "GuiTool_LineMeasure", - "GuiTool_CircleMeasure", - "GuiTool_AngleMeasure", - "GuiTool_EllipseMeasure", - "GuiTool_LAST" - }; - if (i >= GuiTool_LAST) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Wrong tool index"); - } - return descs[i]; - } - - boost::shared_ptr<Scene2D> RadiographyEditorApp::GetScene() - { - return controller_->GetScene(); - } - - boost::shared_ptr<const Scene2D> RadiographyEditorApp::GetScene() const - { - return controller_->GetScene(); - } - - void RadiographyEditorApp::SelectNextTool() - { - currentTool_ = static_cast<GuiTool>(currentTool_ + 1); - if (currentTool_ == GuiTool_LAST) - currentTool_ = static_cast<GuiTool>(0);; - printf("Current tool is now: %s\n", MeasureToolToString(currentTool_)); - } - - void RadiographyEditorApp::DisplayInfoText() - { - // do not try to use stuff too early! - if (compositor_.get() == NULL) - return; - - std::stringstream msg; - - for (std::map<std::string, std::string>::const_iterator kv = infoTextMap_.begin(); - kv != infoTextMap_.end(); ++kv) - { - msg << kv->first << " : " << kv->second << std::endl; - } - std::string msgS = msg.str(); - - TextSceneLayer* layerP = NULL; - if (GetScene()->HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) - { - TextSceneLayer& layer = dynamic_cast<TextSceneLayer&>( - GetScene()->GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); - layerP = &layer; - } - else - { - std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer); - layerP = layer.get(); - layer->SetColor(0, 255, 0); - layer->SetFontIndex(1); - layer->SetBorder(20); - layer->SetAnchor(BitmapAnchor_TopLeft); - //layer->SetPosition(0,0); - GetScene()->SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); - } - // position the fixed info text in the upper right corner - layerP->SetText(msgS.c_str()); - double cX = compositor_->GetCanvasWidth() * (-0.5); - double cY = compositor_->GetCanvasHeight() * (-0.5); - GetScene()->GetCanvasToSceneTransform().Apply(cX,cY); - layerP->SetPosition(cX, cY); - } - - void RadiographyEditorApp::DisplayFloatingCtrlInfoText(const PointerEvent& e) - { - ScenePoint2D p = e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()); - - char buf[128]; - sprintf(buf, "S:(%0.02f,%0.02f) C:(%0.02f,%0.02f)", - p.GetX(), p.GetY(), - e.GetMainPosition().GetX(), e.GetMainPosition().GetY()); - - if (GetScene()->HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) - { - TextSceneLayer& layer = - dynamic_cast<TextSceneLayer&>(GetScene()->GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); - layer.SetText(buf); - layer.SetPosition(p.GetX(), p.GetY()); - } - else - { - std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer); - layer->SetColor(0, 255, 0); - layer->SetText(buf); - layer->SetBorder(20); - layer->SetAnchor(BitmapAnchor_BottomCenter); - layer->SetPosition(p.GetX(), p.GetY()); - GetScene()->SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); - } - } - - void RadiographyEditorApp::HideInfoText() - { - GetScene()->DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); - } - - ScenePoint2D RadiographyEditorApp::GetRandomPointInScene() const - { - unsigned int w = compositor_->GetCanvasWidth(); - LOG(TRACE) << "compositor_->GetCanvasWidth() = " << - compositor_->GetCanvasWidth(); - unsigned int h = compositor_->GetCanvasHeight(); - LOG(TRACE) << "compositor_->GetCanvasHeight() = " << - compositor_->GetCanvasHeight(); - - if ((w >= RAND_MAX) || (h >= RAND_MAX)) - LOG(WARNING) << "Canvas is too big : tools will not be randomly placed"; - - int x = rand() % w; - int y = rand() % h; - LOG(TRACE) << "random x = " << x << "random y = " << y; - - ScenePoint2D p = compositor_->GetPixelCenterCoordinates(x, y); - LOG(TRACE) << "--> p.GetX() = " << p.GetX() << " p.GetY() = " << p.GetY(); - - ScenePoint2D r = p.Apply(GetScene()->GetCanvasToSceneTransform()); - LOG(TRACE) << "--> r.GetX() = " << r.GetX() << " r.GetY() = " << r.GetY(); - return r; - } - - void RadiographyEditorApp::CreateRandomMeasureTool() - { - static bool srandCalled = false; - if (!srandCalled) - { - srand(42); - srandCalled = true; - } - - int i = rand() % 2; - LOG(TRACE) << "random i = " << i; - switch (i) - { - case 0: - // line measure - { - boost::shared_ptr<CreateLineMeasureCommand> cmd = - boost::make_shared<CreateLineMeasureCommand>( - boost::ref(IObserver::GetBroker()), - controller_, - GetRandomPointInScene()); - cmd->SetEnd(GetRandomPointInScene()); - controller_->PushCommand(cmd); - } - break; - case 1: - // angle measure - { - boost::shared_ptr<CreateAngleMeasureCommand> cmd = - boost::make_shared<CreateAngleMeasureCommand>( - boost::ref(IObserver::GetBroker()), - controller_, - GetRandomPointInScene()); - cmd->SetCenter(GetRandomPointInScene()); - cmd->SetSide2End(GetRandomPointInScene()); - controller_->PushCommand(cmd); - } - break; - } - } - - void RadiographyEditorApp::OnMouseMove(int x, int y, OrthancStone::KeyboardModifiers modifiers) - { - DisplayInfoText(); - if (activeTracker_.get() == NULL && (modifiers & OrthancStone::KeyboardModifiers_Alt)) - { - // The "left-ctrl" key is down, while no tracker is present - // Let's display the info text - PointerEvent e; - e.AddPosition(compositor_->GetPixelCenterCoordinates(x, 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(x, 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(); - } - } - } - - void RadiographyEditorApp::OnKeyPressed(char keyChar, OrthancStone::KeyboardModifiers modifiers) - { - DisplayInfoText(); - - switch (keyChar) - { - case '\033': // escape - { - if (activeTracker_) - { - activeTracker_->Cancel(); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - };break; - case 't': - { - if (!activeTracker_) - SelectNextTool(); - else - { - LOG(WARNING) << "You cannot change the active tool when an interaction" - " is taking place"; - } - };break; - case 'm': - CreateRandomMeasureTool(); - break; - case 's': - controller_->FitContent(compositor_->GetCanvasWidth(), - compositor_->GetCanvasHeight()); - break; - case 'z': - LOG(TRACE) << "z has been pressed. modifier = " << modifiers; - if (modifiers & OrthancStone::KeyboardModifiers_Control) - { - if (controller_->CanUndo()) - { - LOG(TRACE) << "Undoing..."; - controller_->Undo(); - } - else - { - LOG(WARNING) << "Nothing to undo!!!"; - } - } - break; - - case 'y': - LOG(TRACE) << "y has been pressed. modifier = " << modifiers; - if (modifiers & OrthancStone::KeyboardModifiers_Control) - { - if (controller_->CanRedo()) - { - LOG(TRACE) << "Redoing..."; - controller_->Redo(); - } - else - { - LOG(WARNING) << "Nothing to redo!!!"; - } - } - break; - - case 'c': - TakeScreenshot( - "screenshot.png", - compositor_->GetCanvasWidth(), - compositor_->GetCanvasHeight()); - break; - - } - } - - void RadiographyEditorApp::OnMouseDown(int x, int y, OrthancStone::KeyboardModifiers modifiers, OrthancStone::MouseButton button) - { - DisplayInfoText(); - PointerEvent e; - e.AddPosition(compositor_->GetPixelCenterCoordinates(x, y)); - // TODO: set modifiers in e - - if (activeTracker_) - { - activeTracker_->PointerDown(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - else - { - // we ATTEMPT to create a tracker if need be - activeTracker_ = CreateSuitableTracker(button, e); - } - } - - void RadiographyEditorApp::OnMouseUp(int x, int y, OrthancStone::KeyboardModifiers modifiers, OrthancStone::MouseButton button) - { - DisplayInfoText(); - if (activeTracker_) - { - PointerEvent e; - e.AddPosition(compositor_->GetPixelCenterCoordinates(x, y)); - // TODO: set modifiers in e - - activeTracker_->PointerUp(e); - if (!activeTracker_->IsAlive()) - activeTracker_.reset(); - } - } - - void RadiographyEditorApp::HandleApplicationEvent( - const SDL_Event & event) - { - DisplayInfoText(); - - 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)); - // TODO: set modifiers in e - - 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)); - // TODO: set modifiers in e - - //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)); - // TODO: set modifiers in e - 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)); - // TODO: set modifiers in e - 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_t: - if (!activeTracker_) - SelectNextTool(); - else - { - LOG(WARNING) << "You cannot change the active tool when an interaction" - " is taking place"; - } - break; - - case SDLK_m: - CreateRandomMeasureTool(); - break; - case SDLK_s: - controller_->FitContent(compositor_->GetCanvasWidth(), - compositor_->GetCanvasHeight()); - 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; - } - } - } - - - void RadiographyEditorApp::OnSceneTransformChanged( - const ViewportController::SceneTransformChanged& message) - { - DisplayInfoText(); - } - - boost::shared_ptr<IFlexiblePointerTracker> RadiographyEditorApp::CreateSuitableTracker( - OrthancStone::MouseButton button, - const PointerEvent & e) - { - using namespace Orthanc; - - switch (button) - { - case OrthancStone::MouseButton_Middle: - return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker - (controller_, e)); - - case OrthancStone::MouseButton_Right: - return boost::shared_ptr<IFlexiblePointerTracker>(new ZoomSceneTracker - (controller_, e, compositor_->GetCanvasHeight())); - - case OrthancStone::MouseButton_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 GuiTool_Rotate: - //LOG(TRACE) << "Creating RotateSceneTracker"; - return boost::shared_ptr<IFlexiblePointerTracker>(new RotateSceneTracker( - controller_, e)); - case GuiTool_Pan: - return boost::shared_ptr<IFlexiblePointerTracker>(new PanSceneTracker( - controller_, e)); - case GuiTool_Zoom: - return boost::shared_ptr<IFlexiblePointerTracker>(new ZoomSceneTracker( - controller_, 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 GuiTool_LineMeasure: - return boost::shared_ptr<IFlexiblePointerTracker>(new CreateLineMeasureTracker( - IObserver::GetBroker(), controller_, e)); - case GuiTool_AngleMeasure: - return boost::shared_ptr<IFlexiblePointerTracker>(new CreateAngleMeasureTracker( - IObserver::GetBroker(), controller_, e)); - case GuiTool_CircleMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr<IFlexiblePointerTracker>(); - case GuiTool_EllipseMeasure: - LOG(ERROR) << "Not implemented yet!"; - return boost::shared_ptr<IFlexiblePointerTracker>(); - default: - throw OrthancException(ErrorCode_InternalError, "Wrong tool!"); - } - } - } - default: - return boost::shared_ptr<IFlexiblePointerTracker>(); - } - } - - - RadiographyEditorApp::RadiographyEditorApp(OrthancStone::IOracle& oracle, - IObservable& oracleObservable, - ICompositorFactory* compositorFactory) : - IObserver(oracleObservable.GetBroker()), - oracle_(oracle), - compositorFactory_(compositorFactory), - currentTool_(GuiTool_Rotate) - { - boost::shared_ptr<UndoStack> undoStack(new UndoStack); - controller_ = boost::shared_ptr<ViewportController>(new ViewportController(undoStack, IObserver::GetBroker())); - - controller_->RegisterObserverCallback( - new Callable<RadiographyEditorApp, ViewportController::SceneTransformChanged> - (*this, &RadiographyEditorApp::OnSceneTransformChanged)); - - TEXTURE_2x2_1_ZINDEX = 1; - TEXTURE_1x1_ZINDEX = 2; - TEXTURE_2x2_2_ZINDEX = 3; - LINESET_1_ZINDEX = 4; - LINESET_2_ZINDEX = 5; - FLOATING_INFOTEXT_LAYER_ZINDEX = 6; - FIXED_INFOTEXT_LAYER_ZINDEX = 7; - } - - void RadiographyEditorApp::PrepareScene() - { - // Texture of 2x2 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); - - uint8_t* p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast<uint8_t*>(i.GetRow(1)); - p[0] = 0; - p[1] = 0; - p[2] = 255; - - p[3] = 255; - p[4] = 0; - p[5] = 0; - - GetScene()->SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); - - std::auto_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-3, 2); - l->SetPixelSpacing(1.5, 1); - l->SetAngle(20.0 / 180.0 * M_PI); - GetScene()->SetLayer(TEXTURE_2x2_2_ZINDEX, l.release()); - } - - // Texture of 1x1 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 1, 1, false); - - uint8_t* p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - std::auto_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); - l->SetOrigin(-2, 1); - l->SetAngle(20.0 / 180.0 * M_PI); - GetScene()->SetLayer(TEXTURE_1x1_ZINDEX, l.release()); - } - - // Some lines - { - std::auto_ptr<PolylineSceneLayer> 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); - - GetScene()->SetLayer(LINESET_1_ZINDEX, layer.release()); - } - - // Some text - { - std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer); - layer->SetText("Hello"); - GetScene()->SetLayer(LINESET_2_ZINDEX, layer.release()); - } - } - - - void RadiographyEditorApp::DisableTracker() - { - if (activeTracker_) - { - activeTracker_->Cancel(); - activeTracker_.reset(); - } - } - - void RadiographyEditorApp::TakeScreenshot(const std::string& target, - unsigned int canvasWidth, - unsigned int canvasHeight) - { - CairoCompositor compositor(*GetScene(), canvasWidth, canvasHeight); - compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, 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); - } - - - boost::shared_ptr<IFlexiblePointerTracker> RadiographyEditorApp::TrackerHitTest(const PointerEvent & e) - { - // std::vector<boost::shared_ptr<MeasureTool>> measureTools_; - return boost::shared_ptr<IFlexiblePointerTracker>(); - } - - - void RadiographyEditorApp::FitContent(unsigned int width, unsigned int height) - { - controller_->FitContent(width, height); - } - - void RadiographyEditorApp::UpdateSize() - { - if (dynamic_cast<OpenGLCompositor*>(compositor_.get()) != NULL) - { - dynamic_cast<OpenGLCompositor*>(compositor_.get())->UpdateSize(); - } - } - - void RadiographyEditorApp::Refresh() - { - compositor_.reset(compositorFactory_->GetCompositor(*GetScene())); - compositor_->Refresh(); - - // the following is paramount because the compositor holds a reference - // to the scene and we do not want this reference to become dangling - // TODO ???? compositor_.reset(NULL); - } - - void RadiographyEditorApp::SetInfoDisplayMessage( - std::string key, std::string value) - { - if (value == "") - infoTextMap_.erase(key); - else - infoTextMap_[key] = value; - DisplayInfoText(); - } - -}
--- a/Samples/Shared/RadiographyEditorApp.h Fri Jul 19 11:40:45 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -/** - * 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 <http://www.gnu.org/licenses/>. - **/ - - -#include "../../Framework/Messages/IObserver.h" -#include "../../Framework/Oracle/IOracle.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/Scene2D/Internals/CompositorHelper.h" -#include "../../Framework/Scene2DViewport/IFlexiblePointerTracker.h" -#include "../../Framework/Scene2DViewport/MeasureTool.h" -#include "../../Framework/Scene2DViewport/PredeclaredTypes.h" -#include "../../Framework/Scene2DViewport/ViewportController.h" - -#include <SDL.h> - -#include <boost/make_shared.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> - - -namespace OrthancStone -{ - class ICompositorFactory - { - public: - virtual OrthancStone::ICompositor* GetCompositor(const OrthancStone::Scene2D& scene) = 0; - }; - - class IInteractor - { - public: - virtual void OnMouseDown(int x, int y, OrthancStone::KeyboardModifiers modifiers, OrthancStone::MouseButton button) = 0; - virtual void OnMouseMove(int x, int y, OrthancStone::KeyboardModifiers modifiers) = 0; - virtual void OnMouseUp(int x, int y, OrthancStone::KeyboardModifiers modifiers, OrthancStone::MouseButton button) = 0; - virtual void OnKeyPressed(char keyChar, OrthancStone::KeyboardModifiers modifiers) = 0; - }; - - - - - enum GuiTool - { - GuiTool_Rotate = 0, - GuiTool_Pan, - GuiTool_Zoom, - GuiTool_LineMeasure, - GuiTool_CircleMeasure, - GuiTool_AngleMeasure, - GuiTool_EllipseMeasure, - GuiTool_LAST - }; - - const char* MeasureToolToString(size_t i); - - static const unsigned int FONT_SIZE_0 = 32; - static const unsigned int FONT_SIZE_1 = 24; - - class Scene2D; - - class RadiographyEditorApp : public IObserver - , public IInteractor, public boost::enable_shared_from_this<RadiographyEditorApp> - { - OrthancStone::IOracle& oracle_; - std::auto_ptr<ICompositorFactory> compositorFactory_; - std::auto_ptr<ICompositor> compositor_; - - public: - // 12 because. - RadiographyEditorApp(OrthancStone::IOracle& oracle, IObservable& oracleObservable, ICompositorFactory* compositorFactory); - - void PrepareScene(); - void FitContent(unsigned int width, unsigned int height); - void Refresh(); - void UpdateSize(); - void SetInfoDisplayMessage(std::string key, std::string value); - void DisableTracker(); - - virtual void OnMouseMove(int x, int y, OrthancStone::KeyboardModifiers modifiers); - virtual void OnKeyPressed(char keyChar, OrthancStone::KeyboardModifiers modifiers); - virtual void OnMouseDown(int x, int y, OrthancStone::KeyboardModifiers modifiers, OrthancStone::MouseButton button); - virtual void OnMouseUp(int x, int y, OrthancStone::KeyboardModifiers modifiers, OrthancStone::MouseButton button); - - boost::shared_ptr<Scene2D> GetScene(); - boost::shared_ptr<const Scene2D> GetScene() const; - - void HandleApplicationEvent(const SDL_Event& event); - - /** - This method is called when the scene transform changes. It allows to - recompute the visual elements whose content depend upon the scene transform - */ - void OnSceneTransformChanged( - const ViewportController::SceneTransformChanged& message); - - private: - void SelectNextTool(); - void CreateRandomMeasureTool(); - - /** - This returns a random point in the canvas part of the scene, but in - scene coordinates - */ - ScenePoint2D GetRandomPointInScene() const; - - boost::shared_ptr<IFlexiblePointerTracker> TrackerHitTest(const PointerEvent& e); - - boost::shared_ptr<IFlexiblePointerTracker> CreateSuitableTracker( - OrthancStone::MouseButton button, - const PointerEvent& e); - - void TakeScreenshot( - const std::string& target, - unsigned int canvasWidth, - unsigned int canvasHeight); - - /** - This adds the command at the top of the undo stack - */ - void Commit(boost::shared_ptr<TrackerCommand> cmd); - void Undo(); - void Redo(); - - private: - void DisplayFloatingCtrlInfoText(const PointerEvent& e); - void DisplayInfoText(); - void HideInfoText(); - - private: - /** - WARNING: the measuring tools do store a reference to the scene, and it - paramount that the scene gets destroyed AFTER the measurement tools. - */ - boost::shared_ptr<ViewportController> controller_; - - std::map<std::string, std::string> infoTextMap_; - boost::shared_ptr<IFlexiblePointerTracker> activeTracker_; - - //static const int LAYER_POSITION = 150; - - int TEXTURE_2x2_1_ZINDEX; - int TEXTURE_1x1_ZINDEX; - int TEXTURE_2x2_2_ZINDEX; - int LINESET_1_ZINDEX; - int LINESET_2_ZINDEX; - int FLOATING_INFOTEXT_LAYER_ZINDEX; - int FIXED_INFOTEXT_LAYER_ZINDEX; - - GuiTool currentTool_; - }; - -}
--- a/Samples/Shared/SharedBasicScene.cpp Fri Jul 19 11:40:45 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +0,0 @@ -/** - * 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 <http://www.gnu.org/licenses/>. - **/ - -#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 <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> - -using namespace OrthancStone; - -const unsigned int BASIC_SCENE_FONT_SIZE = 32; -const int BASIC_SCENE_LAYER_POSITION = 150; - -void PrepareScene(Scene2D& scene) -{ - //Scene2D& scene(*controller->GetScene()); - // Texture of 2x2 size - { - Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); - - uint8_t *p = reinterpret_cast<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - p[3] = 0; - p[4] = 255; - p[5] = 0; - - p = reinterpret_cast<uint8_t*>(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<ColorTextureSceneLayer> 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<uint8_t*>(i.GetRow(0)); - p[0] = 255; - p[1] = 0; - p[2] = 0; - - std::auto_ptr<ColorTextureSceneLayer> 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<PolylineSceneLayer> 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<TextSceneLayer> layer(new TextSceneLayer); - layer->SetText("Hello"); - scene.SetLayer(100, layer.release()); - } -} - -#if ORTHANC_SANDBOXED == 0 -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); -} -#endif - -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<TextSceneLayer&>(scene.GetLayer(BASIC_SCENE_LAYER_POSITION)); - layer.SetText(buf); - layer.SetPosition(p.GetX(), p.GetY()); - } - else - { - std::auto_ptr<TextSceneLayer> - 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; - default: - return false; - } - 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_->GetCanvasHeight())); - } - } - 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_->GetCanvasWidth(), compositor_->GetCanvasHeight()); - return true; - }; -#if ORTHANC_SANDBOXED == 0 - case 'c': - { - Scene2D& scene(viewportController_->GetScene()); - TakeScreenshot("screenshot.png", scene, compositor_->GetCanvasWidth(), compositor_->GetCanvasHeight()); - return true; - } -#endif - 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; -}
--- a/Samples/Shared/SharedBasicScene.h Fri Jul 19 11:40:45 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/** - * 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include <boost/shared_ptr.hpp> -#include "../../Framework/Scene2DViewport/ViewportController.h" -#include "../../Framework/Scene2D/Scene2D.h" - -extern const unsigned int BASIC_SCENE_FONT_SIZE; -extern const int BASIC_SCENE_LAYER_POSITION; - -extern void PrepareScene(OrthancStone::Scene2D& scene); -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<OrthancStone::IFlexiblePointerTracker> currentTracker_; - bool showCursorInfo_; -public: - BasicScene2DInteractor(boost::shared_ptr<OrthancStone::ViewportController> viewportController) : - Scene2DInteractor(viewportController), - showCursorInfo_(false) - {} - - virtual bool OnMouseEvent(const OrthancStone::GuiAdapterMouseEvent& event, const OrthancStone::PointerEvent& pointerEvent) override; - virtual bool OnKeyboardEvent(const OrthancStone::GuiAdapterKeyboardEvent& guiEvent) override; - virtual bool OnWheelEvent(const OrthancStone::GuiAdapterWheelEvent& guiEvent) override; -}; -