comparison Samples/Sdl/BasicScene.cpp @ 700:059e1fd05fd6 refactor-viewport-controller

Introduced the ViewportController that sits between the application and the Scene2D to handle the trackers and measuring tools. This is a work in progress. The Scene2D is no longer an observable. Message sending is managed by the ViewportController. Move some refs to shared and weak to prevent lifetime issues.
author Benjamin Golinvaux <bgo@osimis.io>
date Sun, 19 May 2019 16:26:17 +0200
parents 462a5074f914
children ef07304d4423
comparison
equal deleted inserted replaced
699:5c551f078c18 700:059e1fd05fd6
26 #include "../../Framework/Scene2D/OpenGLCompositor.h" 26 #include "../../Framework/Scene2D/OpenGLCompositor.h"
27 #include "../../Framework/Scene2D/PanSceneTracker.h" 27 #include "../../Framework/Scene2D/PanSceneTracker.h"
28 #include "../../Framework/Scene2D/RotateSceneTracker.h" 28 #include "../../Framework/Scene2D/RotateSceneTracker.h"
29 #include "../../Framework/Scene2D/Scene2D.h" 29 #include "../../Framework/Scene2D/Scene2D.h"
30 #include "../../Framework/Scene2D/ZoomSceneTracker.h" 30 #include "../../Framework/Scene2D/ZoomSceneTracker.h"
31 #include "../../Framework/Scene2DViewport/ViewportController.h"
32
31 #include "../../Framework/StoneInitialization.h" 33 #include "../../Framework/StoneInitialization.h"
32 #include "../../Framework/Messages/MessageBroker.h" 34 #include "../../Framework/Messages/MessageBroker.h"
33 35
34 // From Orthanc framework 36 // From Orthanc framework
35 #include <Core/Logging.h> 37 #include <Core/Logging.h>
42 #include <stdio.h> 44 #include <stdio.h>
43 45
44 static const unsigned int FONT_SIZE = 32; 46 static const unsigned int FONT_SIZE = 32;
45 static const int LAYER_POSITION = 150; 47 static const int LAYER_POSITION = 150;
46 48
47 49 using namespace OrthancStone;
48 void PrepareScene(OrthancStone::Scene2D& scene) 50
49 { 51 void PrepareScene(ViewportControllerPtr controller)
50 using namespace OrthancStone; 52 {
51 53 Scene2D& scene(*controller->GetScene());
52 // Texture of 2x2 size 54 // Texture of 2x2 size
53 { 55 {
54 Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); 56 Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false);
55 57
56 uint8_t *p = reinterpret_cast<uint8_t*>(i.GetRow(0)); 58 uint8_t *p = reinterpret_cast<uint8_t*>(i.GetRow(0));
135 } 137 }
136 } 138 }
137 139
138 140
139 void TakeScreenshot(const std::string& target, 141 void TakeScreenshot(const std::string& target,
140 const OrthancStone::Scene2D& scene, 142 const Scene2D& scene,
141 unsigned int canvasWidth, 143 unsigned int canvasWidth,
142 unsigned int canvasHeight) 144 unsigned int canvasHeight)
143 { 145 {
144 // Take a screenshot, then save it as PNG file 146 // Take a screenshot, then save it as PNG file
145 OrthancStone::CairoCompositor compositor(scene, canvasWidth, canvasHeight); 147 CairoCompositor compositor(scene, canvasWidth, canvasHeight);
146 compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1); 148 compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1);
147 compositor.Refresh(); 149 compositor.Refresh();
148 150
149 Orthanc::ImageAccessor canvas; 151 Orthanc::ImageAccessor canvas;
150 compositor.GetCanvas().GetReadOnlyAccessor(canvas); 152 compositor.GetCanvas().GetReadOnlyAccessor(canvas);
155 Orthanc::PngWriter writer; 157 Orthanc::PngWriter writer;
156 writer.WriteToFile(target, png); 158 writer.WriteToFile(target, png);
157 } 159 }
158 160
159 161
160 void HandleApplicationEvent(OrthancStone::Scene2D& scene, 162 void HandleApplicationEvent(ViewportControllerPtr controller,
161 const OrthancStone::OpenGLCompositor& compositor, 163 const OpenGLCompositor& compositor,
162 const SDL_Event& event, 164 const SDL_Event& event,
163 std::auto_ptr<OrthancStone::IPointerTracker>& activeTracker) 165 FlexiblePointerTrackerPtr& activeTracker)
164 { 166 {
167 Scene2D& scene(*controller->GetScene());
165 if (event.type == SDL_MOUSEMOTION) 168 if (event.type == SDL_MOUSEMOTION)
166 { 169 {
167 int scancodeCount = 0; 170 int scancodeCount = 0;
168 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); 171 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount);
169 172
171 SDL_SCANCODE_LCTRL < scancodeCount && 174 SDL_SCANCODE_LCTRL < scancodeCount &&
172 keyboardState[SDL_SCANCODE_LCTRL]) 175 keyboardState[SDL_SCANCODE_LCTRL])
173 { 176 {
174 // The "left-ctrl" key is down, while no tracker is present 177 // The "left-ctrl" key is down, while no tracker is present
175 178
176 OrthancStone::PointerEvent e; 179 PointerEvent e;
177 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); 180 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y));
178 181
179 OrthancStone::ScenePoint2D p = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); 182 ScenePoint2D p = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform());
180 183
181 char buf[64]; 184 char buf[64];
182 sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY()); 185 sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY());
183 186
184 if (scene.HasLayer(LAYER_POSITION)) 187 if (scene.HasLayer(LAYER_POSITION))
185 { 188 {
186 OrthancStone::TextSceneLayer& layer = 189 TextSceneLayer& layer =
187 dynamic_cast<OrthancStone::TextSceneLayer&>(scene.GetLayer(LAYER_POSITION)); 190 dynamic_cast<TextSceneLayer&>(scene.GetLayer(LAYER_POSITION));
188 layer.SetText(buf); 191 layer.SetText(buf);
189 layer.SetPosition(p.GetX(), p.GetY()); 192 layer.SetPosition(p.GetX(), p.GetY());
190 } 193 }
191 else 194 else
192 { 195 {
193 std::auto_ptr<OrthancStone::TextSceneLayer> layer(new OrthancStone::TextSceneLayer); 196 std::auto_ptr<TextSceneLayer>
197 layer(new TextSceneLayer);
194 layer->SetColor(0, 255, 0); 198 layer->SetColor(0, 255, 0);
195 layer->SetText(buf); 199 layer->SetText(buf);
196 layer->SetBorder(20); 200 layer->SetBorder(20);
197 layer->SetAnchor(OrthancStone::BitmapAnchor_BottomCenter); 201 layer->SetAnchor(BitmapAnchor_BottomCenter);
198 layer->SetPosition(p.GetX(), p.GetY()); 202 layer->SetPosition(p.GetX(), p.GetY());
199 scene.SetLayer(LAYER_POSITION, layer.release()); 203 scene.SetLayer(LAYER_POSITION, layer.release());
200 } 204 }
201 } 205 }
202 else 206 else
204 scene.DeleteLayer(LAYER_POSITION); 208 scene.DeleteLayer(LAYER_POSITION);
205 } 209 }
206 } 210 }
207 else if (event.type == SDL_MOUSEBUTTONDOWN) 211 else if (event.type == SDL_MOUSEBUTTONDOWN)
208 { 212 {
209 OrthancStone::PointerEvent e; 213 PointerEvent e;
210 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); 214 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y));
211 215
212 switch (event.button.button) 216 switch (event.button.button)
213 { 217 {
214 case SDL_BUTTON_MIDDLE: 218 case SDL_BUTTON_MIDDLE:
215 activeTracker.reset(new OrthancStone::PanSceneTracker(scene, e)); 219 activeTracker.reset(new PanSceneTracker(
220 controller, e));
216 break; 221 break;
217 222
218 case SDL_BUTTON_RIGHT: 223 case SDL_BUTTON_RIGHT:
219 activeTracker.reset(new OrthancStone::ZoomSceneTracker(scene, e, 224 activeTracker.reset(new ZoomSceneTracker(
220 compositor.GetCanvasHeight())); 225 controller, e, compositor.GetCanvasHeight()));
221 break; 226 break;
222 227
223 case SDL_BUTTON_LEFT: 228 case SDL_BUTTON_LEFT:
224 activeTracker.reset(new OrthancStone::RotateSceneTracker(scene, e)); 229 activeTracker.reset(new RotateSceneTracker(
230 controller, e));
225 break; 231 break;
226 232
227 default: 233 default:
228 break; 234 break;
229 } 235 }
267 type, severity, message ); 273 type, severity, message );
268 } 274 }
269 } 275 }
270 276
271 277
272 void Run(OrthancStone::Scene2D& scene) 278 void Run(ViewportControllerPtr controller)
273 { 279 {
274 OrthancStone::SdlOpenGLWindow window("Hello", 1024, 768); 280 SdlOpenGLWindow window("Hello", 1024, 768);
275 281
276 scene.FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); 282 controller->GetScene()->FitContent(
283 window.GetCanvasWidth(), window.GetCanvasHeight());
277 284
278 glEnable(GL_DEBUG_OUTPUT); 285 glEnable(GL_DEBUG_OUTPUT);
279 glDebugMessageCallback(OpenGLMessageCallback, 0); 286 glDebugMessageCallback(OpenGLMessageCallback, 0);
280 287
281 OrthancStone::OpenGLCompositor compositor(window, scene); 288 OpenGLCompositor compositor(window, *controller->GetScene());
282 compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, 289 compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT,
283 FONT_SIZE, Orthanc::Encoding_Latin1); 290 FONT_SIZE, Orthanc::Encoding_Latin1);
284 291
285 std::auto_ptr<OrthancStone::IPointerTracker> tracker; 292 FlexiblePointerTrackerPtr tracker;
286 293
287 bool stop = false; 294 bool stop = false;
288 while (!stop) 295 while (!stop)
289 { 296 {
290 compositor.Refresh(); 297 compositor.Refresh();
298 stop = true; 305 stop = true;
299 break; 306 break;
300 } 307 }
301 else if (event.type == SDL_MOUSEMOTION) 308 else if (event.type == SDL_MOUSEMOTION)
302 { 309 {
303 if (tracker.get() != NULL) 310 if (tracker)
304 { 311 {
305 OrthancStone::PointerEvent e; 312 PointerEvent e;
306 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); 313 e.AddPosition(compositor.GetPixelCenterCoordinates(
307 tracker->Update(e); 314 event.button.x, event.button.y));
315 tracker->PointerMove(e);
308 } 316 }
309 } 317 }
310 else if (event.type == SDL_MOUSEBUTTONUP) 318 else if (event.type == SDL_MOUSEBUTTONUP)
311 { 319 {
312 if (tracker.get() != NULL) 320 if (tracker)
313 { 321 {
314 tracker->Release(); 322 PointerEvent e;
315 tracker.reset(NULL); 323 e.AddPosition(compositor.GetPixelCenterCoordinates(
324 event.button.x, event.button.y));
325 tracker->PointerUp(e);
326 if(!tracker->IsAlive())
327 tracker = NULL;
316 } 328 }
317 } 329 }
318 else if (event.type == SDL_WINDOWEVENT && 330 else if (event.type == SDL_WINDOWEVENT &&
319 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) 331 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
320 { 332 {
321 tracker.reset(NULL); 333 tracker = NULL;
322 compositor.UpdateSize(); 334 compositor.UpdateSize();
323 } 335 }
324 else if (event.type == SDL_KEYDOWN && 336 else if (event.type == SDL_KEYDOWN &&
325 event.key.repeat == 0 /* Ignore key bounce */) 337 event.key.repeat == 0 /* Ignore key bounce */)
326 { 338 {
337 default: 349 default:
338 break; 350 break;
339 } 351 }
340 } 352 }
341 353
342 HandleApplicationEvent(scene, compositor, event, tracker); 354 HandleApplicationEvent(controller, compositor, event, tracker);
343 } 355 }
344 356
345 SDL_Delay(1); 357 SDL_Delay(1);
346 } 358 }
347 } 359 }
354 * Windows. Otherwise, one gets the linking error "undefined reference 366 * Windows. Otherwise, one gets the linking error "undefined reference
355 * to `SDL_main'". https://wiki.libsdl.org/FAQWindows 367 * to `SDL_main'". https://wiki.libsdl.org/FAQWindows
356 **/ 368 **/
357 int main(int argc, char* argv[]) 369 int main(int argc, char* argv[])
358 { 370 {
359 OrthancStone::StoneInitialize(); 371 StoneInitialize();
360 Orthanc::Logging::EnableInfoLevel(true); 372 Orthanc::Logging::EnableInfoLevel(true);
361 373
362 try 374 try
363 { 375 {
364 OrthancStone::MessageBroker broker; 376 MessageBroker broker;
365 OrthancStone::Scene2D scene(broker); 377 ViewportControllerPtr controller(
366 PrepareScene(scene); 378 new ViewportController(broker));
367 Run(scene); 379 PrepareScene(controller);
380 Run(controller);
368 } 381 }
369 catch (Orthanc::OrthancException& e) 382 catch (Orthanc::OrthancException& e)
370 { 383 {
371 LOG(ERROR) << "EXCEPTION: " << e.What(); 384 LOG(ERROR) << "EXCEPTION: " << e.What();
372 } 385 }
373 386
374 OrthancStone::StoneFinalize(); 387 StoneFinalize();
375 388
376 return 0; 389 return 0;
377 } 390 }