Mercurial > hg > orthanc-stone
comparison Samples/WebAssembly/BasicScene.cpp @ 830:171a486a0373
Merge
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Fri, 31 May 2019 09:12:05 +0200 |
parents | 2de01660debe |
children | 0aff28f15ea2 6073c980323a |
comparison
equal
deleted
inserted
replaced
829:3a984741686f | 830:171a486a0373 |
---|---|
17 * You should have received a copy of the GNU Affero General Public License | 17 * You should have received a copy of the GNU Affero General Public License |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 **/ | 19 **/ |
20 | 20 |
21 | 21 |
22 #include "dev.h" | |
22 | 23 |
23 #include <emscripten.h> | 24 #include <emscripten.h> |
24 #include <emscripten/html5.h> | 25 #include <emscripten/html5.h> |
25 | 26 |
26 // From Stone | 27 // From Stone |
27 #include "../../Applications/Sdl/SdlOpenGLWindow.h" | |
28 #include "../../Framework/Scene2D/CairoCompositor.h" | |
29 #include "../../Framework/Scene2D/ColorTextureSceneLayer.h" | 28 #include "../../Framework/Scene2D/ColorTextureSceneLayer.h" |
30 #include "../../Framework/Scene2D/OpenGLCompositor.h" | |
31 #include "../../Framework/Scene2D/PanSceneTracker.h" | |
32 #include "../../Framework/Scene2D/RotateSceneTracker.h" | |
33 #include "../../Framework/Scene2D/Scene2D.h" | |
34 #include "../../Framework/Scene2D/ZoomSceneTracker.h" | |
35 #include "../../Framework/Scene2DViewport/ViewportController.h" | |
36 #include "../../Framework/StoneInitialization.h" | 29 #include "../../Framework/StoneInitialization.h" |
37 #include "../../Framework/OpenGL/WebAssemblyOpenGLContext.h" | |
38 | 30 |
39 // From Orthanc framework | 31 // From Orthanc framework |
40 #include <Core/Images/Image.h> | 32 #include <Core/Images/Image.h> |
41 #include <Core/Logging.h> | 33 #include <Core/Logging.h> |
42 #include <Core/OrthancException.h> | 34 #include <Core/OrthancException.h> |
43 | 35 |
44 #include <boost/make_shared.hpp> | 36 void PrepareScene(OrthancStone::Scene2D& scene) |
45 | |
46 #include <stdio.h> | |
47 | |
48 static const unsigned int FONT_SIZE = 32; | |
49 | |
50 using boost::shared_ptr; | |
51 using boost::make_shared; | |
52 | |
53 void PrepareScene(OrthancStone::Scene2DPtr scene) | |
54 { | 37 { |
55 using namespace OrthancStone; | 38 using namespace OrthancStone; |
56 | 39 |
57 // Texture of 2x2 size | 40 // Texture of 2x2 size |
58 if (1) | 41 if (1) |
75 | 58 |
76 p[3] = 255; | 59 p[3] = 255; |
77 p[4] = 0; | 60 p[4] = 0; |
78 p[5] = 0; | 61 p[5] = 0; |
79 | 62 |
80 scene->SetLayer(12, new ColorTextureSceneLayer(i)); | 63 scene.SetLayer(12, new ColorTextureSceneLayer(i)); |
81 | 64 |
82 std::auto_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); | 65 std::auto_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); |
83 l->SetOrigin(-3, 2); | 66 l->SetOrigin(-3, 2); |
84 l->SetPixelSpacing(1.5, 1); | 67 l->SetPixelSpacing(1.5, 1); |
85 l->SetAngle(20.0 / 180.0 * M_PI); | 68 l->SetAngle(20.0 / 180.0 * M_PI); |
86 scene->SetLayer(14, l.release()); | 69 scene.SetLayer(14, l.release()); |
87 } | 70 } |
88 | 71 |
89 // Texture of 1x1 size | 72 // Texture of 1x1 size |
90 if (1) | 73 if (1) |
91 { | 74 { |
97 p[2] = 0; | 80 p[2] = 0; |
98 | 81 |
99 std::auto_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); | 82 std::auto_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); |
100 l->SetOrigin(-2, 1); | 83 l->SetOrigin(-2, 1); |
101 l->SetAngle(20.0 / 180.0 * M_PI); | 84 l->SetAngle(20.0 / 180.0 * M_PI); |
102 scene->SetLayer(13, l.release()); | 85 scene.SetLayer(13, l.release()); |
103 } | 86 } |
104 | 87 |
105 // Some lines | 88 // Some lines |
106 { | 89 { |
107 std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer); | 90 std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer); |
128 chain.push_back(ScenePoint2D(4, -4 + dy)); | 111 chain.push_back(ScenePoint2D(4, -4 + dy)); |
129 chain.push_back(ScenePoint2D(-4, -4 + 2.0 * dy)); | 112 chain.push_back(ScenePoint2D(-4, -4 + 2.0 * dy)); |
130 chain.push_back(ScenePoint2D(4, 2)); | 113 chain.push_back(ScenePoint2D(4, 2)); |
131 layer->AddChain(chain, false, 0, 0, 255); | 114 layer->AddChain(chain, false, 0, 0, 255); |
132 | 115 |
133 scene->SetLayer(50, layer.release()); | 116 scene.SetLayer(50, layer.release()); |
134 } | 117 } |
135 | 118 |
136 // Some text | 119 // Some text |
137 if (1) | 120 if (1) |
138 { | 121 { |
139 std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer); | 122 std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer); |
140 layer->SetText("Hello"); | 123 layer->SetText("Hello"); |
141 scene->SetLayer(100, layer.release()); | 124 scene.SetLayer(100, layer.release()); |
142 } | 125 } |
143 } | 126 } |
144 | 127 |
145 namespace OrthancStone | |
146 { | |
147 class WebAssemblyViewport : public boost::noncopyable | |
148 { | |
149 private: | |
150 // the construction order is important because compositor_ | |
151 // will hold a reference to the scene that belong to the | |
152 // controller_ object | |
153 OpenGL::WebAssemblyOpenGLContext context_; | |
154 ViewportControllerPtr controller_; | |
155 OpenGLCompositor compositor_; | |
156 | |
157 void SetupEvents(const std::string& canvas); | |
158 | |
159 public: | |
160 WebAssemblyViewport(MessageBroker& broker, const std::string& canvas) : | |
161 context_(canvas), | |
162 controller_(make_shared<ViewportController>(broker)), | |
163 compositor_(context_, *controller_->GetScene()) | |
164 { | |
165 compositor_.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, | |
166 FONT_SIZE, Orthanc::Encoding_Latin1); | |
167 SetupEvents(canvas); | |
168 } | |
169 | |
170 Scene2DPtr GetScene() | |
171 { | |
172 return controller_->GetScene(); | |
173 } | |
174 | |
175 ViewportControllerPtr GetController() | |
176 { | |
177 return controller_; | |
178 } | |
179 | |
180 void UpdateSize() | |
181 { | |
182 context_.UpdateSize(); | |
183 compositor_.UpdateSize(); | |
184 Refresh(); | |
185 } | |
186 | |
187 void Refresh() | |
188 { | |
189 compositor_.Refresh(); | |
190 } | |
191 | |
192 const std::string& GetCanvasIdentifier() const | |
193 { | |
194 return context_.GetCanvasIdentifier(); | |
195 } | |
196 | |
197 ScenePoint2D GetPixelCenterCoordinates(int x, int y) const | |
198 { | |
199 return compositor_.GetPixelCenterCoordinates(x, y); | |
200 } | |
201 | |
202 unsigned int GetCanvasWidth() const | |
203 { | |
204 return context_.GetCanvasWidth(); | |
205 } | |
206 | |
207 unsigned int GetCanvasHeight() const | |
208 { | |
209 return context_.GetCanvasHeight(); | |
210 } | |
211 }; | |
212 | |
213 class ActiveTracker : public boost::noncopyable | |
214 { | |
215 private: | |
216 OrthancStone::FlexiblePointerTrackerPtr tracker_; | |
217 std::string canvasIdentifier_; | |
218 bool insideCanvas_; | |
219 | |
220 public: | |
221 ActiveTracker(FlexiblePointerTrackerPtr tracker, | |
222 const WebAssemblyViewport& viewport) : | |
223 tracker_(tracker), | |
224 canvasIdentifier_(viewport.GetCanvasIdentifier()), | |
225 insideCanvas_(true) | |
226 { | |
227 if (tracker_.get() == NULL) | |
228 { | |
229 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
230 } | |
231 } | |
232 | |
233 bool IsAlive() const | |
234 { | |
235 return tracker_->IsAlive(); | |
236 } | |
237 | |
238 void PointerMove(const PointerEvent& event) | |
239 { | |
240 tracker_->PointerMove(event); | |
241 } | |
242 | |
243 void PointerUp(const PointerEvent& event) | |
244 { | |
245 tracker_->PointerUp(event); | |
246 } | |
247 }; | |
248 } | |
249 | |
250 static OrthancStone::PointerEvent* ConvertMouseEvent( | |
251 const EmscriptenMouseEvent& source, | |
252 OrthancStone::WebAssemblyViewport& viewport) | |
253 { | |
254 std::auto_ptr<OrthancStone::PointerEvent> target( | |
255 new OrthancStone::PointerEvent); | |
256 | |
257 target->AddPosition(viewport.GetPixelCenterCoordinates( | |
258 source.targetX, source.targetY)); | |
259 target->SetAltModifier(source.altKey); | |
260 target->SetControlModifier(source.ctrlKey); | |
261 target->SetShiftModifier(source.shiftKey); | |
262 | |
263 return target.release(); | |
264 } | |
265 | |
266 std::auto_ptr<OrthancStone::ActiveTracker> tracker_; | |
267 | |
268 EM_BOOL OnMouseEvent(int eventType, | |
269 const EmscriptenMouseEvent *mouseEvent, | |
270 void *userData) | |
271 { | |
272 if (mouseEvent != NULL && | |
273 userData != NULL) | |
274 { | |
275 OrthancStone::WebAssemblyViewport& viewport = | |
276 *reinterpret_cast<OrthancStone::WebAssemblyViewport*>(userData); | |
277 | |
278 switch (eventType) | |
279 { | |
280 case EMSCRIPTEN_EVENT_CLICK: | |
281 { | |
282 static unsigned int count = 0; | |
283 char buf[64]; | |
284 sprintf(buf, "click %d", count++); | |
285 | |
286 std::auto_ptr<OrthancStone::TextSceneLayer> layer(new OrthancStone::TextSceneLayer); | |
287 layer->SetText(buf); | |
288 viewport.GetScene()->SetLayer(100, layer.release()); | |
289 viewport.Refresh(); | |
290 break; | |
291 } | |
292 | |
293 case EMSCRIPTEN_EVENT_MOUSEDOWN: | |
294 { | |
295 OrthancStone::FlexiblePointerTrackerPtr t; | |
296 | |
297 { | |
298 std::auto_ptr<OrthancStone::PointerEvent> event( | |
299 ConvertMouseEvent(*mouseEvent, viewport)); | |
300 | |
301 switch (mouseEvent->button) | |
302 { | |
303 case 0: // Left button | |
304 emscripten_console_log("Creating RotateSceneTracker"); | |
305 t.reset(new OrthancStone::RotateSceneTracker( | |
306 viewport.GetController(), *event)); | |
307 break; | |
308 | |
309 case 1: // Middle button | |
310 emscripten_console_log("Creating PanSceneTracker"); | |
311 LOG(INFO) << "Creating PanSceneTracker" ; | |
312 t.reset(new OrthancStone::PanSceneTracker( | |
313 viewport.GetController(), *event)); | |
314 break; | |
315 | |
316 case 2: // Right button | |
317 emscripten_console_log("Creating ZoomSceneTracker"); | |
318 t.reset(new OrthancStone::ZoomSceneTracker( | |
319 viewport.GetController(), *event, viewport.GetCanvasWidth())); | |
320 break; | |
321 | |
322 default: | |
323 break; | |
324 } | |
325 } | |
326 | |
327 if (t.get() != NULL) | |
328 { | |
329 tracker_.reset( | |
330 new OrthancStone::ActiveTracker(t, viewport)); | |
331 viewport.Refresh(); | |
332 } | |
333 | |
334 break; | |
335 } | |
336 | |
337 case EMSCRIPTEN_EVENT_MOUSEMOVE: | |
338 if (tracker_.get() != NULL) | |
339 { | |
340 std::auto_ptr<OrthancStone::PointerEvent> event( | |
341 ConvertMouseEvent(*mouseEvent, viewport)); | |
342 tracker_->PointerMove(*event); | |
343 viewport.Refresh(); | |
344 } | |
345 break; | |
346 | |
347 case EMSCRIPTEN_EVENT_MOUSEUP: | |
348 if (tracker_.get() != NULL) | |
349 { | |
350 std::auto_ptr<OrthancStone::PointerEvent> event( | |
351 ConvertMouseEvent(*mouseEvent, viewport)); | |
352 tracker_->PointerUp(*event); | |
353 viewport.Refresh(); | |
354 if (!tracker_->IsAlive()) | |
355 tracker_.reset(); | |
356 } | |
357 break; | |
358 | |
359 default: | |
360 break; | |
361 } | |
362 } | |
363 | |
364 return true; | |
365 } | |
366 | |
367 | |
368 void OrthancStone::WebAssemblyViewport::SetupEvents(const std::string& canvas) | |
369 { | |
370 #if 0 | |
371 emscripten_set_click_callback(canvas.c_str(), this, false, OnMouseEvent); | |
372 #else | |
373 emscripten_set_mousedown_callback(canvas.c_str(), this, false, OnMouseEvent); | |
374 emscripten_set_mousemove_callback(canvas.c_str(), this, false, OnMouseEvent); | |
375 emscripten_set_mouseup_callback(canvas.c_str(), this, false, OnMouseEvent); | |
376 #endif | |
377 } | |
378 | 128 |
379 std::auto_ptr<OrthancStone::WebAssemblyViewport> viewport1_; | 129 std::auto_ptr<OrthancStone::WebAssemblyViewport> viewport1_; |
380 std::auto_ptr<OrthancStone::WebAssemblyViewport> viewport2_; | 130 std::auto_ptr<OrthancStone::WebAssemblyViewport> viewport2_; |
381 std::auto_ptr<OrthancStone::WebAssemblyViewport> viewport3_; | 131 std::auto_ptr<OrthancStone::WebAssemblyViewport> viewport3_; |
382 OrthancStone::MessageBroker broker_; | 132 OrthancStone::MessageBroker broker_; |