Mercurial > hg > orthanc-stone
annotate Platforms/Wasm/Defaults.cpp @ 287:2038d76bf13f am-2
interaction with HTML/JS
author | am@osimis.io |
---|---|
date | Thu, 30 Aug 2018 11:36:36 +0200 |
parents | 8a86695fcbc3 |
children | 8c8da145fefa |
rev | line source |
---|---|
222 | 1 #include "Defaults.h" |
2 | |
223 | 3 #include "WasmWebService.h" |
4 #include <Framework/dev.h> | |
5 #include "Framework/Widgets/TestCairoWidget.h" | |
6 #include <Framework/Viewport/WidgetViewport.h> | |
7 #include <Framework/Widgets/LayerWidget.h> | |
228 | 8 #include <algorithm> |
242 | 9 #include "Applications/Wasm/StartupParametersBuilder.h" |
287 | 10 #include "Platforms/Wasm/IStoneApplicationToWebApplicationAdapter.h" |
223 | 11 |
12 static unsigned int width_ = 0; | |
13 static unsigned int height_ = 0; | |
14 | |
15 /**********************************/ | |
16 | |
242 | 17 static std::unique_ptr<OrthancStone::IBasicApplication> application; |
287 | 18 static OrthancStone::IStoneApplicationToWebApplicationAdapter* applicationWebAdapter = NULL; |
242 | 19 static std::unique_ptr<OrthancStone::BasicApplicationContext> context; |
20 static OrthancStone::StartupParametersBuilder startupParametersBuilder; | |
253 | 21 static OrthancStone::MessageBroker broker; |
242 | 22 |
278 | 23 static OrthancStone::ViewportContentChangedObserver viewportContentChangedObserver_; |
223 | 24 static OrthancStone::StatusBar statusBar_; |
25 | |
227 | 26 static std::list<std::shared_ptr<OrthancStone::WidgetViewport>> viewports_; |
27 | |
228 | 28 std::shared_ptr<OrthancStone::WidgetViewport> FindViewportSharedPtr(ViewportHandle viewport) { |
29 for (const auto& v : viewports_) { | |
30 if (v.get() == viewport) { | |
31 return v; | |
32 } | |
33 } | |
229 | 34 assert(false); |
35 return std::shared_ptr<OrthancStone::WidgetViewport>(); | |
228 | 36 } |
37 | |
223 | 38 #ifdef __cplusplus |
39 extern "C" { | |
40 #endif | |
41 | |
42 using namespace OrthancStone; | |
227 | 43 |
44 // when WASM needs a C++ viewport | |
45 ViewportHandle EMSCRIPTEN_KEEPALIVE CreateCppViewport() { | |
46 | |
47 std::shared_ptr<OrthancStone::WidgetViewport> viewport(new OrthancStone::WidgetViewport); | |
287 | 48 printf("viewport %x\n", (int)viewport.get()); |
227 | 49 |
50 viewports_.push_back(viewport); | |
51 | |
52 printf("There are now %d viewports in C++\n", viewports_.size()); | |
53 | |
54 viewport->SetStatusBar(statusBar_); | |
278 | 55 viewport->Register(viewportContentChangedObserver_); |
227 | 56 |
57 return viewport.get(); | |
58 } | |
59 | |
60 // when WASM does not need a viewport anymore, it should release it | |
61 void EMSCRIPTEN_KEEPALIVE ReleaseCppViewport(ViewportHandle viewport) { | |
62 viewports_.remove_if([viewport](const std::shared_ptr<OrthancStone::WidgetViewport>& v) { return v.get() == viewport;}); | |
63 | |
64 printf("There are now %d viewports in C++\n", viewports_.size()); | |
65 } | |
66 | |
67 void EMSCRIPTEN_KEEPALIVE CreateWasmApplication(ViewportHandle viewport) { | |
223 | 68 |
69 printf("CreateWasmApplication\n"); | |
70 | |
253 | 71 application.reset(CreateUserApplication(broker)); |
287 | 72 applicationWebAdapter = dynamic_cast<OrthancStone::IStoneApplicationToWebApplicationAdapter*>(application.get()); |
255 | 73 WasmWebService::SetBroker(broker); |
223 | 74 |
242 | 75 startupParametersBuilder.Clear(); |
223 | 76 } |
77 | |
78 void EMSCRIPTEN_KEEPALIVE SetStartupParameter(const char* keyc, | |
79 const char* value) { | |
242 | 80 startupParametersBuilder.SetStartupParameter(keyc, value); |
223 | 81 } |
82 | |
231
5027cb2feb51
viewport is now part of the Application itself and not global anymore
am@osimis.io
parents:
229
diff
changeset
|
83 void EMSCRIPTEN_KEEPALIVE StartWasmApplication() { |
223 | 84 |
85 printf("StartWasmApplication\n"); | |
86 | |
87 // recreate a command line from uri arguments and parse it | |
88 boost::program_options::variables_map parameters; | |
242 | 89 boost::program_options::options_description options; |
90 application->DeclareStartupOptions(options); | |
91 startupParametersBuilder.GetStartupParameters(parameters, options); | |
223 | 92 |
272 | 93 context.reset(new OrthancStone::BasicApplicationContext()); |
94 context->SetWebService(OrthancStone::WasmWebService::GetInstance()); | |
242 | 95 application->Initialize(context.get(), statusBar_, parameters); |
96 application->InitializeWasm(); | |
223 | 97 |
231
5027cb2feb51
viewport is now part of the Application itself and not global anymore
am@osimis.io
parents:
229
diff
changeset
|
98 // viewport->SetSize(width_, height_); |
223 | 99 printf("StartWasmApplication - completed\n"); |
100 } | |
101 | |
102 void EMSCRIPTEN_KEEPALIVE NotifyUpdateContent() | |
103 { | |
228 | 104 for (auto viewport : viewports_) { |
105 // TODO Only launch the JavaScript timer if "HasUpdateContent()" | |
106 if (viewport->HasUpdateContent()) | |
107 { | |
108 viewport->UpdateContent(); | |
109 } | |
110 | |
223 | 111 } |
112 | |
113 } | |
114 | |
115 | |
228 | 116 void EMSCRIPTEN_KEEPALIVE ViewportSetSize(ViewportHandle viewport, unsigned int width, unsigned int height) |
223 | 117 { |
118 width_ = width; | |
119 height_ = height; | |
120 | |
228 | 121 viewport->SetSize(width, height); |
223 | 122 } |
123 | |
228 | 124 int EMSCRIPTEN_KEEPALIVE ViewportRender(ViewportHandle viewport, |
227 | 125 unsigned int width, |
223 | 126 unsigned int height, |
127 uint8_t* data) | |
128 { | |
278 | 129 viewportContentChangedObserver_.Reset(); |
223 | 130 |
131 //printf("ViewportRender called %dx%d\n", width, height); | |
132 if (width == 0 || | |
133 height == 0) | |
134 { | |
135 return 1; | |
136 } | |
137 | |
138 Orthanc::ImageAccessor surface; | |
139 surface.AssignWritable(Orthanc::PixelFormat_BGRA32, width, height, 4 * width, data); | |
140 | |
227 | 141 viewport->Render(surface); |
223 | 142 |
143 // Convert from BGRA32 memory layout (only color mode supported by | |
144 // Cairo, which corresponds to CAIRO_FORMAT_ARGB32) to RGBA32 (as | |
145 // expected by HTML5 canvas). This simply amounts to swapping the | |
146 // B and R channels. | |
147 uint8_t* p = data; | |
148 for (unsigned int y = 0; y < height; y++) { | |
149 for (unsigned int x = 0; x < width; x++) { | |
150 uint8_t tmp = p[0]; | |
151 p[0] = p[2]; | |
152 p[2] = tmp; | |
153 | |
154 p += 4; | |
155 } | |
156 } | |
157 | |
158 return 1; | |
159 } | |
160 | |
161 | |
228 | 162 void EMSCRIPTEN_KEEPALIVE ViewportMouseDown(ViewportHandle viewport, |
163 unsigned int rawButton, | |
223 | 164 int x, |
165 int y, | |
166 unsigned int rawModifiers) | |
167 { | |
168 OrthancStone::MouseButton button; | |
169 switch (rawButton) | |
170 { | |
171 case 0: | |
172 button = OrthancStone::MouseButton_Left; | |
173 break; | |
174 | |
175 case 1: | |
176 button = OrthancStone::MouseButton_Middle; | |
177 break; | |
178 | |
179 case 2: | |
180 button = OrthancStone::MouseButton_Right; | |
181 break; | |
182 | |
183 default: | |
184 return; // Unknown button | |
185 } | |
186 | |
228 | 187 viewport->MouseDown(button, x, y, OrthancStone::KeyboardModifiers_None /* TODO */); |
223 | 188 } |
189 | |
190 | |
228 | 191 void EMSCRIPTEN_KEEPALIVE ViewportMouseWheel(ViewportHandle viewport, |
192 int deltaY, | |
223 | 193 int x, |
194 int y, | |
195 int isControl) | |
196 { | |
228 | 197 if (deltaY != 0) |
223 | 198 { |
199 OrthancStone::MouseWheelDirection direction = (deltaY < 0 ? | |
200 OrthancStone::MouseWheelDirection_Up : | |
201 OrthancStone::MouseWheelDirection_Down); | |
202 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; | |
203 | |
204 if (isControl != 0) | |
205 { | |
206 modifiers = OrthancStone::KeyboardModifiers_Control; | |
207 } | |
208 | |
228 | 209 viewport->MouseWheel(direction, x, y, modifiers); |
223 | 210 } |
211 } | |
212 | |
213 | |
228 | 214 void EMSCRIPTEN_KEEPALIVE ViewportMouseMove(ViewportHandle viewport, |
215 int x, | |
223 | 216 int y) |
217 { | |
228 | 218 viewport->MouseMove(x, y); |
223 | 219 } |
220 | |
228 | 221 void EMSCRIPTEN_KEEPALIVE ViewportKeyPressed(ViewportHandle viewport, |
222 const char* key, | |
223 | 223 bool isShiftPressed, |
224 bool isControlPressed, | |
225 bool isAltPressed) | |
226 | |
227 { | |
228 | 228 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; |
229 if (isShiftPressed) { | |
230 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Shift); | |
223 | 231 } |
228 | 232 if (isControlPressed) { |
233 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Control); | |
234 } | |
235 if (isAltPressed) { | |
236 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Alt); | |
237 } | |
238 printf("key pressed : %c\n", key[0]); | |
239 viewport->KeyPressed(key[0], modifiers); | |
223 | 240 } |
241 | |
242 | |
228 | 243 void EMSCRIPTEN_KEEPALIVE ViewportMouseUp(ViewportHandle viewport) |
223 | 244 { |
228 | 245 viewport->MouseUp(); |
223 | 246 } |
247 | |
248 | |
228 | 249 void EMSCRIPTEN_KEEPALIVE ViewportMouseEnter(ViewportHandle viewport) |
223 | 250 { |
228 | 251 viewport->MouseEnter(); |
223 | 252 } |
253 | |
254 | |
228 | 255 void EMSCRIPTEN_KEEPALIVE ViewportMouseLeave(ViewportHandle viewport) |
223 | 256 { |
228 | 257 viewport->MouseLeave(); |
223 | 258 } |
259 | |
287 | 260 const char* EMSCRIPTEN_KEEPALIVE SendMessageToStoneApplication(const char* message) |
261 { | |
262 static std::string output; // we don't want the string to be deallocated when we return to JS code so we always use the same string (this is fine since JS is single-thread) | |
263 | |
264 if (applicationWebAdapter != NULL) { | |
265 printf("sending message to C++"); | |
266 applicationWebAdapter->HandleMessageFromWeb(output, std::string(message)); | |
267 return output.c_str(); | |
268 } | |
269 return "This stone application does not have a Web Adapter"; | |
270 } | |
271 | |
223 | 272 |
273 #ifdef __cplusplus | |
274 } | |
275 #endif |