comparison Samples/WebAssembly/dev.h @ 826:2de01660debe

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 29 May 2019 16:48:56 +0200
parents
children 5cfb479fdbde 77c96ba899f9
comparison
equal deleted inserted replaced
825:9a6c7a5dcb76 826:2de01660debe
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2019 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
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/>.
19 **/
20
21
22 #pragma once
23
24 #include "../../Framework/OpenGL/WebAssemblyOpenGLContext.h"
25 #include "../../Framework/Scene2D/OpenGLCompositor.h"
26 #include "../../Framework/Scene2D/PanSceneTracker.h"
27 #include "../../Framework/Scene2D/RotateSceneTracker.h"
28 #include "../../Framework/Scene2D/ZoomSceneTracker.h"
29 #include "../../Framework/Scene2DViewport/ViewportController.h"
30
31 #include <Core/OrthancException.h>
32
33 #include <emscripten/html5.h>
34
35 static const unsigned int FONT_SIZE = 32;
36
37 namespace OrthancStone
38 {
39 class WebAssemblyViewport : public boost::noncopyable
40 {
41 private:
42 // the construction order is important because compositor_
43 // will hold a reference to the scene that belong to the
44 // controller_ object
45 OpenGL::WebAssemblyOpenGLContext context_;
46 boost::shared_ptr<ViewportController> controller_;
47 OpenGLCompositor compositor_;
48
49 void SetupEvents(const std::string& canvas);
50
51 public:
52 WebAssemblyViewport(MessageBroker& broker,
53 const std::string& canvas) :
54 context_(canvas),
55 controller_(new ViewportController(broker)),
56 compositor_(context_, *controller_->GetScene())
57 {
58 compositor_.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT,
59 FONT_SIZE, Orthanc::Encoding_Latin1);
60 SetupEvents(canvas);
61 }
62
63 Scene2D& GetScene()
64 {
65 return *controller_->GetScene();
66 }
67
68 const boost::shared_ptr<ViewportController>& GetController()
69 {
70 return controller_;
71 }
72
73 void UpdateSize()
74 {
75 context_.UpdateSize();
76 compositor_.UpdateSize();
77 Refresh();
78 }
79
80 void Refresh()
81 {
82 compositor_.Refresh();
83 }
84
85 void FitContent()
86 {
87 GetScene().FitContent(context_.GetCanvasWidth(), context_.GetCanvasHeight());
88 }
89
90 const std::string& GetCanvasIdentifier() const
91 {
92 return context_.GetCanvasIdentifier();
93 }
94
95 ScenePoint2D GetPixelCenterCoordinates(int x, int y) const
96 {
97 return compositor_.GetPixelCenterCoordinates(x, y);
98 }
99
100 unsigned int GetCanvasWidth() const
101 {
102 return context_.GetCanvasWidth();
103 }
104
105 unsigned int GetCanvasHeight() const
106 {
107 return context_.GetCanvasHeight();
108 }
109 };
110
111 class ActiveTracker : public boost::noncopyable
112 {
113 private:
114 boost::shared_ptr<IFlexiblePointerTracker> tracker_;
115 std::string canvasIdentifier_;
116 bool insideCanvas_;
117
118 public:
119 ActiveTracker(const boost::shared_ptr<IFlexiblePointerTracker>& tracker,
120 const WebAssemblyViewport& viewport) :
121 tracker_(tracker),
122 canvasIdentifier_(viewport.GetCanvasIdentifier()),
123 insideCanvas_(true)
124 {
125 if (tracker_.get() == NULL)
126 {
127 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
128 }
129 }
130
131 bool IsAlive() const
132 {
133 return tracker_->IsAlive();
134 }
135
136 void PointerMove(const PointerEvent& event)
137 {
138 tracker_->PointerMove(event);
139 }
140
141 void PointerUp(const PointerEvent& event)
142 {
143 tracker_->PointerUp(event);
144 }
145 };
146 }
147
148 static OrthancStone::PointerEvent* ConvertMouseEvent(
149 const EmscriptenMouseEvent& source,
150 OrthancStone::WebAssemblyViewport& viewport)
151 {
152 std::auto_ptr<OrthancStone::PointerEvent> target(
153 new OrthancStone::PointerEvent);
154
155 target->AddPosition(viewport.GetPixelCenterCoordinates(
156 source.targetX, source.targetY));
157 target->SetAltModifier(source.altKey);
158 target->SetControlModifier(source.ctrlKey);
159 target->SetShiftModifier(source.shiftKey);
160
161 return target.release();
162 }
163
164 std::auto_ptr<OrthancStone::ActiveTracker> tracker_;
165
166 EM_BOOL OnMouseEvent(int eventType,
167 const EmscriptenMouseEvent *mouseEvent,
168 void *userData)
169 {
170 if (mouseEvent != NULL &&
171 userData != NULL)
172 {
173 OrthancStone::WebAssemblyViewport& viewport =
174 *reinterpret_cast<OrthancStone::WebAssemblyViewport*>(userData);
175
176 switch (eventType)
177 {
178 case EMSCRIPTEN_EVENT_CLICK:
179 {
180 static unsigned int count = 0;
181 char buf[64];
182 sprintf(buf, "click %d", count++);
183
184 std::auto_ptr<OrthancStone::TextSceneLayer> layer(new OrthancStone::TextSceneLayer);
185 layer->SetText(buf);
186 viewport.GetScene().SetLayer(100, layer.release());
187 viewport.Refresh();
188 break;
189 }
190
191 case EMSCRIPTEN_EVENT_MOUSEDOWN:
192 {
193 boost::shared_ptr<OrthancStone::IFlexiblePointerTracker> t;
194
195 {
196 std::auto_ptr<OrthancStone::PointerEvent> event(
197 ConvertMouseEvent(*mouseEvent, viewport));
198
199 switch (mouseEvent->button)
200 {
201 case 0: // Left button
202 emscripten_console_log("Creating RotateSceneTracker");
203 t.reset(new OrthancStone::RotateSceneTracker(
204 viewport.GetController(), *event));
205 break;
206
207 case 1: // Middle button
208 emscripten_console_log("Creating PanSceneTracker");
209 LOG(INFO) << "Creating PanSceneTracker" ;
210 t.reset(new OrthancStone::PanSceneTracker(
211 viewport.GetController(), *event));
212 break;
213
214 case 2: // Right button
215 emscripten_console_log("Creating ZoomSceneTracker");
216 t.reset(new OrthancStone::ZoomSceneTracker(
217 viewport.GetController(), *event, viewport.GetCanvasWidth()));
218 break;
219
220 default:
221 break;
222 }
223 }
224
225 if (t.get() != NULL)
226 {
227 tracker_.reset(
228 new OrthancStone::ActiveTracker(t, viewport));
229 viewport.Refresh();
230 }
231
232 break;
233 }
234
235 case EMSCRIPTEN_EVENT_MOUSEMOVE:
236 if (tracker_.get() != NULL)
237 {
238 std::auto_ptr<OrthancStone::PointerEvent> event(
239 ConvertMouseEvent(*mouseEvent, viewport));
240 tracker_->PointerMove(*event);
241 viewport.Refresh();
242 }
243 break;
244
245 case EMSCRIPTEN_EVENT_MOUSEUP:
246 if (tracker_.get() != NULL)
247 {
248 std::auto_ptr<OrthancStone::PointerEvent> event(
249 ConvertMouseEvent(*mouseEvent, viewport));
250 tracker_->PointerUp(*event);
251 viewport.Refresh();
252 if (!tracker_->IsAlive())
253 tracker_.reset();
254 }
255 break;
256
257 default:
258 break;
259 }
260 }
261
262 return true;
263 }
264
265
266 void OrthancStone::WebAssemblyViewport::SetupEvents(const std::string& canvas)
267 {
268 emscripten_set_mousedown_callback(canvas.c_str(), this, false, OnMouseEvent);
269 emscripten_set_mousemove_callback(canvas.c_str(), this, false, OnMouseEvent);
270 emscripten_set_mouseup_callback(canvas.c_str(), this, false, OnMouseEvent);
271 }