Mercurial > hg > orthanc-stone
comparison Samples/Sdl/TrackerSampleApp.cpp @ 656:002d9562c8f5
Added support to DISABLE legacy scaling in SDL Windows (only in WIN32... this
might also be needed on macos and GNU/Linux ?) + fixed text info overlay pos
for angle measure (this requires the app to be aware of the compositor)
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Tue, 14 May 2019 16:54:13 +0200 |
parents | 462a5074f914 |
children | cb3b76d16234 |
comparison
equal
deleted
inserted
replaced
655:1e26bb5f2a02 | 656:002d9562c8f5 |
---|---|
78 if (currentTool_ == GuiTool_LAST) | 78 if (currentTool_ == GuiTool_LAST) |
79 currentTool_ = static_cast<GuiTool>(0);; | 79 currentTool_ = static_cast<GuiTool>(0);; |
80 printf("Current tool is now: %s\n", MeasureToolToString(currentTool_)); | 80 printf("Current tool is now: %s\n", MeasureToolToString(currentTool_)); |
81 } | 81 } |
82 | 82 |
83 void TrackerSampleApp::DisplayInfoText(const PointerEvent& e) | 83 void TrackerSampleApp::DisplayInfoText() |
84 { | |
85 char buf[256]; | |
86 sprintf(buf, "INFO TEXT\n*** INFO TEXT ***\ntoto tata tutu titi\nprrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrout"); | |
87 | |
88 TextSceneLayer* layerP = NULL; | |
89 if (scene_.HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) | |
90 { | |
91 TextSceneLayer& layer = dynamic_cast<TextSceneLayer&>( | |
92 scene_.GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); | |
93 layerP = &layer; | |
94 } | |
95 else | |
96 { | |
97 std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer); | |
98 layerP = layer.get(); | |
99 layer->SetColor(0, 255, 0); | |
100 layer->SetFontIndex(1); | |
101 layer->SetText(buf); | |
102 layer->SetBorder(20); | |
103 layer->SetAnchor(BitmapAnchor_TopLeft); | |
104 //layer->SetPosition(0,0); | |
105 scene_.SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); | |
106 } | |
107 // position the fixed info text in the upper right corner | |
108 layerP->SetText(buf); | |
109 double cX = compositor_->GetCanvasWidth() * (-0.5); | |
110 double cY = compositor_->GetCanvasHeight() * (-0.5); | |
111 scene_.GetCanvasToSceneTransform().Apply(cX,cY); | |
112 layerP->SetPosition(cX, cY); | |
113 } | |
114 | |
115 void TrackerSampleApp::DisplayFloatingCtrlInfoText(const PointerEvent& e) | |
84 { | 116 { |
85 ScenePoint2D p = e.GetMainPosition().Apply(scene_.GetCanvasToSceneTransform()); | 117 ScenePoint2D p = e.GetMainPosition().Apply(scene_.GetCanvasToSceneTransform()); |
86 | 118 |
87 char buf[64]; | 119 char buf[128]; |
88 sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY()); | 120 sprintf(buf, "S:(%0.02f,%0.02f) C:(%0.02f,%0.02f)", |
89 | 121 p.GetX(), p.GetY(), |
90 if (scene_.HasLayer(INFOTEXT_LAYER_ZINDEX)) | 122 e.GetMainPosition().GetX(), e.GetMainPosition().GetY()); |
123 | |
124 if (scene_.HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) | |
91 { | 125 { |
92 TextSceneLayer& layer = | 126 TextSceneLayer& layer = |
93 dynamic_cast<TextSceneLayer&>(scene_.GetLayer(INFOTEXT_LAYER_ZINDEX)); | 127 dynamic_cast<TextSceneLayer&>(scene_.GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); |
94 layer.SetText(buf); | 128 layer.SetText(buf); |
95 layer.SetPosition(p.GetX(), p.GetY()); | 129 layer.SetPosition(p.GetX(), p.GetY()); |
96 } | 130 } |
97 else | 131 else |
98 { | 132 { |
100 layer->SetColor(0, 255, 0); | 134 layer->SetColor(0, 255, 0); |
101 layer->SetText(buf); | 135 layer->SetText(buf); |
102 layer->SetBorder(20); | 136 layer->SetBorder(20); |
103 layer->SetAnchor(BitmapAnchor_BottomCenter); | 137 layer->SetAnchor(BitmapAnchor_BottomCenter); |
104 layer->SetPosition(p.GetX(), p.GetY()); | 138 layer->SetPosition(p.GetX(), p.GetY()); |
105 scene_.SetLayer(INFOTEXT_LAYER_ZINDEX, layer.release()); | 139 scene_.SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); |
106 } | 140 } |
107 } | 141 } |
108 | 142 |
109 void TrackerSampleApp::HideInfoText() | 143 void TrackerSampleApp::HideInfoText() |
110 { | 144 { |
111 scene_.DeleteLayer(INFOTEXT_LAYER_ZINDEX); | 145 scene_.DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); |
112 } | 146 } |
113 | 147 |
114 void TrackerSampleApp::HandleApplicationEvent( | 148 void TrackerSampleApp::HandleApplicationEvent( |
115 const OpenGLCompositor & compositor, | |
116 const SDL_Event & event) | 149 const SDL_Event & event) |
117 { | 150 { |
151 DisplayInfoText(); | |
152 | |
118 if (event.type == SDL_MOUSEMOTION) | 153 if (event.type == SDL_MOUSEMOTION) |
119 { | 154 { |
120 int scancodeCount = 0; | 155 int scancodeCount = 0; |
121 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); | 156 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); |
122 | 157 |
125 keyboardState[SDL_SCANCODE_LCTRL]) | 160 keyboardState[SDL_SCANCODE_LCTRL]) |
126 { | 161 { |
127 // The "left-ctrl" key is down, while no tracker is present | 162 // The "left-ctrl" key is down, while no tracker is present |
128 // Let's display the info text | 163 // Let's display the info text |
129 PointerEvent e; | 164 PointerEvent e; |
130 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); | 165 e.AddPosition(compositor_->GetPixelCenterCoordinates( |
131 DisplayInfoText(e); | 166 event.button.x, event.button.y)); |
167 | |
168 DisplayFloatingCtrlInfoText(e); | |
132 } | 169 } |
133 else | 170 else |
134 { | 171 { |
135 HideInfoText(); | 172 HideInfoText(); |
136 //LOG(TRACE) << "(event.type == SDL_MOUSEMOTION)"; | 173 //LOG(TRACE) << "(event.type == SDL_MOUSEMOTION)"; |
137 if (activeTracker_.get() != NULL) | 174 if (activeTracker_.get() != NULL) |
138 { | 175 { |
139 //LOG(TRACE) << "(activeTracker_.get() != NULL)"; | 176 //LOG(TRACE) << "(activeTracker_.get() != NULL)"; |
140 PointerEvent e; | 177 PointerEvent e; |
141 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); | 178 e.AddPosition(compositor_->GetPixelCenterCoordinates( |
179 event.button.x, event.button.y)); | |
180 | |
142 //LOG(TRACE) << "event.button.x = " << event.button.x << " " << | 181 //LOG(TRACE) << "event.button.x = " << event.button.x << " " << |
143 // "event.button.y = " << event.button.y; | 182 // "event.button.y = " << event.button.y; |
144 //LOG(TRACE) << "activeTracker_->PointerMove(e); " << | 183 //LOG(TRACE) << "activeTracker_->PointerMove(e); " << |
145 // e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); | 184 // e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); |
185 | |
146 activeTracker_->PointerMove(e); | 186 activeTracker_->PointerMove(e); |
147 if (!activeTracker_->IsActive()) | 187 if (!activeTracker_->IsActive()) |
148 activeTracker_ = NULL; | 188 activeTracker_ = NULL; |
149 } | 189 } |
150 } | 190 } |
152 else if (event.type == SDL_MOUSEBUTTONUP) | 192 else if (event.type == SDL_MOUSEBUTTONUP) |
153 { | 193 { |
154 if (activeTracker_) | 194 if (activeTracker_) |
155 { | 195 { |
156 PointerEvent e; | 196 PointerEvent e; |
157 e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); | 197 e.AddPosition(compositor_->GetPixelCenterCoordinates(event.button.x, event.button.y)); |
158 activeTracker_->PointerUp(e); | 198 activeTracker_->PointerUp(e); |
159 if (!activeTracker_->IsActive()) | 199 if (!activeTracker_->IsActive()) |
160 activeTracker_ = NULL; | 200 activeTracker_ = NULL; |
161 } | 201 } |
162 } | 202 } |
163 else if (event.type == SDL_MOUSEBUTTONDOWN) | 203 else if (event.type == SDL_MOUSEBUTTONDOWN) |
164 { | 204 { |
165 PointerEvent e; | 205 PointerEvent e; |
166 e.AddPosition(compositor.GetPixelCenterCoordinates( | 206 e.AddPosition(compositor_->GetPixelCenterCoordinates( |
167 event.button.x, event.button.y)); | 207 event.button.x, event.button.y)); |
168 if (activeTracker_) | 208 if (activeTracker_) |
169 { | 209 { |
170 activeTracker_->PointerDown(e); | 210 activeTracker_->PointerDown(e); |
171 if (!activeTracker_->IsActive()) | 211 if (!activeTracker_->IsActive()) |
172 activeTracker_ = NULL; | 212 activeTracker_ = NULL; |
173 } | 213 } |
174 else | 214 else |
175 { | 215 { |
176 // we ATTEMPT to create a tracker if need be | 216 // we ATTEMPT to create a tracker if need be |
177 activeTracker_ = CreateSuitableTracker(event, e, compositor); | 217 activeTracker_ = CreateSuitableTracker(event, e); |
178 } | 218 } |
179 } | 219 } |
180 else if (event.type == SDL_KEYDOWN && | 220 else if (event.type == SDL_KEYDOWN && |
181 event.key.repeat == 0 /* Ignore key bounce */) | 221 event.key.repeat == 0 /* Ignore key bounce */) |
182 { | 222 { |
200 " is taking place"; | 240 " is taking place"; |
201 } | 241 } |
202 break; | 242 break; |
203 | 243 |
204 case SDLK_s: | 244 case SDLK_s: |
205 scene_.FitContent(compositor.GetCanvasWidth(), | 245 scene_.FitContent(compositor_->GetCanvasWidth(), |
206 compositor.GetCanvasHeight()); | 246 compositor_->GetCanvasHeight()); |
207 break; | 247 break; |
208 | 248 |
209 case SDLK_c: | 249 case SDLK_c: |
210 TakeScreenshot( | 250 TakeScreenshot( |
211 "screenshot.png", | 251 "screenshot.png", |
212 compositor.GetCanvasWidth(), | 252 compositor_->GetCanvasWidth(), |
213 compositor.GetCanvasHeight()); | 253 compositor_->GetCanvasHeight()); |
214 break; | 254 break; |
215 | 255 |
216 default: | 256 default: |
217 break; | 257 break; |
218 } | 258 } |
219 } | 259 } |
220 } | 260 } |
221 | 261 |
262 | |
263 void TrackerSampleApp::OnSceneTransformChanged(const Scene2D::SceneTransformChanged& message) | |
264 { | |
265 // do not try to call this too early! | |
266 if(compositor_.get() != NULL) | |
267 DisplayInfoText(); | |
268 } | |
269 | |
222 FlexiblePointerTrackerPtr TrackerSampleApp::CreateSuitableTracker( | 270 FlexiblePointerTrackerPtr TrackerSampleApp::CreateSuitableTracker( |
223 const SDL_Event & event, | 271 const SDL_Event & event, |
224 const PointerEvent & e, | 272 const PointerEvent & e) |
225 const OpenGLCompositor & compositor) | |
226 { | 273 { |
227 switch (event.button.button) | 274 switch (event.button.button) |
228 { | 275 { |
229 case SDL_BUTTON_MIDDLE: | 276 case SDL_BUTTON_MIDDLE: |
230 return CreateSimpleTrackerAdapter(PointerTrackerPtr( | 277 return CreateSimpleTrackerAdapter(PointerTrackerPtr( |
231 new PanSceneTracker(scene_, e))); | 278 new PanSceneTracker(scene_, e))); |
232 | 279 |
233 case SDL_BUTTON_RIGHT: | 280 case SDL_BUTTON_RIGHT: |
234 return CreateSimpleTrackerAdapter(PointerTrackerPtr( | 281 return CreateSimpleTrackerAdapter(PointerTrackerPtr( |
235 new ZoomSceneTracker(scene_, e, compositor.GetCanvasHeight()))); | 282 new ZoomSceneTracker(scene_, e, compositor_->GetCanvasHeight()))); |
236 | 283 |
237 case SDL_BUTTON_LEFT: | 284 case SDL_BUTTON_LEFT: |
238 { | 285 { |
239 //LOG(TRACE) << "CreateSuitableTracker: case SDL_BUTTON_LEFT:"; | 286 //LOG(TRACE) << "CreateSuitableTracker: case SDL_BUTTON_LEFT:"; |
240 // TODO: we need to iterate on the set of measuring tool and perform | 287 // TODO: we need to iterate on the set of measuring tool and perform |
262 case GuiTool_Pan: | 309 case GuiTool_Pan: |
263 return CreateSimpleTrackerAdapter(PointerTrackerPtr( | 310 return CreateSimpleTrackerAdapter(PointerTrackerPtr( |
264 new PanSceneTracker(scene_, e))); | 311 new PanSceneTracker(scene_, e))); |
265 case GuiTool_Zoom: | 312 case GuiTool_Zoom: |
266 return CreateSimpleTrackerAdapter(PointerTrackerPtr( | 313 return CreateSimpleTrackerAdapter(PointerTrackerPtr( |
267 new ZoomSceneTracker(scene_, e, compositor.GetCanvasHeight()))); | 314 new ZoomSceneTracker(scene_, e, compositor_->GetCanvasHeight()))); |
268 //case GuiTool_AngleMeasure: | 315 //case GuiTool_AngleMeasure: |
269 // return new AngleMeasureTracker(scene_, measureTools_, undoStack_, e); | 316 // return new AngleMeasureTracker(scene_, measureTools_, undoStack_, e); |
270 //case GuiTool_CircleMeasure: | 317 //case GuiTool_CircleMeasure: |
271 // return new CircleMeasureTracker(scene_, measureTools_, undoStack_, e); | 318 // return new CircleMeasureTracker(scene_, measureTools_, undoStack_, e); |
272 //case GuiTool_EllipseMeasure: | 319 //case GuiTool_EllipseMeasure: |
395 | 442 |
396 void TrackerSampleApp::TakeScreenshot(const std::string& target, | 443 void TrackerSampleApp::TakeScreenshot(const std::string& target, |
397 unsigned int canvasWidth, | 444 unsigned int canvasWidth, |
398 unsigned int canvasHeight) | 445 unsigned int canvasHeight) |
399 { | 446 { |
400 // Take a screenshot, then save it as PNG file | |
401 CairoCompositor compositor(scene_, canvasWidth, canvasHeight); | 447 CairoCompositor compositor(scene_, canvasWidth, canvasHeight); |
402 compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1); | 448 compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, Orthanc::Encoding_Latin1); |
403 compositor.Refresh(); | 449 compositor.Refresh(); |
404 | 450 |
405 Orthanc::ImageAccessor canvas; | 451 Orthanc::ImageAccessor canvas; |
406 compositor.GetCanvas().GetReadOnlyAccessor(canvas); | 452 compositor.GetCanvas().GetReadOnlyAccessor(canvas); |
407 | 453 |
417 { | 463 { |
418 // std::vector<MeasureToolPtr> measureTools_; | 464 // std::vector<MeasureToolPtr> measureTools_; |
419 return nullptr; | 465 return nullptr; |
420 } | 466 } |
421 | 467 |
468 static void GLAPIENTRY | |
469 OpenGLMessageCallback(GLenum source, | |
470 GLenum type, | |
471 GLuint id, | |
472 GLenum severity, | |
473 GLsizei length, | |
474 const GLchar* message, | |
475 const void* userParam) | |
476 { | |
477 if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) | |
478 { | |
479 fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", | |
480 (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), | |
481 type, severity, message); | |
482 } | |
483 } | |
484 | |
485 static bool g_stopApplication = false; | |
486 | |
487 void TrackerSampleApp::Run() | |
488 { | |
489 // False means we do NOT let Windows treat this as a legacy application | |
490 // that needs to be scaled | |
491 SdlOpenGLWindow window("Hello", 1024, 1024, false); | |
492 | |
493 GetScene().FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); | |
494 | |
495 glEnable(GL_DEBUG_OUTPUT); | |
496 glDebugMessageCallback(OpenGLMessageCallback, 0); | |
497 | |
498 compositor_.reset(new OpenGLCompositor(window, GetScene())); | |
499 | |
500 compositor_->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, | |
501 FONT_SIZE_0, Orthanc::Encoding_Latin1); | |
502 compositor_->SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, | |
503 FONT_SIZE_1, Orthanc::Encoding_Latin1); | |
504 | |
505 while (!g_stopApplication) | |
506 { | |
507 compositor_->Refresh(); | |
508 | |
509 SDL_Event event; | |
510 while (!g_stopApplication && SDL_PollEvent(&event)) | |
511 { | |
512 if (event.type == SDL_QUIT) | |
513 { | |
514 g_stopApplication = true; | |
515 break; | |
516 } | |
517 else if (event.type == SDL_WINDOWEVENT && | |
518 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) | |
519 { | |
520 DisableTracker(); // was: tracker.reset(NULL); | |
521 compositor_->UpdateSize(); | |
522 } | |
523 else if (event.type == SDL_KEYDOWN && | |
524 event.key.repeat == 0 /* Ignore key bounce */) | |
525 { | |
526 switch (event.key.keysym.sym) | |
527 { | |
528 case SDLK_f: | |
529 window.GetWindow().ToggleMaximize(); | |
530 break; | |
531 | |
532 case SDLK_q: | |
533 g_stopApplication = true; | |
534 break; | |
535 default: | |
536 break; | |
537 } | |
538 } | |
539 HandleApplicationEvent(event); | |
540 } | |
541 SDL_Delay(1); | |
542 } | |
543 compositor_.reset(NULL); | |
544 } | |
545 | |
422 | 546 |
423 | 547 |
424 } | 548 } |