iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
IGraphicsWeb.cpp
1/*
2 ==============================================================================
3
4 This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5
6 See LICENSE.txt for more info.
7
8 ==============================================================================
9*/
10
11#include <cstring>
12#include <cstdio>
13#include <cstdint>
14
15#include "IGraphicsWeb.h"
16
17BEGIN_IPLUG_NAMESPACE
18BEGIN_IGRAPHICS_NAMESPACE
19
20void GetScreenDimensions(int& width, int& height)
21{
22 width = val::global("window")["innerWidth"].as<int>();
23 height = val::global("window")["innerHeight"].as<int>();
24}
25
26END_IPLUG_NAMESPACE
27END_IGRAPHICS_NAMESPACE
28
29using namespace iplug;
30using namespace igraphics;
31using namespace emscripten;
32
33extern IGraphicsWeb* gGraphics;
34double gPrevMouseDownTime = 0.;
35bool gFirstClick = false;
36
37#pragma mark - Private Classes and Structs
38
39// Fonts
40
41class IGraphicsWeb::Font : public PlatformFont
42{
43public:
44 Font(const char* fontName, const char* fontStyle)
45 : PlatformFont(true), mDescriptor{fontName, fontStyle}
46 {}
47
48 FontDescriptor GetDescriptor() override { return &mDescriptor; }
49
50private:
51 std::pair<WDL_String, WDL_String> mDescriptor;
52};
53
54class IGraphicsWeb::FileFont : public Font
55{
56public:
57 FileFont(const char* fontName, const char* fontStyle, const char* fontPath)
58 : Font(fontName, fontStyle), mPath(fontPath)
59 {
60 mSystem = false;
61 }
62
63 IFontDataPtr GetFontData() override;
64
65private:
66 WDL_String mPath;
67};
68
69IFontDataPtr IGraphicsWeb::FileFont::GetFontData()
70{
71 IFontDataPtr fontData(new IFontData());
72 FILE* fp = fopen(mPath.Get(), "rb");
73
74 // Read in the font data.
75 if (!fp)
76 return fontData;
77
78 fseek(fp,0,SEEK_END);
79 fontData = std::make_unique<IFontData>((int) ftell(fp));
80
81 if (!fontData->GetSize())
82 return fontData;
83
84 fseek(fp,0,SEEK_SET);
85 size_t readSize = fread(fontData->Get(), 1, fontData->GetSize(), fp);
86 fclose(fp);
87
88 if (readSize && readSize == fontData->GetSize())
89 fontData->SetFaceIdx(0);
90
91 return fontData;
92}
93
94class IGraphicsWeb::MemoryFont : public Font
95{
96public:
97 MemoryFont(const char* fontName, const char* fontStyle, const void* pData, int dataSize)
98 : Font(fontName, fontStyle)
99 {
100 mSystem = false;
101 mData.Set((const uint8_t*)pData, dataSize);
102 }
103
104 IFontDataPtr GetFontData() override
105 {
106 return IFontDataPtr(new IFontData(mData.Get(), mData.GetSize(), 0));
107 }
108
109private:
110 WDL_TypedBuf<uint8_t> mData;
111};
112
113#pragma mark - Utilities and Callbacks
114
115static EM_BOOL key_callback(int eventType, const EmscriptenKeyboardEvent* pEvent, void* pUserData)
116{
117 IGraphicsWeb* pGraphicsWeb = (IGraphicsWeb*) pUserData;
118
119 int VK = DOMKeyToVirtualKey(pEvent->keyCode);
120 WDL_String keyUTF8;
121
122 // filter utf8 for non ascii keys
123 if ((VK >= kVK_0 && VK <= kVK_Z) || VK == kVK_NONE)
124 keyUTF8.Set(pEvent->key);
125 else
126 keyUTF8.Set("");
127
128 IKeyPress keyPress {keyUTF8.Get(),
129 DOMKeyToVirtualKey(pEvent->keyCode),
130 static_cast<bool>(pEvent->shiftKey),
131 static_cast<bool>(pEvent->ctrlKey || pEvent->metaKey),
132 static_cast<bool>(pEvent->altKey)};
133
134 switch (eventType)
135 {
136 case EMSCRIPTEN_EVENT_KEYDOWN:
137 {
138 return pGraphicsWeb->OnKeyDown(pGraphicsWeb->mPrevX, pGraphicsWeb->mPrevY, keyPress);
139 }
140 case EMSCRIPTEN_EVENT_KEYUP:
141 {
142 return pGraphicsWeb->OnKeyUp(pGraphicsWeb->mPrevX, pGraphicsWeb->mPrevY, keyPress);
143 }
144 default:
145 break;
146 }
147
148 return 0;
149}
150
151static EM_BOOL outside_mouse_callback(int eventType, const EmscriptenMouseEvent* pEvent, void* pUserData)
152{
153 IGraphicsWeb* pGraphics = (IGraphicsWeb*) pUserData;
154
155 IMouseInfo info;
156 val rect = GetCanvas().call<val>("getBoundingClientRect");
157 info.x = (pEvent->targetX - rect["left"].as<double>()) / pGraphics->GetDrawScale();
158 info.y = (pEvent->targetY - rect["top"].as<double>()) / pGraphics->GetDrawScale();
159 info.dX = pEvent->movementX;
160 info.dY = pEvent->movementY;
161 info.ms = {(pEvent->buttons & 1) != 0, (pEvent->buttons & 2) != 0, static_cast<bool>(pEvent->shiftKey), static_cast<bool>(pEvent->ctrlKey), static_cast<bool>(pEvent->altKey)};
162 std::vector<IMouseInfo> list {info};
163
164 switch (eventType)
165 {
166 case EMSCRIPTEN_EVENT_MOUSEUP:
167 {
168 // Get button states based on what caused the mouse up (nothing in buttons)
169 list[0].ms.L = pEvent->button == 0;
170 list[0].ms.R = pEvent->button == 2;
171 pGraphics->OnMouseUp(list);
172 emscripten_set_mousemove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, pGraphics, 1, nullptr);
173 emscripten_set_mouseup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, pGraphics, 1, nullptr);
174 break;
175 }
176 case EMSCRIPTEN_EVENT_MOUSEMOVE:
177 {
178 if(pEvent->buttons != 0 && !pGraphics->IsInPlatformTextEntry())
179 pGraphics->OnMouseDrag(list);
180 break;
181 }
182 default:
183 break;
184 }
185
186 pGraphics->mPrevX = info.x;
187 pGraphics->mPrevY = info.y;
188
189 return true;
190}
191
192static EM_BOOL mouse_callback(int eventType, const EmscriptenMouseEvent* pEvent, void* pUserData)
193{
194 IGraphicsWeb* pGraphics = (IGraphicsWeb*) pUserData;
195
196 IMouseInfo info;
197 info.x = pEvent->targetX / pGraphics->GetDrawScale();
198 info.y = pEvent->targetY / pGraphics->GetDrawScale();
199 info.dX = pEvent->movementX;
200 info.dY = pEvent->movementY;
201 info.ms = {(pEvent->buttons & 1) != 0,
202 (pEvent->buttons & 2) != 0,
203 static_cast<bool>(pEvent->shiftKey),
204 static_cast<bool>(pEvent->ctrlKey),
205 static_cast<bool>(pEvent->altKey)};
206
207 std::vector<IMouseInfo> list {info};
208 switch (eventType)
209 {
210 case EMSCRIPTEN_EVENT_MOUSEDOWN:
211 {
212 const double timestamp = GetTimestamp();
213 const double timeDiff = timestamp - gPrevMouseDownTime;
214
215 if (gFirstClick && timeDiff < 0.3)
216 {
217 gFirstClick = false;
218 pGraphics->OnMouseDblClick(info.x, info.y, info.ms);
219 }
220 else
221 {
222 gFirstClick = true;
223 pGraphics->OnMouseDown(list);
224 }
225
226 gPrevMouseDownTime = timestamp;
227
228 break;
229 }
230 case EMSCRIPTEN_EVENT_MOUSEUP:
231 {
232 // Get button states based on what caused the mouse up (nothing in buttons)
233 list[0].ms.L = pEvent->button == 0;
234 list[0].ms.R = pEvent->button == 2;
235 pGraphics->OnMouseUp(list);
236 break;
237 }
238 case EMSCRIPTEN_EVENT_MOUSEMOVE:
239 {
240 gFirstClick = false;
241
242 if(pEvent->buttons == 0)
243 pGraphics->OnMouseOver(info.x, info.y, info.ms);
244 else
245 {
246 if(!pGraphics->IsInPlatformTextEntry())
247 pGraphics->OnMouseDrag(list);
248 }
249 break;
250 }
251 case EMSCRIPTEN_EVENT_MOUSEENTER:
252 pGraphics->OnSetCursor();
253 pGraphics->OnMouseOver(info.x, info.y, info.ms);
254 emscripten_set_mousemove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, pGraphics, 1, nullptr);
255 break;
256 case EMSCRIPTEN_EVENT_MOUSELEAVE:
257 if(pEvent->buttons != 0)
258 {
259 emscripten_set_mousemove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, pGraphics, 1, outside_mouse_callback);
260 emscripten_set_mouseup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, pGraphics, 1, outside_mouse_callback);
261 }
262 pGraphics->OnMouseOut(); break;
263 default:
264 break;
265 }
266
267 pGraphics->mPrevX = info.x;
268 pGraphics->mPrevY = info.y;
269
270 return true;
271}
272
273static EM_BOOL wheel_callback(int eventType, const EmscriptenWheelEvent* pEvent, void* pUserData)
274{
275 IGraphics* pGraphics = (IGraphics*) pUserData;
276
277 IMouseMod modifiers(false, false, pEvent->mouse.shiftKey, pEvent->mouse.ctrlKey, pEvent->mouse.altKey);
278
279 double x = pEvent->mouse.targetX;
280 double y = pEvent->mouse.targetY;
281
282 x /= pGraphics->GetDrawScale();
283 y /= pGraphics->GetDrawScale();
284
285 switch (eventType) {
286 case EMSCRIPTEN_EVENT_WHEEL: pGraphics->OnMouseWheel(x, y, modifiers, pEvent->deltaY);
287 default:
288 break;
289 }
290
291 return true;
292}
293
294EM_BOOL touch_callback(int eventType, const EmscriptenTouchEvent* pEvent, void* pUserData)
295{
296 IGraphics* pGraphics = (IGraphics*) pUserData;
297 const float drawScale = pGraphics->GetDrawScale();
298
299 std::vector<IMouseInfo> points;
300
301 static EmscriptenTouchPoint previousTouches[32];
302
303 for (auto i = 0; i < pEvent->numTouches; i++)
304 {
305 IMouseInfo info;
306 info.x = pEvent->touches[i].targetX / drawScale;
307 info.y = pEvent->touches[i].targetY / drawScale;
308 info.dX = info.x - (previousTouches[i].targetX / drawScale);
309 info.dY = info.y - (previousTouches[i].targetY / drawScale);
310 info.ms = {true,
311 false,
312 static_cast<bool>(pEvent->shiftKey),
313 static_cast<bool>(pEvent->ctrlKey),
314 static_cast<bool>(pEvent->altKey),
315 static_cast<ITouchID>(pEvent->touches[i].identifier)
316 };
317
318 if(pEvent->touches[i].isChanged)
319 points.push_back(info);
320 }
321
322 memcpy(previousTouches, pEvent->touches, sizeof(previousTouches));
323
324 switch (eventType)
325 {
326 case EMSCRIPTEN_EVENT_TOUCHSTART:
327 pGraphics->OnMouseDown(points);
328 return true;
329 case EMSCRIPTEN_EVENT_TOUCHEND:
330 pGraphics->OnMouseUp(points);
331 return true;
332 case EMSCRIPTEN_EVENT_TOUCHMOVE:
333 pGraphics->OnMouseDrag(points);
334 return true;
335 case EMSCRIPTEN_EVENT_TOUCHCANCEL:
336 pGraphics->OnTouchCancelled(points);
337 return true;
338 default:
339 return false;
340 }
341}
342
343static EM_BOOL complete_text_entry(int eventType, const EmscriptenFocusEvent* focusEvent, void* pUserData)
344{
345 IGraphicsWeb* pGraphics = (IGraphicsWeb*) pUserData;
346
347 val input = val::global("document").call<val>("getElementById", std::string("textEntry"));
348 std::string str = input["value"].as<std::string>();
349 val::global("document")["body"].call<void>("removeChild", input);
350 pGraphics->SetControlValueAfterTextEdit(str.c_str());
351
352 return true;
353}
354
355static EM_BOOL text_entry_keydown(int eventType, const EmscriptenKeyboardEvent* pEvent, void* pUserData)
356{
357 IGraphicsWeb* pGraphicsWeb = (IGraphicsWeb*) pUserData;
358
359 IKeyPress keyPress {pEvent->key, DOMKeyToVirtualKey(pEvent->keyCode),
360 static_cast<bool>(pEvent->shiftKey),
361 static_cast<bool>(pEvent->ctrlKey),
362 static_cast<bool>(pEvent->altKey)};
363
364 if (keyPress.VK == kVK_RETURN || keyPress.VK == kVK_TAB)
365 return complete_text_entry(0, nullptr, pUserData);
366
367 return false;
368}
369
370static EM_BOOL uievent_callback(int eventType, const EmscriptenUiEvent* pEvent, void* pUserData)
371{
372 IGraphicsWeb* pGraphics = (IGraphicsWeb*) pUserData;
373
374 if (eventType == EMSCRIPTEN_EVENT_RESIZE)
375 {
376 pGraphics->GetDelegate()->OnParentWindowResize(pEvent->windowInnerWidth, pEvent->windowInnerHeight);
377
378 return true;
379 }
380
381 return false;
382}
383
384IColorPickerHandlerFunc gColorPickerHandlerFunc = nullptr;
385
386static void color_picker_callback(val e)
387{
388 if(gColorPickerHandlerFunc)
389 {
390 std::string colorStrHex = e["target"]["value"].as<std::string>();
391
392 if (colorStrHex[0] == '#')
393 colorStrHex = colorStrHex.erase(0, 1);
394
395 IColor result;
396 result.A = 255;
397 sscanf(colorStrHex.c_str(), "%02x%02x%02x", &result.R, &result.G, &result.B);
398
399 gColorPickerHandlerFunc(result);
400 }
401}
402
403static void file_dialog_callback(val e)
404{
405 // DBGMSG(e["files"].as<std::string>().c_str());
406}
407
408EMSCRIPTEN_BINDINGS(events) {
409 function("color_picker_callback", color_picker_callback);
410 function("file_dialog_callback", file_dialog_callback);
411}
412
413#pragma mark -
414
415IGraphicsWeb::IGraphicsWeb(IGEditorDelegate& dlg, int w, int h, int fps, float scale)
416: IGRAPHICS_DRAW_CLASS(dlg, w, h, fps, scale)
417{
418 val keys = val::global("Object").call<val>("keys", GetPreloadedImages());
419
420 DBGMSG("Preloaded %i images\n", keys["length"].as<int>());
421
422 emscripten_set_mousedown_callback("#canvas", this, 1, mouse_callback);
423 emscripten_set_mouseup_callback("#canvas", this, 1, mouse_callback);
424 emscripten_set_mousemove_callback("#canvas", this, 1, mouse_callback);
425 emscripten_set_mouseenter_callback("#canvas", this, 1, mouse_callback);
426 emscripten_set_mouseleave_callback("#canvas", this, 1, mouse_callback);
427 emscripten_set_wheel_callback("#canvas", this, 1, wheel_callback);
428 emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, this, 1, key_callback);
429 emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, this, 1, key_callback);
430 emscripten_set_touchstart_callback("#canvas", this, 1, touch_callback);
431 emscripten_set_touchend_callback("#canvas", this, 1, touch_callback);
432 emscripten_set_touchmove_callback("#canvas", this, 1, touch_callback);
433 emscripten_set_touchcancel_callback("#canvas", this, 1, touch_callback);
434 emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, this, 1, uievent_callback);
435}
436
437IGraphicsWeb::~IGraphicsWeb()
438{
439}
440
441void* IGraphicsWeb::OpenWindow(void* pHandle)
442{
443#ifdef IGRAPHICS_GL
444 EmscriptenWebGLContextAttributes attr;
445 emscripten_webgl_init_context_attributes(&attr);
446 attr.stencil = true;
447 attr.depth = true;
448// attr.explicitSwapControl = 1;
449
450 EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context("#canvas", &attr);
451 emscripten_webgl_make_context_current(ctx);
452#endif
453
454 OnViewInitialized(nullptr /* not used */);
455
456 SetScreenScale(std::ceil(std::max(emscripten_get_device_pixel_ratio(), 1.)));
457
458 GetDelegate()->LayoutUI(this);
459 GetDelegate()->OnUIOpen();
460
461 return nullptr;
462}
463
464void IGraphicsWeb::HideMouseCursor(bool hide, bool lock)
465{
466 if (mCursorHidden == hide)
467 return;
468
469 if (hide)
470 {
471#ifdef IGRAPHICS_WEB_POINTERLOCK
472 if (lock)
473 emscripten_request_pointerlock("#canvas", EM_FALSE);
474 else
475#endif
476 val::global("document")["body"]["style"].set("cursor", "none");
477
478 mCursorHidden = true;
479 mCursorLock = lock;
480 }
481 else
482 {
483#ifdef IGRAPHICS_WEB_POINTERLOCK
484 if (mCursorLock)
485 emscripten_exit_pointerlock();
486 else
487#endif
488 OnSetCursor();
489
490 mCursorHidden = false;
491 mCursorLock = false;
492 }
493}
494
495ECursor IGraphicsWeb::SetMouseCursor(ECursor cursorType)
496{
497 std::string cursor("pointer");
498
499 switch (cursorType)
500 {
501 case ECursor::ARROW: cursor = "default"; break;
502 case ECursor::IBEAM: cursor = "text"; break;
503 case ECursor::WAIT: cursor = "wait"; break;
504 case ECursor::CROSS: cursor = "crosshair"; break;
505 case ECursor::UPARROW: cursor = "n-resize"; break;
506 case ECursor::SIZENWSE: cursor = "nwse-resize"; break;
507 case ECursor::SIZENESW: cursor = "nesw-resize"; break;
508 case ECursor::SIZEWE: cursor = "ew-resize"; break;
509 case ECursor::SIZENS: cursor = "ns-resize"; break;
510 case ECursor::SIZEALL: cursor = "move"; break;
511 case ECursor::INO: cursor = "not-allowed"; break;
512 case ECursor::HAND: cursor = "pointer"; break;
513 case ECursor::APPSTARTING: cursor = "progress"; break;
514 case ECursor::HELP: cursor = "help"; break;
515 }
516
517 val::global("document")["body"]["style"].set("cursor", cursor);
518 return IGraphics::SetMouseCursor(cursorType);
519}
520
521void IGraphicsWeb::GetMouseLocation(float& x, float&y) const
522{
523 x = mPrevX;
524 y = mPrevY;
525}
526
527//static
528void IGraphicsWeb::OnMainLoopTimer()
529{
530 IRECTList rects;
531 int screenScale = (int) std::ceil(std::max(emscripten_get_device_pixel_ratio(), 1.));
532
533 // Don't draw if there are no graphics or if assets are still loading
534 if (!gGraphics || !gGraphics->AssetsLoaded())
535 return;
536
537 if (screenScale != gGraphics->GetScreenScale())
538 {
539 gGraphics->SetScreenScale(screenScale);
540 }
541
542 if (gGraphics->IsDirty(rects))
543 {
544 gGraphics->SetAllControlsClean();
545 gGraphics->Draw(rects);
546 }
547}
548
549EMsgBoxResult IGraphicsWeb::ShowMessageBox(const char* str, const char* /*title*/, EMsgBoxType type, IMsgBoxCompletionHandlerFunc completionHandler)
550{
551 ReleaseMouseCapture();
552
553 EMsgBoxResult result = kNoResult;
554
555 switch (type)
556 {
557 case kMB_OK:
558 {
559 val::global("window").call<val>("alert", std::string(str));
560 result = EMsgBoxResult::kOK;
561 break;
562 }
563 case kMB_YESNO:
564 case kMB_OKCANCEL:
565 {
566 result = static_cast<EMsgBoxResult>(val::global("window").call<val>("confirm", std::string(str)).as<int>());
567 }
568 // case MB_CANCEL:
569 // break;
570 default:
571 return result = kNoResult;
572 }
573
574 if(completionHandler)
575 completionHandler(result);
576
577 return result;
578}
579
580void IGraphicsWeb::PromptForFile(WDL_String& filename, WDL_String& path, EFileAction action, const char* ext, IFileDialogCompletionHandlerFunc completionHandler)
581{
582 //TODO
583 // val inputEl = val::global("document").call<val>("createElement", std::string("input"));
584
585 // inputEl.call<void>("setAttribute", std::string("type"), std::string("file"));
586 // inputEl.call<void>("setAttribute", std::string("accept"), std::string(ext));
587 // inputEl.call<void>("click");
588 // inputEl.call<void>("addEventListener", std::string("input"), val::module_property("file_dialog_callback"), false);
589 // inputEl.call<void>("addEventListener", std::string("onChange"), val::module_property("file_dialog_callback"), false);
590}
591
592void IGraphicsWeb::PromptForDirectory(WDL_String& path, IFileDialogCompletionHandlerFunc completionHandler)
593{
594 //TODO
595 // val inputEl = val::global("document").call<val>("createElement", std::string("input"));
596
597 // inputEl.call<void>("setAttribute", std::string("type"), std::string("file"));
598 // inputEl.call<void>("setAttribute", std::string("directory"), true);
599 // inputEl.call<void>("setAttribute", std::string("webkitdirectory"), true);
600 // inputEl.call<void>("click");
601 // inputEl.call<void>("addEventListener", std::string("input"), val::module_property("file_dialog_callback"), false);
602 // inputEl.call<void>("addEventListener", std::string("onChange"), val::module_property("file_dialog_callback"), false);
603}
604
605bool IGraphicsWeb::PromptForColor(IColor& color, const char* str, IColorPickerHandlerFunc func)
606{
607 ReleaseMouseCapture();
608
609 gColorPickerHandlerFunc = func;
610
611 val inputEl = val::global("document").call<val>("createElement", std::string("input"));
612 inputEl.call<void>("setAttribute", std::string("type"), std::string("color"));
613 WDL_String colorStr;
614 colorStr.SetFormatted(64, "#%02x%02x%02x", color.R, color.G, color.B);
615 inputEl.call<void>("setAttribute", std::string("value"), std::string(colorStr.Get()));
616 inputEl.call<void>("click");
617 inputEl.call<void>("addEventListener", std::string("input"), val::module_property("color_picker_callback"), false);
618 inputEl.call<void>("addEventListener", std::string("onChange"), val::module_property("color_picker_callback"), false);
619
620 return false;
621}
622
623void IGraphicsWeb::CreatePlatformTextEntry(int paramIdx, const IText& text, const IRECT& bounds, int length, const char* str)
624{
625 val input = val::global("document").call<val>("createElement", std::string("input"));
626 val rect = GetCanvas().call<val>("getBoundingClientRect");
627
628 auto setDim = [&input](const char *dimName, double pixels)
629 {
630 WDL_String dimstr;
631 dimstr.SetFormatted(32, "%fpx", pixels);
632 input["style"].set(dimName, std::string(dimstr.Get()));
633 };
634
635 auto setColor = [&input](const char *colorName, IColor color)
636 {
637 WDL_String str;
638 str.SetFormatted(64, "rgba(%d, %d, %d, %d)", color.R, color.G, color.B, color.A);
639 input["style"].set(colorName, std::string(str.Get()));
640 };
641
642 input.set("id", std::string("textEntry"));
643 input["style"].set("position", val("fixed"));
644 setDim("left", rect["left"].as<double>() + bounds.L);
645 setDim("top", rect["top"].as<double>() + bounds.T);
646 setDim("width", bounds.W());
647 setDim("height", bounds.H());
648
649 setColor("color", text.mTextEntryFGColor);
650 setColor("background-color", text.mTextEntryBGColor);
651 if (paramIdx > kNoParameter)
652 {
653 const IParam* pParam = GetDelegate()->GetParam(paramIdx);
654
655 switch (pParam->Type())
656 {
657 case IParam::kTypeEnum:
658 case IParam::kTypeInt:
659 case IParam::kTypeBool:
660 input.set("type", val("number")); // TODO
661 break;
662 case IParam::kTypeDouble:
663 input.set("type", val("number"));
664 break;
665 default:
666 break;
667 }
668 }
669 else
670 {
671 input.set("type", val("text"));
672 }
673
674 val::global("document")["body"].call<void>("appendChild", input);
675 input.call<void>("focus");
676 emscripten_set_focusout_callback("textEntry", this, 1, complete_text_entry);
677 emscripten_set_keydown_callback("textEntry", this, 1, text_entry_keydown);
678}
679
680IPopupMenu* IGraphicsWeb::CreatePlatformPopupMenu(IPopupMenu& menu, const IRECT bounds, bool& isAsync)
681{
682 return nullptr;
683}
684
685bool IGraphicsWeb::OpenURL(const char* url, const char* msgWindowTitle, const char* confirmMsg, const char* errMsgOnFailure)
686{
687 val::global("window").call<val>("open", std::string(url), std::string("_blank"));
688
689 return true;
690}
691
692void IGraphicsWeb::DrawResize()
693{
694 val canvas = GetCanvas();
695
696 canvas["style"].set("width", val(Width() * GetDrawScale()));
697 canvas["style"].set("height", val(Height() * GetDrawScale()));
698
699 canvas.set("width", Width() * GetBackingPixelScale());
700 canvas.set("height", Height() * GetBackingPixelScale());
701
702 IGRAPHICS_DRAW_CLASS::DrawResize();
703}
704
705PlatformFontPtr IGraphicsWeb::LoadPlatformFont(const char* fontID, const char* fileNameOrResID)
706{
707 WDL_String fullPath;
708 const EResourceLocation fontLocation = LocateResource(fileNameOrResID, "ttf", fullPath, GetBundleID(), nullptr, nullptr);
709
710 if (fontLocation == kNotFound)
711 return nullptr;
712
713 return PlatformFontPtr(new FileFont(fontID, "", fullPath.Get()));
714}
715
716PlatformFontPtr IGraphicsWeb::LoadPlatformFont(const char* fontID, const char* fontName, ETextStyle style)
717{
718 const char* styles[] = { "normal", "bold", "italic" };
719
720 return PlatformFontPtr(new Font(fontName, styles[static_cast<int>(style)]));
721}
722
723PlatformFontPtr IGraphicsWeb::LoadPlatformFont(const char* fontID, void* pData, int dataSize)
724{
725 return PlatformFontPtr(new MemoryFont(fontID, "", pData, dataSize));
726}
727
728#if defined IGRAPHICS_CANVAS
729#include "IGraphicsCanvas.cpp"
730#elif defined IGRAPHICS_NANOVG
731#include "IGraphicsNanoVG.cpp"
732
733#ifdef IGRAPHICS_FREETYPE
734#define FONS_USE_FREETYPE
735#endif
736
737#include "nanovg.c"
738#endif
EResourceLocation LocateResource(const char *fileNameOrResID, const char *type, WDL_String &result, const char *bundleID, void *pHInstance, const char *sharedResourcesSubPath)
Find the absolute path of a resource based on it's file name (e.g.
An editor delegate base class that uses IGraphics for the UI.
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
virtual ECursor SetMouseCursor(ECursor cursorType=ECursor::ARROW)
Sets the mouse cursor to one of ECursor (implementations should return the result of the base impleme...
Definition: IGraphics.h:828
void OnMouseDrag(const std::vector< IMouseInfo > &points)
Called when the platform class sends drag events.
Definition: IGraphics.cpp:1163
void OnMouseUp(const std::vector< IMouseInfo > &points)
Called when the platform class sends mouse up events.
Definition: IGraphics.cpp:1065
void OnTouchCancelled(const std::vector< IMouseInfo > &points)
Called when the platform class sends touch cancel events.
Definition: IGraphics.cpp:1106
void OnMouseDown(const std::vector< IMouseInfo > &points)
Called when the platform class sends mouse down events.
Definition: IGraphics.cpp:979
bool OnMouseWheel(float x, float y, const IMouseMod &mod, float delta)
Definition: IGraphics.cpp:1231
float GetDrawScale() const
Gets the graphics context scaling factor.
Definition: IGraphics.h:1106
IGraphics platform class for the web.
Definition: IGraphicsWeb.h:44
IPlug's parameter class.
EParamType Type() const
Get the parameter's type.
A class for setting the contents of a pop up menu.
Used to manage a list of rectangular areas and optimize them for drawing to the screen.
Used to group mouse coordinates with mouse modifier information.
int DOMKeyToVirtualKey(uint32_t domKeyCode)
Converts a DOM virtual key code to an iPlug2 virtual key code.
Used to manage color data, independent of draw class/platform.
Used for key press info, such as ASCII representation, virtual key (mapped to win32 codes) and modifi...
Definition: IPlugStructs.h:616
Used to manage mouse modifiers i.e.
Used to manage a rectangular area, independent of draw class/platform.
float W() const
float H() const
IText is used to manage font and text/text entry style for a piece of text on the UI,...