13 #define NANOSVG_IMPLEMENTATION 14 #pragma warning(disable:4244) // float conversion 18 #include "pluginterfaces/base/ustring.h" 20 using VST3_API_BASE = iplug::IPlugVST3;
21 #elif defined VST3C_API 22 #include "pluginterfaces/base/ustring.h" 24 #include "IPlugVST3_View.h" 25 using VST3_API_BASE = iplug::IPlugVST3Controller;
40 using namespace iplug;
41 using namespace igraphics;
43 static StaticStorage<APIBitmap> sBitmapCache;
44 static StaticStorage<SVGHolder> sSVGCache;
46 IGraphics::IGraphics(
IGEditorDelegate& dlg,
int w,
int h,
int fps,
float scale)
51 , mMinScale(scale / 2)
52 , mMaxScale(scale * 2)
55 StaticStorage<APIBitmap>::Accessor bitmapStorage(sBitmapCache);
56 bitmapStorage.Retain();
57 StaticStorage<SVGHolder>::Accessor svgStorage(sSVGCache);
61 IGraphics::~IGraphics()
63 #ifdef IGRAPHICS_IMGUI 64 mImGuiRenderer =
nullptr;
70 mCursorHidden =
false;
73 StaticStorage<APIBitmap>::Accessor bitmapStorage(sBitmapCache);
74 bitmapStorage.Release();
75 StaticStorage<SVGHolder>::Accessor svgStorage(sSVGCache);
82 int windowWidth = WindowWidth() * GetPlatformWindowScale();
83 int windowHeight = WindowHeight() * GetPlatformWindowScale();
85 PlatformResize(
GetDelegate()->EditorResizeFromUI(windowWidth, windowHeight,
true));
87 SetAllControlsDirty();
95 scale =
Clip(scale, mMinScale, mMaxScale);
97 if (w == Width() && h == Height() && scale == GetDrawScale())
return;
100 ReleaseMouseCapture();
107 mCornerResizer->OnRescale();
109 int windowWidth = WindowWidth() * GetPlatformWindowScale();
110 int windowHeight = WindowHeight() * GetPlatformWindowScale();
112 PlatformResize(
GetDelegate()->EditorResizeFromUI(windowWidth, windowHeight, needsPlatformResize));
114 SetAllControlsDirty();
121 void IGraphics::SetLayoutOnResize(
bool layoutOnResize)
123 mLayoutOnResize = layoutOnResize;
128 mControls.DeletePtr(GetControlWithTag(ctrlTag));
129 mCtrlTags.erase(ctrlTag);
130 SetAllControlsDirty();
135 int idx = NControls()-1;
136 while (idx >= fromIdx)
138 IControl* pControl = GetControl(idx);
140 if(ControlIsCaptured(pControl))
141 ReleaseMouseCapture();
143 if(pControl == mMouseOver)
146 if(pControl == mInTextEntry)
147 mInTextEntry =
nullptr;
149 if(pControl == mInPopupMenu)
150 mInPopupMenu =
nullptr;
152 if(pControl->
GetTag() > kNoTag)
153 mCtrlTags.erase(pControl->
GetTag());
155 mControls.Delete(idx--,
true);
158 SetAllControlsDirty();
163 RemoveControl(GetControl(idx));
168 if(ControlIsCaptured(pControl))
169 ReleaseMouseCapture();
171 if(pControl == mMouseOver)
174 if(pControl == mInTextEntry)
175 mInTextEntry =
nullptr;
177 if(pControl == mInPopupMenu)
178 mInPopupMenu =
nullptr;
180 if(pControl->
GetTag() > kNoTag)
181 mCtrlTags.erase(pControl->
GetTag());
183 mControls.DeletePtr(pControl,
true);
185 SetAllControlsDirty();
190 ReleaseMouseCapture();
193 mPopupControl =
nullptr;
194 mTextEntryControl =
nullptr;
195 mCornerResizer =
nullptr;
196 mPerfDisplay =
nullptr;
202 mBubbleControls.Empty(
true);
205 mControls.Empty(
true);
210 IControl* pControl = GetControl(idx);
213 SetAllControlsDirty();
218 IControl* pControl = GetControl(idx);
221 SetAllControlsDirty();
226 IControl* pControl = GetControl(idx);
229 SetAllControlsDirty();
237 const IParam* pParam = mTextEntryValIdx > kNoValIdx ? mInTextEntry->GetParam(mTextEntryValIdx) :
nullptr;
242 mInTextEntry->SetValueFromUserInput(pParam->
ToNormalized(v), mTextEntryValIdx);
246 mInTextEntry->OnTextEntryCompletion(str, mTextEntryValIdx);
249 mInTextEntry =
nullptr;
258 mInPopupMenu->OnContextSelection(pMenu ? pMenu->GetChosenItemIdx() : -1);
260 mInPopupMenu->OnPopupMenuSelection(!pMenu || pMenu->GetChosenItemIdx() == -1 ?
nullptr : pMenu, mPopupMenuValIdx);
262 int nVals = mInPopupMenu->NVals();
264 for (
int v = 0; v < nVals; v++)
266 int paramIdx = mInPopupMenu->GetParamIdx(v);
268 if (paramIdx > kNoParameter)
274 mInPopupMenu =
nullptr;
281 mControls.Insert(0, pBG);
288 mControls.Insert(0, pBG);
295 mControls.Insert(0, pBG);
302 auto result = mCtrlTags.insert(std::make_pair(ctrlTag, pControl));
303 assert(result.second &&
"AttachControl failed: ctrl tags must be unique");
311 mControls.Add(pControl);
319 AttachCornerResizer(
new ICornerResizerControl(GetBounds(), size, color, mouseOverColor, dragColor), sizeMode, layoutOnResize);
324 assert(!mCornerResizer);
326 std::unique_ptr<ICornerResizerControl> control(pControl);
330 mCornerResizer.swap(control);
331 mGUISizeMode = sizeMode;
332 mLayoutOnResize = layoutOnResize;
340 AttachBubbleControl(pControl);
346 mBubbleControls.Add(pControl);
353 mPopupControl = std::make_unique<IPopupMenuControl>(kNoParameter, text,
IRECT(), bounds);
360 mPopupControl =
nullptr;
365 if (!mTextEntryControl)
367 mTextEntryControl = std::make_unique<ITextEntryControl>();
374 mTextEntryControl =
nullptr;
377 void IGraphics::ShowBubbleControl(
IControl* pCaller,
float x,
float y,
const char* str, EDirection dir,
IRECT minimumContentBounds)
379 assert(mBubbleControls.GetSize() &&
"No bubble controls attached");
381 if(MultiTouchEnabled())
383 std::vector<ITouchID> touchIDsForCaller;
384 GetTouches(pCaller, touchIDsForCaller);
385 std::vector<IBubbleControl*> availableBubbleControls;
386 int nBubbleControls = mBubbleControls.GetSize();
388 if(touchIDsForCaller.size() == 1)
390 ITouchID touchID = touchIDsForCaller[0];
393 for(
int i=0;i<nBubbleControls;i++)
396 if(pBubbleControl->GetTouchID() == touchID)
398 pBubbleControl->ShowBubble(pCaller, x, y, str, dir, minimumContentBounds, touchID);
402 availableBubbleControls.push_back(pBubbleControl);
405 if(availableBubbleControls.size())
408 static int whichBubbleControl = 0;
409 availableBubbleControls[whichBubbleControl++]->ShowBubble(pCaller, x, y, str, dir, minimumContentBounds, touchID);
410 whichBubbleControl %= nBubbleControls;
419 mBubbleControls.Get(0)->ShowBubble(pCaller, x, y, str, dir, minimumContentBounds);
428 mPerfDisplay = std::make_unique<IFPSDisplayControl>(GetBounds().GetPadded(-10).GetFromTLHC(200, 50));
434 mPerfDisplay =
nullptr;
438 SetAllControlsDirty();
443 const auto it = mCtrlTags.find(ctrlTag);
445 if (it != mCtrlTags.end())
451 assert(
"There is no control attached with this tag");
468 for (
auto c = 0; c < NControls(); c++)
482 for (
auto c = 0; c < NControls(); c++)
486 if (CStringHasContents(pControl->
GetGroup()))
488 if (strcmp(pControl->
GetGroup(), group) == 0)
497 for (
auto c = 0; c < NControls(); c++)
503 ForStandardControlsFunc(func);
506 func(mPerfDisplay.get());
510 func(mLiveEdit.get());
514 func(mCornerResizer.get());
516 if (mTextEntryControl)
517 func(mTextEntryControl.get());
520 func(mPopupControl.get());
522 if (mBubbleControls.GetSize())
524 for(
int i = 0;i<mBubbleControls.GetSize();i++)
526 func(mBubbleControls.Get(i));
531 template<
typename T,
typename... Args>
534 ForAllControlsFunc([method, args...](
IControl* pControl) { (pControl->*method)(args...); });
537 template<
typename T,
typename... Args>
540 ForControlWithParam(paramIdx, [method, args...](
IControl* pControl) { (pControl->*method)(args...); });
550 ForAllControls(&IControl::SetClean);
557 if (pControl->GetParamIdx() > kNoParameter)
558 pControl->SetTooltip(pControl->GetParam()->GetName());
561 ForStandardControlsFunc(func);
566 double value = pCaller->
GetValue(callerValIdx);
569 auto func = [pCaller, paramIdx, value](
IControl* pControl)
571 int valIdx = pControl->LinkedToParam(paramIdx);
574 if ((valIdx > kNoValIdx) && (pControl != pCaller))
576 pControl->SetValueFromDelegate(value, valIdx);
580 ForStandardControlsFunc(func);
585 assert(valIdx > kNoValIdx);
593 WDL_String currentText;
595 if ( type == IParam::kTypeEnum || (type == IParam::kTypeBool && nDisplayTexts))
598 mPromptPopupMenu.Clear();
601 for (
int i = 0; i < nDisplayTexts; ++i)
605 if (!strcmp(str, currentText.Get()))
606 mPromptPopupMenu.AddItem(
new IPopupMenu::Item(str, IPopupMenu::Item::kChecked), -1 );
610 mPromptPopupMenu.SetRootTitle(pParam->
GetName());
613 CreatePopupMenu(control, mPromptPopupMenu, bounds, valIdx);
622 currentText.Append(
" ");
623 currentText.Append(pParam->
GetLabel());
626 CreateTextEntry(control, control.
GetText(), bounds, currentText.Get(), valIdx);
633 if (!str || str[0] ==
'\0')
636 DoDrawText(text, str, bounds, pBlend);
641 if (!str || str[0] ==
'\0')
644 return DoMeasureText(text, str, bounds);
649 IRECT bounds = { x, y, x, y };
650 DrawText(text, str, bounds, pBlend);
658 bmpState =
Clip(bmpState, 1, bitmap.
N());
660 if (bitmap.
N() > 1 && bmpState > 1)
664 srcX = bitmap.
W() * (bmpState - 1) / bitmap.
N();
668 srcY = bitmap.
H() * (bmpState - 1) / bitmap.
N();
672 return DrawBitmap(bitmap, bounds, srcX, srcY, pBlend);
677 if (CStringHasContents(str))
679 int stringLength = (int) strlen(str);
681 float basicYOffset = 0.;
682 float basicXOffset = 0.;
685 basicYOffset = bounds.
T + ((bounds.
H() - charHeight) / 2.f);
687 basicYOffset = bounds.
T;
689 if (text.mAlign == EAlign::Center)
690 basicXOffset = bounds.
L + ((bounds.
W() - (stringLength * charWidth)) / 2.f);
691 else if (text.mAlign == EAlign::Near)
692 basicXOffset = bounds.
L;
693 else if (text.mAlign == EAlign::Far)
694 basicXOffset = bounds.
R - (stringLength * charWidth);
696 int widthAsOneLine = charWidth * stringLength;
701 int nCharsThatFitIntoLine;
705 if (widthAsOneLine > bounds.
W())
707 nCharsThatFitIntoLine = int(bounds.
W() / (float)charWidth);
708 nLines = int(
float(widthAsOneLine) / bounds.
W()) + 1;
712 nCharsThatFitIntoLine = stringLength;
718 nCharsThatFitIntoLine = int(bounds.
W() / (float) charWidth);
722 for (
int line=0; line<nLines; line++)
724 float yOffset = basicYOffset + line * charHeight;
726 for (
int linepos=0; linepos<nCharsThatFitIntoLine; linepos++)
728 if (str[stridx] ==
'\0')
return;
730 int frameOffset = (int) str[stridx++] - 31;
732 float xOffset = ((float) linepos * ((
float) charWidth + (float) charOffset)) + basicXOffset;
733 IRECT charRect =
IRECT(xOffset, yOffset, xOffset + charWidth, yOffset + charHeight);
734 DrawBitmap(bitmap, charRect, frameOffset, pBlend);
742 x =
Clip(x, 0.0f, 1.0f);
743 float xi = bounds.
L + int(x * (bounds.
R - bounds.
L));
744 return DrawVerticalLine(color, xi, bounds.
T, bounds.
B, pBlend, thickness);
749 y =
Clip(y, 0.0f, 1.0f);
750 float yi = bounds.
B - (y * (float) (bounds.
B - bounds.
T));
751 return DrawHorizontalLine(color, yi, bounds.
L, bounds.
R, pBlend, thickness);
756 DrawLine(color, xi, yLo, xi, yHi, pBlend, thickness);
761 DrawLine(color, xLo, yi, xHi, yi, pBlend, thickness);
767 RadialPoints(angle, cx, cy, rMin, rMax, 2, data);
768 DrawLine(color, data[0][0], data[0][1], data[1][0], data[1][1], pBlend, thickness);
774 RadialPoints(angle, cx, cy, rMin, rMax, 2, data);
775 PathLine(data[0][0], data[0][1], data[1][0], data[1][1]);
780 if (mDisplayTickFunc)
783 ForAllControlsFunc([](
IControl* pControl) { pControl->Animate(); } );
787 auto func = [&dirty, &rects](
IControl* pControl) {
796 ForAllControlsFunc(func);
798 #ifdef USE_IDLE_CALLS 803 else if (++mIdleTicks > IDLE_TICKS)
810 #if defined IGRAPHICS_IMGUI 811 #if defined IGRAPHICS_GL || defined IGRAPHICS_SKIA && !defined IGRAPHICS_CPU 812 if (mImGuiRenderer && mImGuiRenderer->GetDrawFunc())
827 const double timestamp = GetTimestamp();
828 const double timeDiff = timestamp - mPrevTimestamp;
829 mPerfDisplay->Update((
float) timeDiff);
830 mPrevTimestamp = timestamp;
835 void IGraphics::DrawControl(
IControl* pControl,
const IRECT& bounds,
float scale)
837 if (pControl && (!pControl->
IsHidden() || pControl == GetControl(0)))
843 if (clipBounds.
W() <= 0.0 || clipBounds.
H() <= 0)
846 PrepareRegion(clipBounds);
847 pControl->
Draw(*
this);
853 if (mShowControlBounds)
855 PrepareRegion(clipBounds);
856 DrawRect(CONTROL_BOUNDS_COLOR, pControl->
GetRECT());
860 CompleteRegion(clipBounds);
866 ForAllControlsFunc([
this, bounds, scale](
IControl* pControl) { DrawControl(pControl, bounds, scale); });
871 PrepareRegion(bounds);
875 CompleteRegion(bounds);
885 float scale = GetBackingPixelScale();
900 for (
auto i = 0; i < rects.
Size(); i++)
910 SetAllControlsDirty();
917 bool singlePoint = points.size() == 1;
919 #ifdef IGRAPHICS_IMGUI 920 if(mImGuiRenderer && singlePoint)
922 IControl* pControl = GetMouseControl(points[0].x, points[0].y,
true);
924 bool cornerResizer =
false;
925 if(mCornerResizer.get() !=
nullptr)
926 cornerResizer = pControl == mCornerResizer.get();
928 if(!cornerResizer && mImGuiRenderer->OnMouseDown(points[0].x, points[0].y, points[0].ms))
930 ReleaseMouseCapture();
938 mMouseDownX = points[0].x;
939 mMouseDownY = points[0].y;
942 for (
auto& point : points)
948 IControl* pCapturedControl = GetMouseControl(x, y,
true,
false, mod.touchID);
950 if (pCapturedControl)
952 int nVals = pCapturedControl->
NVals();
954 int paramIdx = pCapturedControl->
GetParamIdx((valIdx > kNoValIdx) ? valIdx : 0);
957 if (mAAXViewContainer && paramIdx > kNoParameter)
959 auto GetAAXModifiersFromIMouseMod = [](
const IMouseMod& mod) {
960 uint32_t modifiers = 0;
962 if (mod.A) modifiers |= AAX_eModifiers_Option;
965 if (mod.C) modifiers |= AAX_eModifiers_Command;
967 if (mod.C) modifiers |= AAX_eModifiers_Control;
968 if (mod.R) modifiers |= AAX_eModifiers_Command;
970 if (mod.S) modifiers |= AAX_eModifiers_Shift;
971 if (mod.R) modifiers |= AAX_eModifiers_SecondaryButton;
976 uint32_t aaxModifiersForPT = GetAAXModifiersFromIMouseMod(mod);
979 uint32_t aaxModifiersFromPT = 0;
980 mAAXViewContainer->GetModifiers(&aaxModifiersFromPT);
981 aaxModifiersForPT |= aaxModifiersFromPT;
984 paramID.SetFormatted(32,
"%i", paramIdx+1);
986 if (mAAXViewContainer->HandleParameterMouseDown(paramID.Get(), aaxModifiersForPT) == AAX_SUCCESS)
988 ReleaseMouseCapture();
994 #ifndef IGRAPHICS_NO_CONTEXT_MENU 995 if (mod.R && paramIdx > kNoParameter)
997 ReleaseMouseCapture();
998 PopupHostContextMenuForParam(pCapturedControl, paramIdx, x, y);
1003 for (
int v = 0; v < nVals; v++)
1005 if (pCapturedControl->
GetParamIdx(v) > kNoParameter)
1018 if (ControlIsCaptured())
1020 for (
auto& point : points)
1025 auto itr = mCapturedMap.find(mod.touchID);
1027 if(itr != mCapturedMap.end())
1029 IControl* pCapturedControl = itr->second;
1033 int nVals = pCapturedControl->
NVals();
1035 for (
int v = 0; v < nVals; v++)
1037 if (pCapturedControl->
GetParamIdx(v) > kNoParameter)
1041 mCapturedMap.erase(mod.touchID);
1046 if (mResizingInProcess)
1051 #ifdef IGRAPHICS_IMGUI 1052 if(mImGuiRenderer && points.size() == 1)
1054 if(mImGuiRenderer->OnMouseUp(points[0].x, points[0].y, points[0].ms))
1056 ReleaseMouseCapture();
1062 if (points.size() == 1 && !points[0].ms.IsTouch())
1063 OnMouseOver(points[0].x, points[0].y, points[0].ms);
1068 if (ControlIsCaptured())
1071 for (
auto& point : points)
1077 auto itr = mCapturedMap.find(mod.touchID);
1079 if(itr != mCapturedMap.end())
1081 IControl* pCapturedControl = itr->second;
1083 mCapturedMap.erase(mod.touchID);
1093 Trace(
"IGraphics::OnMouseOver", __LINE__,
"x:%0.2f, y:%0.2f, mod:LRSCA: %i%i%i%i%i",
1094 x, y, mod.L, mod.R, mod.S, mod.C, mod.A);
1096 #ifdef IGRAPHICS_IMGUI 1098 mImGuiRenderer->OnMouseMove(x, y, mod);
1102 IControl* pControl = GetMouseControl(x, y,
false,
true);
1104 if (pControl != mMouseOver)
1107 mMouseOver->OnMouseOut();
1109 mMouseOver = pControl;
1120 Trace(
"IGraphics::OnMouseOut", __LINE__,
"");
1123 mCursorType = SetMouseCursor(ECursor::ARROW);
1130 Trace(
"IGraphics::OnMouseDrag:", __LINE__,
"x:%0.2f, y:%0.2f, dX:%0.2f, dY:%0.2f, mod:LRSCA: %i%i%i%i%i",
1131 points[0].x, points[0].y, points[0].dX, points[0].dY, points[0].ms.L, points[0].ms.R, points[0].ms.S, points[0].ms.C, points[0].ms.A);
1133 if (mResizingInProcess && points.size() == 1)
1134 OnDragResize(points[0].x, points[0].y);
1135 else if (ControlIsCaptured() && !IsInPlatformTextEntry())
1139 if (GetControlInTextEntry())
1140 textEntry = mTextEntryControl.get();
1142 for (
auto& point : points)
1146 float dX = point.dX;
1147 float dY = point.dY;
1150 auto itr = mCapturedMap.find(mod.touchID);
1152 if (itr != mCapturedMap.end())
1154 IControl* pCapturedControl = itr->second;
1156 if (textEntry && pCapturedControl != textEntry)
1157 pCapturedControl =
nullptr;
1159 if (pCapturedControl && (dX != 0 || dY != 0))
1166 #ifdef IGRAPHICS_IMGUI 1167 else if(mImGuiRenderer && points.size() == 1)
1168 mImGuiRenderer->OnMouseMove(points[0].x, points[0].y, points[0].ms);
1174 Trace(
"IGraphics::OnMouseDblClick", __LINE__,
"x:%0.2f, y:%0.2f, mod:LRSCA: %i%i%i%i%i",
1175 x, y, mod.L, mod.R, mod.S, mod.C, mod.A);
1177 #ifdef IGRAPHICS_IMGUI 1180 mImGuiRenderer->OnMouseDown(x, y, mod);
1185 IControl* pControl = GetMouseControl(x, y,
true);
1195 std::vector<IMouseInfo> list {info};
1201 ReleaseMouseCapture();
1210 #ifdef IGRAPHICS_IMGUI 1213 mImGuiRenderer->OnMouseWheel(x, y, mod, d);
1218 IControl* pControl = GetMouseControl(x, y,
false);
1225 Trace(
"IGraphics::OnKeyDown", __LINE__,
"x:%0.2f, y:%0.2f, key:%s",
1228 bool handled =
false;
1230 #ifdef IGRAPHICS_IMGUI 1233 handled = mImGuiRenderer->OnKeyDown(x, y, key);
1240 IControl* pControl = GetMouseControl(x, y,
false);
1242 if (pControl && pControl != GetControl(0))
1243 handled = pControl->
OnKeyDown(x, y, key);
1246 handled = mKeyHandlerFunc ? mKeyHandlerFunc(key,
false) :
false;
1253 Trace(
"IGraphics::OnKeyUp", __LINE__,
"x:%0.2f, y:%0.2f, key:%s",
1256 bool handled =
false;
1258 #ifdef IGRAPHICS_IMGUI 1261 handled = mImGuiRenderer->OnKeyUp(x, y, key);
1268 IControl* pControl = GetMouseControl(x, y,
false);
1270 if (pControl && pControl != GetControl(0))
1271 handled = pControl->
OnKeyUp(x, y, key);
1274 handled = mKeyHandlerFunc ? mKeyHandlerFunc(key,
true) :
false;
1281 IControl* pControl = GetMouseControl(x, y,
false);
1282 if (pControl) pControl->
OnDrop(str);
1287 mCapturedMap.clear();
1289 HideMouseCursor(
false);
1292 int IGraphics::GetMouseControlIdx(
float x,
float y,
bool mouseOver)
1294 if (!mouseOver || mEnableMouseOver)
1297 for (
auto c = NControls() - 1; c >= (mouseOver ? 1 : 0); --c)
1299 IControl* pControl = GetControl(c);
1309 if (pControl->
IsHit(x, y))
1328 IControl* IGraphics::GetMouseControl(
float x,
float y,
bool capture,
bool mouseOver, ITouchID touchID)
1332 auto itr = mCapturedMap.find(touchID);
1334 if(ControlIsCaptured() && itr != mCapturedMap.end())
1336 pControl = itr->second;
1342 int controlIdx = -1;
1344 if (!pControl && mPopupControl && mPopupControl->GetExpanded())
1345 pControl = mPopupControl.get();
1347 if (!pControl && mTextEntryControl && mTextEntryControl->EditInProgress())
1348 pControl = mTextEntryControl.get();
1350 #if !defined(NDEBUG) 1351 if (!pControl && mLiveEdit)
1352 pControl = mLiveEdit.get();
1355 if (!pControl && mCornerResizer && mCornerResizer->
GetRECT().
Contains(x, y))
1356 pControl = mCornerResizer.get();
1358 if (!pControl && mPerfDisplay && mPerfDisplay->
GetRECT().
Contains(x, y))
1359 pControl = mPerfDisplay.get();
1363 controlIdx = GetMouseControlIdx(x, y, mouseOver);
1364 pControl = (controlIdx >= 0) ? GetControl(controlIdx) :
nullptr;
1367 if (capture && pControl)
1369 if(MultiTouchEnabled())
1371 bool alreadyCaptured = ControlIsCaptured(pControl);
1377 mCapturedMap.insert(std::make_pair(touchID, pControl));
1383 mMouseOverIdx = controlIdx;
1390 IControl* pControl = GetMouseControl(x, y,
false);
1391 int idx = mLastClickedParam = pControl ? pControl->
GetParamIdx() : -1;
1397 const int idx = mLastClickedParam;
1398 mLastClickedParam = kNoParameter;
1410 contextMenu.Clear();
1416 #if defined VST3_API || defined VST3C_API 1417 VST3_API_BASE* pVST3 =
dynamic_cast<VST3_API_BASE*
>(
GetDelegate());
1419 if (!pVST3->GetComponentHandler() || !pVST3->GetView())
1422 Steinberg::FUnknownPtr<Steinberg::Vst::IComponentHandler3>handler(pVST3->GetComponentHandler() );
1427 Steinberg::Vst::ParamID p = paramIdx;
1429 Steinberg::Vst::IContextMenu* pVST3ContextMenu = handler->createContextMenu(pVST3->GetView(), &p);
1431 if (pVST3ContextMenu)
1433 Steinberg::Vst::IContextMenu::Item item = {0};
1435 for (
int i = 0; i < contextMenu.NItems(); i++)
1437 Steinberg::UString128 (contextMenu.GetItemText(i)).copyTo (item.name, 128);
1440 if (!contextMenu.GetItem(i)->GetEnabled())
1441 item.flags = Steinberg::Vst::IContextMenu::Item::kIsDisabled;
1445 pVST3ContextMenu->addItem(item, pControl);
1448 x *= GetTotalScale();
1449 y *= GetTotalScale();
1451 x *= GetDrawScale();
1452 y *= GetDrawScale();
1454 pVST3ContextMenu->popup((Steinberg::UCoord) x, (Steinberg::UCoord) y);
1455 pVST3ContextMenu->release();
1459 if(!contextMenu.NItems())
1462 DoCreatePopupMenu(*pControl, contextMenu,
IRECT(x, y, x, y), kNoValIdx,
true);
1469 PopupHostContextMenuForParam(GetControl(controlIdx), paramIdx, x, y);
1480 if(mGUISizeMode == EUIResizerMode::Scale)
1482 float scaleX = (x * GetDrawScale()) / mMouseDownX;
1483 float scaleY = (y * GetDrawScale()) / mMouseDownY;
1485 Resize(Width(), Height(), std::min(scaleX, scaleY));
1489 Resize(static_cast<int>(x), static_cast<int>(y), GetDrawScale());
1502 mEnableTooltips = enable;
1503 if (enable) mEnableMouseOver =
true;
1513 mLiveEdit = std::make_unique<IGraphicsLiveEdit>(mEnableMouseOver);
1519 mLiveEdit =
nullptr;
1523 ReleaseMouseCapture();
1524 SetMouseCursor(ECursor::ARROW);
1525 SetAllControlsDirty();
1530 #ifdef IGRAPHICS_SKIA 1533 StaticStorage<SVGHolder>::Accessor storage(sSVGCache);
1534 SVGHolder* pHolder = storage.Find(fileName);
1538 WDL_TypedBuf<uint8_t> svgData = LoadResource(fileName,
"svg");
1539 if (svgData.GetSize() == 0)
1541 return ISVG(
nullptr);
1545 return LoadSVG(fileName, svgData.Get(), svgData.GetSize(), units, dpi);
1549 return ISVG(pHolder->mSVGDom);
1554 StaticStorage<SVGHolder>::Accessor storage(sSVGCache);
1555 SVGHolder* pHolder = storage.Find(name);
1559 sk_sp<SkSVGDOM> svgDOM;
1562 SkMemoryStream svgStream(pData, dataSize);
1563 svgDOM = SkSVGDOM::MakeFromStream(svgStream);
1566 return ISVG(
nullptr);
1570 if (svgDOM->containerSize().width() == 0)
1572 NSVGimage* pImage =
nullptr;
1575 svgStr.Set((
const char*)pData, dataSize);
1576 pImage = nsvgParse(svgStr.Get(), units, dpi);
1580 svgDOM->setContainerSize(SkSize::Make(pImage->width, pImage->height));
1585 pHolder =
new SVGHolder(svgDOM);
1586 storage.Add(pHolder, name);
1589 return ISVG(pHolder->mSVGDom);
1595 StaticStorage<SVGHolder>::Accessor storage(sSVGCache);
1596 SVGHolder* pHolder = storage.Find(fileName);
1600 WDL_TypedBuf<uint8_t> svgData = LoadResource(fileName,
"svg");
1601 if (svgData.GetSize() == 0)
1603 return ISVG(
nullptr);
1607 return LoadSVG(fileName, svgData.Get(), svgData.GetSize(), units, dpi);
1611 return ISVG(pHolder->mImage);
1616 StaticStorage<SVGHolder>::Accessor storage(sSVGCache);
1617 SVGHolder* pHolder = storage.Find(name);
1621 NSVGimage* pImage =
nullptr;
1625 svgStr.Set((
const char*)pData, dataSize);
1626 pImage = nsvgParse(svgStr.Get(), units, dpi);
1629 return ISVG(
nullptr);
1631 pHolder =
new SVGHolder(pImage);
1633 storage.Add(pHolder, name);
1636 return ISVG(pHolder->mImage);
1642 WDL_TypedBuf<uint8_t> result;
1645 EResourceLocation resourceFound =
LocateResource(fileNameOrResID, fileType, path, GetBundleID(), GetWinModuleHandle(), GetSharedResourcesSubPath());
1647 if (resourceFound == EResourceLocation::kNotFound)
1651 if (resourceFound == EResourceLocation::kWinBinary)
1654 const void* pResData =
LoadWinResource(path.Get(), fileType, size, GetWinModuleHandle());
1655 result.Resize(size);
1656 result.Set((
const uint8_t*)pResData, size);
1659 if (resourceFound == EResourceLocation::kAbsolutePath)
1661 FILE* fd = fopen(path.Get(),
"rb");
1666 if (fseek(fd, 0, SEEK_END))
1671 long size = ftell(fd);
1674 if (fseek(fd, 0, SEEK_SET))
1680 result.Resize((
int)size);
1681 size_t bytesRead = fread(result.Get(), 1, (size_t)size, fd);
1682 if (bytesRead != (
size_t)size)
1685 result.Resize(0,
true);
1696 if (targetScale == 0)
1697 targetScale = GetRoundedScreenScale();
1699 StaticStorage<APIBitmap>::Accessor storage(sBitmapCache);
1700 APIBitmap* pAPIBitmap = storage.Find(name, targetScale);
1705 WDL_String fullPath;
1706 std::unique_ptr<APIBitmap> loadedBitmap;
1707 int sourceScale = 0;
1709 const char* ext = name + strlen(name) - 1;
1710 while (ext >= name && *ext !=
'.') --ext;
1713 bool bitmapTypeSupported = BitmapExtSupported(ext);
1715 if (!bitmapTypeSupported)
1718 EResourceLocation resourceLocation = SearchImageResource(name, ext, fullPath, targetScale, sourceScale);
1720 if (resourceLocation == EResourceLocation::kNotFound)
1723 pAPIBitmap = SearchBitmapInCache(name, targetScale, sourceScale);
1728 if (sourceScale != targetScale)
1729 pAPIBitmap = storage.Find(name, sourceScale);
1734 loadedBitmap = std::unique_ptr<APIBitmap>(LoadAPIBitmap(fullPath.Get(), sourceScale, resourceLocation, ext));
1735 pAPIBitmap= loadedBitmap.get();
1740 assert(pAPIBitmap &&
"Bitmap not found");
1743 if (pAPIBitmap->
GetScale() != targetScale)
1745 return ScaleBitmap(
IBitmap(pAPIBitmap, nStates, framesAreHorizontal, name), name, targetScale);
1747 else if (loadedBitmap)
1749 RetainBitmap(
IBitmap(loadedBitmap.release(), nStates, framesAreHorizontal, name), name);
1753 return IBitmap(pAPIBitmap, nStates, framesAreHorizontal, name);
1758 if (targetScale == 0)
1759 targetScale = GetRoundedScreenScale();
1761 StaticStorage<APIBitmap>::Accessor storage(sBitmapCache);
1762 APIBitmap* pAPIBitmap = storage.Find(name, targetScale);
1767 WDL_String fullPath;
1768 std::unique_ptr<APIBitmap> loadedBitmap;
1769 int sourceScale = 0;
1771 const char* ext = name + strlen(name) - 1;
1772 while (ext >= name && *ext !=
'.') --ext;
1775 bool bitmapTypeSupported = BitmapExtSupported(ext);
1777 if (!bitmapTypeSupported)
1781 pAPIBitmap = SearchBitmapInCache(name, targetScale, sourceScale);
1785 loadedBitmap = std::unique_ptr<APIBitmap>(LoadAPIBitmap(name, pData, dataSize, 1));
1786 pAPIBitmap= loadedBitmap.get();
1791 assert(pAPIBitmap &&
"Bitmap not found");
1794 if (pAPIBitmap->
GetScale() != targetScale)
1796 return ScaleBitmap(
IBitmap(pAPIBitmap, nStates, framesAreHorizontal, name), name, targetScale);
1798 else if (loadedBitmap)
1800 RetainBitmap(
IBitmap(loadedBitmap.release(), nStates, framesAreHorizontal, name), name);
1804 return IBitmap(pAPIBitmap, nStates, framesAreHorizontal, name);
1809 StaticStorage<APIBitmap>::Accessor storage(sBitmapCache);
1815 StaticStorage<APIBitmap>::Accessor storage(sBitmapCache);
1821 int screenScale = GetRoundedScreenScale();
1822 float drawScale = GetDrawScale();
1824 mScreenScale = scale;
1828 StartLayer(
nullptr, bounds,
true);
1829 DrawBitmap(inBitmap, bounds, 0, 0,
nullptr);
1832 RetainBitmap(outBitmap, name);
1834 mScreenScale = screenScale;
1835 mDrawScale = drawScale;
1843 if (sourceScale == targetScale && (targetScale != MAX_IMG_SCALE))
1844 sourceScale = MAX_IMG_SCALE;
1845 else if (sourceScale == targetScale + 1)
1846 sourceScale = targetScale - 1;
1854 for (sourceScale = targetScale ; sourceScale > 0; SearchNextScale(sourceScale, targetScale))
1856 WDL_String fullName(name);
1858 if (sourceScale != 1)
1860 WDL_String baseName(name); baseName.remove_fileext();
1861 WDL_String ext(fullName.get_fileext());
1862 fullName.SetFormatted((
int) (strlen(name) + strlen(
"@2x")),
"%s@%dx%s", baseName.Get(), sourceScale, ext.Get());
1865 EResourceLocation found =
LocateResource(fullName.Get(), type, result, GetBundleID(), GetWinModuleHandle(), GetSharedResourcesSubPath());
1867 if (found > EResourceLocation::kNotFound)
1871 return EResourceLocation::kNotFound;
1876 StaticStorage<APIBitmap>::Accessor storage(sBitmapCache);
1879 for (sourceScale = targetScale; sourceScale > 0; SearchNextScale(sourceScale, targetScale))
1881 APIBitmap* pBitmap = storage.Find(name, sourceScale);
1892 for (
auto c = 0; c < NControls(); c++)
1902 mInTextEntry = &control;
1903 mTextEntryValIdx = valIdx;
1905 int paramIdx = valIdx > kNoValIdx ? control.
GetParamIdx(valIdx) : kNoParameter;
1907 if (mTextEntryControl)
1908 mTextEntryControl->CreateTextEntry(paramIdx, text, bounds, control.
GetTextEntryLength(), str);
1912 mInTextEntry->SetDirty(
false);
1915 void IGraphics::DoCreatePopupMenu(
IControl& control,
IPopupMenu& menu,
const IRECT& bounds,
int valIdx,
bool isContext)
1917 ReleaseMouseCapture();
1919 mInPopupMenu = &control;
1920 mPopupMenuValIdx = valIdx;
1921 mIsContextMenu = isContext;
1925 mPopupControl->CreatePopupMenu(menu, bounds);
1929 bool isAsync =
false;
1930 IPopupMenu* pReturnMenu = CreatePlatformPopupMenu(menu, bounds, isAsync);
1933 SetControlValueAfterPopupMenu(pReturnMenu);
1939 DoCreatePopupMenu(control, menu, bounds, valIdx,
false);
1942 void IGraphics::EndDragResize()
1944 mResizingInProcess =
false;
1946 if (GetResizerMode() == EUIResizerMode::Scale)
1950 SetAllControlsDirty();
1956 auto pixelBackingScale = GetBackingPixelScale();
1958 const int w =
static_cast<int>(std::ceil(pixelBackingScale * std::ceil(alignedBounds.
W())));
1959 const int h =
static_cast<int>(std::ceil(pixelBackingScale * std::ceil(alignedBounds.
H())));
1961 PushLayer(
new ILayer(CreateAPIBitmap(w, h, GetRoundedScreenScale(), GetDrawScale(), cacheable), alignedBounds, pControl, pControl ? pControl->
GetRECT() :
IRECT()));
1968 ownedLayer.swap(layer);
1969 ILayer* pOwnerlessLayer = ownedLayer.release();
1971 if (pOwnerlessLayer)
1973 PushLayer(pOwnerlessLayer);
1984 mLayers.push(pLayer);
1986 PathTransformReset();
1987 PathClipRegion(pLayer->
Bounds());
1993 ILayer* pLayer =
nullptr;
1995 if (!mLayers.empty())
1997 pLayer = mLayers.top();
2002 PathTransformReset();
2011 const APIBitmap* pBitmap = layer ? layer->GetAPIBitmap() :
nullptr;
2013 if (pBitmap && layer->mControl && layer->mControlRECT != layer->mControl->GetRECT())
2015 layer->mControlRECT = layer->mControl->GetRECT();
2016 layer->Invalidate();
2019 return pBitmap && !layer->mInvalid && pBitmap->
GetDrawScale() == GetDrawScale() && pBitmap->
GetScale() == GetRoundedScreenScale();
2024 PathTransformSave();
2025 PathTransformReset();
2026 DrawBitmap(layer->GetBitmap(), layer->Bounds(), 0, 0, pBlend);
2027 PathTransformRestore();
2032 IBitmap bitmap = layer->GetBitmap();
2033 IRECT layerBounds = layer->Bounds();
2034 PathTransformSave();
2035 PathTransformTranslate(bounds.
L, bounds.
T);
2036 IRECT newBounds(0., 0., layerBounds.
W(), layerBounds.
H());
2037 PathTransformScale(bounds.
W() / layerBounds.
W(), bounds.
H() / layerBounds.
H());
2038 DrawBitmap(bitmap, newBounds, 0, 0, pBlend);
2039 PathTransformRestore();
2044 PathTransformSave();
2045 PathTransformReset();
2046 IBitmap bitmap = layer->GetBitmap();
2047 IRECT bounds = layer->Bounds();
2048 DrawRotatedBitmap(bitmap, bounds.
MW(), bounds.
MH(), angle);
2049 PathTransformRestore();
2054 auto GaussianBlurSwap = [](uint8_t* out, uint8_t* in, uint8_t* kernel,
int width,
int height,
2055 int outStride,
int inStride,
int kernelSize, uint32_t norm)
2058 int fullKernelSize = kernelSize * 2 + 1;
2061 auto RepeatCheck = [&](
int idx)
2063 repeats = last == in[idx * 4] ? std::min(repeats + 1, fullKernelSize) : 1;
2066 return repeats == fullKernelSize;
2069 for (
int i = 0; i < height; i++, in += inStride)
2071 for (
int j = 0; j < kernelSize - 1; j++)
2073 uint32_t accum = in[j * 4] * kernel[0];
2074 for (
int k = 1; k < j + 1; k++)
2075 accum += kernel[k] * in[(j - k) * 4];
2076 for (
int k = 1; k < kernelSize; k++)
2077 accum += kernel[k] * in[(j + k) * 4];
2078 out[j * outStride + (i * 4)] = static_cast<uint8_t>(std::min(static_cast<uint32_t>(255), accum / norm));
2080 for (
int j = 0; j < kernelSize * 2 - 2; j++)
2082 for (
int j = kernelSize - 1; j < (width - kernelSize) + 1; j++)
2084 if (RepeatCheck(j + kernelSize - 1))
2086 out[j * outStride + (i * 4)] = static_cast<uint8_t>(last);
2090 uint32_t accum = in[j * 4] * kernel[0];
2091 for (
int k = 1; k < kernelSize; k++)
2092 accum += kernel[k] * (in[(j - k) * 4] + in[(j + k) * 4]);
2093 out[j * outStride + (i * 4)] = static_cast<uint8_t>(std::min(static_cast<uint32_t>(255), accum / norm));
2095 for (
int j = (width - kernelSize) + 1; j < width; j++)
2097 uint32_t accum = in[j * 4] * kernel[0];
2098 for (
int k = 1; k < kernelSize; k++)
2099 accum += kernel[k] * in[(j - k) * 4];
2100 for (
int k = 1; k < width - j; k++)
2101 accum += kernel[k] * in[(j + k) * 4];
2102 out[j * outStride + (i * 4)] = static_cast<uint8_t>(std::min(static_cast<uint32_t>(255), accum / norm));
2107 RawBitmapData temp1;
2108 RawBitmapData temp2;
2109 RawBitmapData kernel;
2112 GetLayerBitmapData(layer, temp1);
2114 if (!temp1.GetSize())
2116 temp2.Resize(temp1.GetSize());
2119 bool flipped = FlippedBitmap();
2120 float scale = layer->GetAPIBitmap()->GetScale() * layer->GetAPIBitmap()->GetDrawScale();
2121 float blurSize = std::max(1.f, (shadow.mBlurSize * scale) + 1.f);
2122 float blurConst = 4.5f / (blurSize * blurSize);
2123 int iSize =
static_cast<int>(ceil(blurSize));
2124 int width = layer->GetAPIBitmap()->GetWidth();
2125 int height = layer->GetAPIBitmap()->GetHeight();
2126 int stride1 = temp1.GetSize() / width;
2127 int stride2 = flipped ? -temp1.GetSize() / height : temp1.GetSize() / height;
2128 int stride3 = flipped ? -stride2 : stride2;
2130 kernel.Resize(iSize);
2132 for (
int i = 0; i < iSize; i++)
2133 kernel.Get()[i] =
static_cast<uint8_t
>(std::round(255.f * std::expf(-(i * i) * blurConst)));
2136 int normFactor = kernel.Get()[0];
2138 for (
int i = 1; i < iSize; i++)
2139 normFactor += kernel.Get()[i] + kernel.Get()[i];
2142 uint8_t* asRows = temp1.Get() + AlphaChannel();
2143 uint8_t* inRows = flipped ? asRows + stride3 * (height - 1) : asRows;
2144 uint8_t* asCols = temp2.Get() + AlphaChannel();
2146 GaussianBlurSwap(asCols, inRows, kernel.Get(), width, height, stride1, stride2, iSize, normFactor);
2147 GaussianBlurSwap(asRows, asCols, kernel.Get(), height, width, stride3, stride1, iSize, normFactor);
2150 ApplyShadowMask(layer, temp1, shadow);
2155 PlatformFontPtr font = LoadPlatformFont(fontID, fileNameOrResID);
2159 if (LoadAPIFont(fontID, font))
2161 CachePlatformFont(fontID, font);
2166 DBGMSG(
"Could not locate font %s\n", fileNameOrResID);
2172 PlatformFontPtr font = LoadPlatformFont(fontID, pData, dataSize);
2176 if (LoadAPIFont(fontID, font))
2178 CachePlatformFont(fontID, font);
2183 DBGMSG(
"Could not load font %s\n", fontID);
2189 PlatformFontPtr font = LoadPlatformFont(fontID, fontName, style);
2193 if (LoadAPIFont(fontID, font))
2195 CachePlatformFont(fontID, font);
2200 DBGMSG(
"Could not locate font %s\n", fontID);
2206 double tx = 0.0, ty = 0.0;
2208 CalculateTextRotation(text, bounds, rect, tx, ty);
2209 rect.
Translate(static_cast<float>(tx), static_cast<float>(ty));
2233 IRECT r1(static_cast<float>(std::min(x0, x3)), static_cast<float>(std::min(y0, y3)), static_cast<float>(std::max(x0, x3)), static_cast<float>(std::max(y0, y3)));
2234 IRECT r2(static_cast<float>(std::min(x1, x2)), static_cast<float>(std::min(y1, y2)), static_cast<float>(std::max(x1, x2)), static_cast<float>(std::max(y1, y2)));
2235 rect = r1.
Union(r2);
2237 switch (text.mAlign)
2239 case EAlign::Near: tx = bounds.
L - rect.
L;
break;
2240 case EAlign::Center: tx = bounds.
MW() - rect.
MW();
break;
2241 case EAlign::Far: tx = bounds.
R - rect.
R;
break;
2244 switch (text.mVAlign)
2246 case EVAlign::Top: ty = bounds.
T - rect.
T;
break;
2247 case EVAlign::Middle: ty = bounds.
MH() - rect.
MH();
break;
2248 case EVAlign::Bottom: ty = bounds.
B - rect.
B;
break;
2254 SetKeyHandlerFunc([&, func](
const IKeyPress& key,
bool isUp) {
2258 static int base = 48;
2259 static bool keysDown[128] = {};
2261 auto onOctSwitch = [&]() {
2262 base =
Clip(base, 24, 96);
2264 for(
auto i=0;i<128;i++) {
2275 case kVK_A: note = 0;
break;
2276 case kVK_W: note = 1;
break;
2277 case kVK_S: note = 2;
break;
2278 case kVK_E: note = 3;
break;
2279 case kVK_D: note = 4;
break;
2280 case kVK_F: note = 5;
break;
2281 case kVK_T: note = 6;
break;
2282 case kVK_G: note = 7;
break;
2283 case kVK_Y: note = 8;
break;
2284 case kVK_H: note = 9;
break;
2285 case kVK_U: note = 10;
break;
2286 case kVK_J: note = 11;
break;
2287 case kVK_K: note = 12;
break;
2288 case kVK_O: note = 13;
break;
2289 case kVK_L: note = 14;
break;
2290 case kVK_Z:
if(!isUp) { base -= 12; onOctSwitch(); }
return true;
2291 case kVK_X:
if(!isUp) { base += 12; onOctSwitch(); }
return true;
2292 default:
return true;
2295 int pitch = base + note;
2298 if(keysDown[pitch] ==
false) {
2300 keysDown[pitch] =
true;
2307 if(keysDown[pitch] ==
true) {
2309 keysDown[pitch] =
false;
2322 IControl* pControl = GetMouseControl(x, y,
false,
false);
2327 if(mGestureRegions.Size() == 0)
2331 int regionIdx = mGestureRegions.Find(x, y);
2342 IControl* pControl = GetMouseControl(info.x, info.y,
false,
false);
2348 int regionIdx = mGestureRegions.Find(info.x, info.y);
2351 mGestureRegionFuncs.find(regionIdx)->second(
nullptr, info);
2357 if (std::find(std::begin(mRegisteredGestures), std::end(mRegisteredGestures), type) != std::end(mRegisteredGestures))
2359 mRegisteredGestures.push_back(type);
2365 mGestureRegions.Add(bounds);
2367 mGestureRegionFuncs.insert(std::make_pair(mGestureRegions.Size()-1, func));
2372 mGestureRegions.Clear();
2373 mGestureRegionFuncs.clear();
2376 #ifdef IGRAPHICS_IMGUI 2379 mImGuiRenderer = std::make_unique<ImGuiRenderer>(
this, drawFunc, setupFunc);
2381 CreatePlatformImGui();
2390 PathTransformSave();
2391 PathTransformTranslate(destCtrX, destCtrY);
2392 PathTransformRotate((
float) angle);
2393 DrawBitmap(bitmap,
IRECT(-width * 0.5f, - height * 0.5f, width * 0.5f, height * 0.5f), 0, 0, pBlend);
2394 PathTransformRestore();
2399 FillRect(color,
IRECT(x, y, x+1.f, y+1.f), pBlend);
2415 if (gridSizeH > 1.f)
2417 for (
float x = bounds.
L + gridSizeH; x < bounds.
R; x += gridSizeH)
2419 PathMoveTo(x, bounds.
T);
2420 PathLineTo(x, bounds.
B);
2424 if (gridSizeV > 1.f)
2426 for (
float y = bounds.
T + gridSizeV; y < bounds.
B; y += gridSizeV)
2428 PathMoveTo(bounds.
L, y);
2429 PathLineTo(bounds.
R, y);
2440 float xPos = bounds.
L;
2442 PathMoveTo(xPos, bounds.
B - (bounds.
H() * normYPoints[0]));
2444 for (
auto i = 1; i < nPoints; i++)
2447 xPos = bounds.
L + (bounds.
W() * normXPoints[i]);
2449 xPos = bounds.
L + ((bounds.
W() / (float) (nPoints - 1) * i));
2451 PathLineTo(xPos, bounds.
B - (bounds.
H() * normYPoints[i]));
2462 options.mDash.SetDash(&dashLen, 0.0, 1);
2465 PathStroke(color, thickness, options, pBlend);
2471 PathTriangle(x1, y1, x2, y2, x3, y3);
2485 PathRoundRect(bounds, cornerRadius);
2492 PathRoundRect(bounds, cRTL, cRTR, cRBR, cRBL);
2499 PathConvexPolygon(x, y, nPoints);
2506 PathArc(cx, cy, r, a1, a2);
2513 PathCircle(cx, cy, r);
2521 options.mDash.SetDash(&dashLen, 0., 1);
2523 PathStroke(color, thickness, options, pBlend);
2529 PathEllipse(bounds);
2536 PathEllipse(x, y, r1, r2, angle);
2543 PathTriangle(x1, y1, x2, y2, x3, y3);
2557 PathRoundRect(bounds, cornerRadius);
2564 PathRoundRect(bounds, cRTL, cRTR, cRBR, cRBL);
2571 PathConvexPolygon(x, y, nPoints);
2579 PathArc(cx, cy, r, a1, a2);
2587 PathCircle(cx, cy, r);
2594 PathEllipse(bounds);
2601 PathEllipse(x, y, r1, r2, angle);
2615 PathMoveTo(bounds.
L, bounds.
T);
2616 PathLineTo(bounds.
R, bounds.
T);
2617 PathLineTo(bounds.
R, bounds.
B);
2618 PathLineTo(bounds.
L, bounds.
B);
2624 if (ctl <= 0.f && ctr <= 0.f && cbl <= 0.f && cbr <= 0.f)
2630 const float y = bounds.
B - bounds.
H();
2631 PathMoveTo(bounds.
L, y + ctl);
2632 PathArc(bounds.
L + ctl, y + ctl, ctl, 270.f, 360.f);
2633 PathArc(bounds.
L + bounds.
W() - ctr, y + ctr, ctr, 0.f, 90.f);
2634 PathArc(bounds.
L + bounds.
W() - cbr, y + bounds.
H() - cbr, cbr, 90.f, 180.f);
2635 PathArc(bounds.
L + cbl, y + bounds.
H() - cbl, cbl, 180.f, 270.f);
2642 PathRoundRect(bounds, cr, cr, cr, cr);
2647 PathTransformSave();
2649 if (r1 <= 0.0 || r2 <= 0.0)
2652 PathTransformTranslate(x, y);
2653 PathTransformRotate(angle);
2654 PathTransformScale(r1, r2);
2656 PathCircle(0.0, 0.0, 1.0);
2658 PathTransformRestore();
2663 PathEllipse(bounds.
MW(), bounds.
MH(), bounds.
W() / 2.f, bounds.
H() / 2.f);
2668 PathMoveTo(cx, cy - r);
2669 PathArc(cx, cy, r, 0.f, 360.f);
2675 PathMoveTo(x[0], y[0]);
2676 for(
int i = 1; i < nPoints; i++)
2677 PathLineTo(x[i], y[i]);
2683 mTransformStates.push(mTransform);
2688 if (!mTransformStates.empty())
2690 mTransform = mTransformStates.top();
2691 mTransformStates.pop();
2692 PathTransformSetMatrix(mTransform);
2700 std::stack<IMatrix> newStack;
2701 mTransformStates.swap(newStack);
2705 PathTransformSetMatrix(mTransform);
2710 mTransform.Translate(x, y);
2711 PathTransformSetMatrix(mTransform);
2716 mTransform.Scale(scaleX, scaleY);
2717 PathTransformSetMatrix(mTransform);
2722 PathTransformScale(scale, scale);
2727 mTransform.Rotate(angle);
2728 PathTransformSetMatrix(mTransform);
2733 mTransform.Skew(xAngle, yAngle);
2734 PathTransformSetMatrix(mTransform);
2739 mTransform.Transform(matrix);
2740 PathTransformSetMatrix(mTransform);
2745 IRECT drawArea = mLayers.empty() ? mClipRECT : mLayers.top()->Bounds();
2747 PathTransformSetMatrix(
IMatrix());
2748 SetClipRegion(clip);
2749 PathTransformSetMatrix(mTransform);
2754 PathTransformSave();
2755 PathTransformTranslate(bounds.
L, bounds.
T);
2756 IRECT newBounds(0., 0., static_cast<float>(bitmap.
W()), static_cast<float>(bitmap.
H()));
2757 PathTransformScale(bounds.
W() /
static_cast<float>(bitmap.
W()), bounds.
H() /
static_cast<float>(bitmap.
H()));
2758 DrawBitmap(bitmap, newBounds, 0, 0, pBlend);
2759 PathTransformRestore();
2764 float xScale = dest.
W() / svg.
W();
2765 float yScale = dest.
H() / svg.
H();
2766 float scale = xScale < yScale ? xScale : yScale;
2768 PathTransformSave();
2769 PathTransformTranslate(dest.
L, dest.
T);
2770 PathTransformScale(scale);
2771 DoDrawSVG(svg, pBlend);
2772 PathTransformRestore();
2777 PathTransformSave();
2778 PathTransformTranslate(destCtrX, destCtrY);
2779 PathTransformRotate((
float) angle);
2780 DrawSVG(svg,
IRECT(-width * 0.5f, - height * 0.5f, width * 0.5f, height * 0.5f), pBlend);
2781 PathTransformRestore();
2784 IPattern IGraphics::GetSVGPattern(
const NSVGpaint& paint,
float opacity)
2786 int alpha = std::min(255, std::max(
int(roundf(opacity * 255.f)), 0));
2790 case NSVG_PAINT_COLOR:
2791 return IColor(alpha, (paint.color >> 0) & 0xFF, (paint.color >> 8) & 0xFF, (paint.color >> 16) & 0xFF);
2793 case NSVG_PAINT_LINEAR_GRADIENT:
2794 case NSVG_PAINT_RADIAL_GRADIENT:
2796 NSVGgradient* pGrad = paint.gradient;
2798 IPattern pattern(paint.type == NSVG_PAINT_LINEAR_GRADIENT ? EPatternType::Linear : EPatternType::Radial);
2801 switch (pGrad->spread)
2803 case NSVG_SPREAD_PAD: pattern.mExtend = EPatternExtend::Pad;
break;
2804 case NSVG_SPREAD_REFLECT: pattern.mExtend = EPatternExtend::Reflect;
break;
2805 case NSVG_SPREAD_REPEAT: pattern.mExtend = EPatternExtend::Repeat;
break;
2809 for (
int i = 0; i < pGrad->nstops; i++)
2811 unsigned int color = pGrad->stops[i].color;
2812 pattern.
AddStop(
IColor(255, (color >> 0) & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF), pGrad->stops[i].offset);
2816 pattern.
SetTransform(pGrad->xform[0], pGrad->xform[1], pGrad->xform[2], pGrad->xform[3], pGrad->xform[4], pGrad->xform[5]);
2821 return IColor(alpha, 0, 0, 0);
2825 void IGraphics::DoDrawSVG(
const ISVG& svg,
const IBlend* pBlend)
2827 #ifdef IGRAPHICS_SKIA 2828 SkCanvas* canvas =
static_cast<SkCanvas*
>(GetDrawContext());
2829 svg.mSVGDom->render(canvas);
2831 NSVGimage* pImage = svg.mImage;
2833 assert(pImage !=
nullptr);
2835 for (NSVGshape* pShape = pImage->shapes; pShape; pShape = pShape->next)
2837 if (!(pShape->flags & NSVG_FLAGS_VISIBLE))
2844 for (NSVGpath* pPath = pShape->paths; pPath; pPath = pPath->next)
2846 PathMoveTo(pPath->pts[0], pPath->pts[1]);
2848 for (
int i = 1; i < pPath->npts; i += 3)
2850 float *p = &pPath->pts[i*2];
2851 PathCubicBezierTo(p[0], p[1], p[2], p[3], p[4], p[5]);
2859 IVec2 p0{pPath->pts[0], pPath->pts[1]};
2860 IVec2 p1{pPath->bounds[0] - 1.0f, pPath->bounds[1] - 1.0f};
2862 for (NSVGpath *pPath2 = pShape->paths; pPath2; pPath2 = pPath2->next)
2864 if (pPath2 == pPath)
2867 if (pPath2->npts < 4)
2869 for (
int i = 1; i < pPath2->npts + 3; i += 3)
2871 float *p = &pPath2->pts[2*i];
2873 IVec2 p2 {p[-2], p[-1]};
2875 IVec2 p3 = (i < pPath2->npts) ?
IVec2{p[4], p[5]} :
IVec2{pPath2->pts[0], pPath2->pts[1]};
2876 float crossing = GetLineCrossing(p0, p1, p2, p3);
2877 float crossing2 = GetLineCrossing(p2, p3, p0, p1);
2878 if (0.0 <= crossing && crossing < 1.0 && 0.0 <= crossing2)
2884 PathSetWinding(crossings % 2 != 0);
2888 if (pShape->fill.type != NSVG_PAINT_NONE)
2891 options.mFillRule = EFillRule::Preserve;
2893 options.mPreserve = pShape->stroke.type != NSVG_PAINT_NONE;
2894 PathFill(GetSVGPattern(pShape->fill, pShape->opacity), options, pBlend);
2898 if (pShape->stroke.type != NSVG_PAINT_NONE)
2902 options.mMiterLimit = pShape->miterLimit;
2904 switch (pShape->strokeLineCap)
2906 case NSVG_CAP_BUTT: options.mCapOption = ELineCap::Butt;
break;
2907 case NSVG_CAP_ROUND: options.mCapOption = ELineCap::Round;
break;
2908 case NSVG_CAP_SQUARE: options.mCapOption = ELineCap::Square;
break;
2911 switch (pShape->strokeLineJoin)
2913 case NSVG_JOIN_MITER: options.mJoinOption = ELineJoin::Miter;
break;
2914 case NSVG_JOIN_ROUND: options.mJoinOption = ELineJoin::Round;
break;
2915 case NSVG_JOIN_BEVEL: options.mJoinOption = ELineJoin::Bevel;
break;
2918 options.mDash.SetDash(pShape->strokeDashArray, pShape->strokeDashOffset, pShape->strokeDashCount);
2920 PathStroke(GetSVGPattern(pShape->stroke, pShape->opacity), pShape->strokeWidth, options, pBlend);
Encapsulate an xy point in one struct.
void PathRect(const IRECT &bounds)
Add a rectangle to the current path.
bool Contains(const IRECT &rhs) const
Returns true if this IRECT completely contains rhs.
void PathConvexPolygon(float *x, float *y, int nPoints)
Add a convex polygon to the current path.
const IRECT & Get(int idx) const
Get an IRECT from the list (will crash if idx is invalid)
void Optimize()
Remove rects that are contained by other rects and intersections and merge any rects that can be merg...
virtual void DrawPoint(const IColor &color, float x, float y, const IBlend *pBlend=0)
Fill a rectangle corresponding to a pixel on a 1:1 screen with a color.
virtual void OnAttached()
Called after the control has been attached, and its delegate and graphics member variable set...
const char * GetName() const
Returns the parameter's name.
int NDisplayTexts() const
Get the number of display texts for the parameter.
Used to manage a list of rectangular areas and optimize them for drawing to the screen.
void StartLayer(IControl *pOwner, const IRECT &r, bool cacheable=false)
Create an IGraphics layer.
The lowest level base class of an IGraphics control.
virtual void LayoutUI(IGraphics *pGraphics)
Called to layout controls when the GUI is initially opened and again if the UI size changes...
void SetPTParameterHighlight(bool isHighlighted, int color)
Used internally by the AAX wrapper view interface to set the control parmeter highlight.
void OnMouseDrag(const std::vector< IMouseInfo > &points)
Called when the platform class sends drag events.
Used to manage a rectangular area, independent of draw class/platform.
virtual void OnResize()
Called when IControl is constructed or resized using SetRect().
IGEditorDelegate * GetDelegate()
Gets a pointer to the class implementing the IEditorDelegate interface that handles parameter changes...
virtual void DrawGrid(const IColor &color, const IRECT &bounds, float gridSizeH, float gridSizeV, const IBlend *pBlend=0, float thickness=1.f)
Draw a grid to the graphics context.
void SetControlSize(int idx, float w, float h)
Resize a control, redrawing the interface correctly.
virtual void OnMouseDown(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouse down event on this control.
int LinkedToParam(int paramIdx) const
Check if the control is linked to a particular parameter.
void DrawRotatedLayer(const ILayerPtr &layer, double angle)
Draw a layer to the main IGraphics context, with rotation.
A basic control to draw a bitmap, or one frame of a stacked bitmap depending on the current value...
void PathTransformTranslate(float x, float y)
Apply a translation transform to the current path.
virtual void DrawRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0, float thickness=1.f)
Draw a rectangle to the graphics context.
void RemoveTextEntryControl()
Remove the IGraphics text entry, use platform text entry if available.
void AttachTextEntryControl()
Attach a control for text entry, to override platform text entry.
virtual void DrawConvexPolygon(const IColor &color, float *x, float *y, int nPoints, const IBlend *pBlend=0, float thickness=1.f)
Draw a convex polygon to the graphics context.
Used to manage composite/blend operations, independent of draw class/platform.
bool GetMouseEventsWhenDisabled() const
int GetTag() const
Get the control's tag.
User-facing bitmap abstraction that you use to manage bitmap data, independant of draw class/platform...
void ApplyLayerDropShadow(ILayerPtr &layer, const IShadow &shadow)
Applies a drop shadow directly onto a layer.
Encapsulates a MIDI message and provides helper functions.
virtual bool OnKeyUp(float x, float y, const IKeyPress &key)
Implement this method to respond to a key up event on this control.
void EnableTooltips(bool enable)
IRECT Bounds()
Get a union of all rectangles in the list.
Used to manage fill behaviour for path based drawing back ends.
void AttachCornerResizer(EUIResizerMode sizeMode=EUIResizerMode::Scale, bool layoutOnResize=false, const IColor &color=COLOR_TRANSLUCENT, const IColor &mouseOverColor=COLOR_BLACK, const IColor &dragColor=COLOR_BLACK, float size=20.f)
Attach the default control to scale or increase the UI size by dragging the plug-in bottom right-hand...
void CreateTextEntry(IControl &control, const IText &text, const IRECT &bounds, const char *str="", int valIdx=0)
Create a text entry box.
void ReleaseMouseCapture()
Used to tell the graphics context to stop tracking mouse interaction with a control.
void ResumeLayer(ILayerPtr &layer)
If a layer already exists, continue drawing to it.
virtual void DrawDottedRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0, float thickness=1.f, float dashLen=2.f)
Draw a dotted rectangle to the graphics context.
A Text entry widget drawn by IGraphics to optionally override platform text entries.
Used to manage mouse modifiers i.e.
virtual void BeginFrame()
Called at the beginning of drawing.
void OnGUIIdle()
This is an idle timer tick call on the GUI thread, only active if USE_IDLE_CALLS is defined...
void SetControlValueAfterTextEdit(const char *str)
Called by the platform class after returning from a text entry in order to update a control with a ne...
int GetTextEntryLength() const
Get the max number of characters that are allowed in text entry.
virtual void DrawData(const IColor &color, const IRECT &bounds, float *normYPoints, int nPoints, float *normXPoints=nullptr, const IBlend *pBlend=0, float thickness=1.f)
Draw a line between a collection of normalized points.
void PathTransformSave()
Save the current affine transform of the current path.
const void * LoadWinResource(const char *resID, const char *type, int &sizeInBytes, void *pHInstance)
Load a resource from the binary (windows only).
void ForAllControls(T method, Args...args)
For all controls, including the "special controls" call a method.
void PopupHostContextMenuForParam(int controlIdx, int paramIdx, float x, float y)
[VST3 primarily] In VST3 plug-ins this enable support for the IContextMenu interface, which allows the host to add contextual options to e.g.
virtual void Hide(bool hide)
Shows or hides the IControl.
void PathTransformMatrix(const IMatrix &matrix)
Apply an arbitary affine transform matrix to the current path.
void AttachPanelBackground(const IPattern &color)
Attach an IPanelControl as the lowest IControl in the control stack to fill the background with a sol...
virtual void FillCircle(const IColor &color, float cx, float cy, float r, const IBlend *pBlend=0)
Fill a circle with a color.
const IParam * GetParam(int valIdx=0) const
Get a const pointer to the IParam object (owned by the editor delegate class), associated with this c...
void AttachBackground(const char *fileName)
Attach an IBitmapControl as the lowest IControl in the control stack to be the background for the gra...
bool GetMouseDblAsSingleClick() const
Get double click as single click By default, mouse double click has its own handler.
void DisableControl(int paramIdx, bool diable)
Disable or enable controls linked to a specific parameter.
IPlug's parameter class.
void Translate(float x, float y)
Translate this rectangle.
const char * GetDisplayText(double value) const
Get the display text for a particular value.
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
void HideControl(int paramIdx, bool hide)
Hide controls linked to a specific parameter.
void OnMouseUp(const std::vector< IMouseInfo > &points)
Called when the platform class sends mouse up events.
void PixelAlign()
Pixel aligns the rect in an inclusive manner (moves all points outwards)
void SetControlPosition(int idx, float x, float y)
Reposition a control, redrawing the interface correctly.
virtual void DrawDottedLine(const IColor &color, float x1, float y1, float x2, float y2, const IBlend *pBlend=0, float thickness=1.f, float dashLen=2.f)
Draw a dotted line to the graphics context.
void RemoveControlWithTag(int ctrlTag)
Remove controls from the control list with a particular tag.
virtual void DrawRoundRect(const IColor &color, const IRECT &bounds, float cornerRadius=5.f, const IBlend *pBlend=0, float thickness=1.f)
Draw a rounded rectangle to the graphics context.
virtual void BeginInformHostOfParamChangeFromUI(int paramIdx)=0
Called by the UI at the beginning of a parameter change gesture, in order to notify the host (via a c...
void CalculateTextRotation(const IText &text, const IRECT &bounds, IRECT &rect, double &tx, double &ty) const
Used to manage color data, independent of draw class/platform.
void AttachPopupMenuControl(const IText &text=DEFAULT_TEXT, const IRECT &bounds=IRECT())
Attach a control for pop-up menus, to override platform style menus.
Used to describe a particular gesture.
IPlug's parameter class.
bool GetIgnoreMouse() const
int GetLastClickedParamForPTAutomation()
[AAX only]
void DrawText(const IText &text, const char *str, const IRECT &bounds, const IBlend *pBlend=0)
Draw some text to the graphics context in a specific rectangle.
virtual void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod &mod)
Implement this method to respond to a mouse drag event on this control.
Used to manage stroke behaviour for path based drawing back ends.
virtual void AttachGestureRecognizer(EGestureType type)
Registers a gesture recognizer with the graphics context.
bool RespondsToGesture(float x, float y)
Called by platform class to see if the point at x, y is linked to a gesture recognizer.
User-facing SVG abstraction that you use to manage SVG data ISVG doesn't actually own the image data...
void SetStrictDrawing(bool strict)
Enables strict drawing mode.
EResourceLocation SearchImageResource(const char *fileName, const char *type, WDL_String &result, int targetScale, int &sourceScale)
Search for a bitmap image resource matching the target scale.
void OnDrop(const char *str, float x, float y)
void SetScreenScale(float scale)
Called by the platform IGraphics class when moving to a new screen to set DPI.
virtual void Draw(IGraphics &g)=0
Draw the control to the graphics context.
void RemoveControls(int fromIdx)
Remove controls from the control list above a particular index, (frees memory).
int GetParamIdx(int valIdx=0) const
Get the index of a parameter that the control is linked to Normaly controls are either linked to a si...
This file contains the base IControl implementation, along with some base classes for specific types ...
void PushLayer(ILayer *pLayer)
Push a layer on to the stack.
A control to enable live modification of control layout in an IGraphics context in debug builds This ...
virtual int GetValIdxForPos(float x, float y) const
Check to see which of the control's values relates to this x and y coordinate.
void SetAllControlsDirty()
Calls SetDirty() on every control.
float R
Right side of the rectangle (X + W)
void Randomise(int alpha=255)
Randomise the color parts, with optional alpha.
void OnMouseDown(const std::vector< IMouseInfo > &points)
Called when the platform class sends mouse down events.
virtual bool IsHit(float x, float y) const
Hit test the control.
virtual void OnMouseUp(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouse up event on this control.
void PathTransformRestore()
Restore the affine transform of the current path, to the previously saved state.
bool OnKeyDown(float x, float y, const IKeyPress &key)
void SetTransform(float xx, float yx, float xy, float yy, float tx, float ty)
Set the affine transform for the IPattern with values.
void AttachGestureRecognizerToRegion(const IRECT &bounds, EGestureType type, IGestureFunc func)
Attach a gesture recognizer to a rectangular region of the GUI, i.e.
void RemoveControl(int idx)
Remove a control at a particular index, (frees memory).
void ForAllControlsFunc(std::function< void(IControl *pControl)> func)
For all controls, including the "special controls" call a method.
The lowest level base class of an IGraphics context.
IControl * GetControlWithTag(int ctrlTag) const
An editor delegate base class for a SOMETHING that uses IGraphics for it's UI.
virtual void OnTouchCancelled(float x, float y, const IMouseMod &mod)
Implement this method to respond to a touch cancel event on this control.
IRECT Intersect(const IRECT &rhs) const
Create a new IRECT that is the intersection of this IRECT and rhs.
const IRECT & GetRECT() const
Get the rectangular draw area for this control, within the graphics context.
void DoMeasureTextRotation(const IText &text, const IRECT &bounds, IRECT &rect) const
bool GetWantsMultiTouch() const
void CreatePopupMenu(IControl &control, IPopupMenu &menu, const IRECT &bounds, int valIdx=0)
Shows a pop up/contextual menu in relation to a rectangular region of the graphics context...
void EnableLiveEdit(bool enable)
Live edit mode allows you to relocate controls at runtime in debug builds.
virtual IBitmap LoadBitmap(const char *fileNameOrResID, int nStates=1, bool framesAreHorizontal=false, int targetScale=0)
Load a bitmap image from disk or from windows resource.
double StringToValue(const char *str) const
Convert a textual representation of the parameter value to a double (real value)
void PathEllipse(const IRECT &bounds)
Add an ellipse to the current path, specifying the rectangular region.
APIBitmap * SearchBitmapInCache(const char *fileName, int targetScale, int &sourceScale)
Search the static storage cache for a bitmap image resource matching the target scale.
void AttachSVGBackground(const char *fileName)
Attach an ISVGControl as the lowest IControl in the control stack to be the background for the graphi...
void RemovePopupMenuControl()
Remove the IGraphics popup menu, use platform popup menu if available.
void ForStandardControlsFunc(std::function< void(IControl *pControl)> func)
For all standard controls in the main control stack perform a function.
bool ConstrainEditorResize(int &w, int &h) const
Constrain the incoming editor width and height values based on the minimum and maximum.
ILayer * PopLayer()
Pop a layer off the stack.
void DrawRadialLine(const IColor &color, float cx, float cy, float angle, float rMin, float rMax, const IBlend *pBlend=0, float thickness=1.f)
Draw a radial line to the graphics context, useful for pointers on dials.
IText is used to manage font and text/text entry style for a piece of text on the UI...
virtual void DrawCircle(const IColor &color, float cx, float cy, float r, const IBlend *pBlend=0, float thickness=1.f)
Draw a circle to the graphics context.
bool CheckLayer(const ILayerPtr &layer)
Test to see if a layer needs drawing, for instance if the control's bounds were changed.
virtual void SendMidiMsgFromUI(const IMidiMsg &msg)
SendMidiMsgFromUI (Abbreviation: SMMFUI) This method should be used when sending a MIDI message from ...
bool OnKeyUp(float x, float y, const IKeyPress &key)
void StyleAllVectorControls(const IVStyle &style)
Helper method to style all of the controls which inherit IVectorBase.
bool OnMouseOver(float x, float y, const IMouseMod &mod)
virtual void DrawSVG(const ISVG &svg, const IRECT &bounds, const IBlend *pBlend=0)
Draw an SVG image to the graphics context.
Base class that contains plug-in info and state manipulation methods.
virtual bool IsDirty()
Called at each display refresh by the IGraphics draw loop, after IControl::Animate(), to determine if the control is marked as dirty.
void AssignParamNameToolTips()
Call this method in order to create tool tips for every IControl that show the associated parameter's...
void RemoveAllControls()
Removes all regular IControls from the control list, as well as special controls (frees memory)...
Used to group mouse coordinates with mouse modifier information.
void SetAllControlsClean()
Calls SetClean() on every control.
const char * GetGroup() const
Get the group that the control belongs to, if any.
void PathTransformSkew(float xAngle, float yAngle)
Apply a skew transform to the current path.
virtual void RetainBitmap(const IBitmap &bitmap, const char *cacheName)
Adds an IBitmap to the cache/static storage.
void Draw(IRECTList &rects)
Called by the platform class indicating a number of rectangles in the UI that need to redraw...
virtual WDL_TypedBuf< uint8_t > LoadResource(const char *fileNameOrResID, const char *fileType)
Load a resource from the file system, the bundle, or a Windows resource, and returns its data...
IBitmap GetScaledBitmap(IBitmap &inBitmap)
Get a version of the input bitmap from the cache that corresponds to the current screen scale For exa...
void OnGestureRecognized(const IGestureInfo &info)
Called by platform class when a gesture is recognized.
A collection of IControls for common UI widgets, such as knobs, sliders, switches.
void SetPTParameterHighlight(int paramIdx, bool isHighlighted, int color)
[AAX only] See AAX_CEffectGUI::SetControlHighlightInfo()
virtual void FillArc(const IColor &color, float cx, float cy, float r, float a1, float a2, const IBlend *pBlend=0)
Fill an arc segment with a color.
virtual void OnMouseWheel(float x, float y, const IMouseMod &mod, float d)
Implement this method to respond to a mouse wheel event on this control.
void PathClipRegion(const IRECT r=IRECT())
Clip the current path to a particular region.
void AttachImGui(std::function< void(IGraphics *)> drawFunc, std::function< void()> setupFunc=nullptr)
Set functions to draw DearImGui widgets on top of the IGraphics context (only relevant when IGRAPHICS...
void OnMouseWheel(float x, float y, const IMouseMod &mod, float delta)
virtual void ReleaseBitmap(const IBitmap &bitmap)
Releases an IBitmap from the cache/static storage.
void MakeNoteOffMsg(int noteNumber, int offset, int channel=0)
Make a Note Off message.
float GetDrawScale() const
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.
VST3 base class for a non-distributed IPlug VST3 plug-in.
const WDL_String & GetResourceName() const
bool OnMouseDblClick(float x, float y, const IMouseMod &mod)
void Draw(IGraphics &g) override
Draw the control to the graphics context.
The lowest level base class of an IGraphics context.
Used to specify properties of a drop-shadow to a layer.
void SearchNextScale(int &sourceScale, int targetScale)
Utility used by SearchImageResource/SearchBitmapInCache.
void PixelAlign()
Align the rectangles to pixel boundaries.
virtual void OnMouseOver(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouseover event on this control.
void PromptUserInput(IControl &control, const IRECT &bounds, int valIdx=0)
Prompt for user input either using a text entry or pop up menu.
void GetDisplay(WDL_String &display, bool withDisplayText=true) const
Get the current textual display for the current parameter value.
const char * GetLabel() const
Returns the parameter's label.
A control for resizing the plug-in window by clicking and dragging in the bottom right-hand corner Th...
void PathTransformScale(float x, float y)
Apply a scale transform to the current path, with independant x, y scales.
void UpdatePeers(IControl *pCaller, int callerValIdx)
This method is called after interacting with a control, so that any other controls linked to the same...
virtual void FillRoundRect(const IColor &color, const IRECT &bounds, float cornerRadius=5.f, const IBlend *pBlend=0)
Fill a rounded rectangle with a color.
void PathCircle(float cx, float cy, float r)
Add a circle to the current path.
virtual void FillRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0)
Fill a rectangular region of the graphics context with a color.
virtual void OnGUIIdle()
This is an idle timer tick call on the GUI thread, only active if USE_IDLE_CALLS is defined...
IRECT GetPixelAligned() const
Get a copy of this IRECT with PixelAlign() called.
void OnMouseOut()
Called when the mouse leaves the graphics context.
VST3 Controller API-base class for a distributed IPlug VST3 plug-in.
void Resize(int w, int h, float scale, bool needsPlatformResize=true)
virtual void EndInformHostOfParamChangeFromUI(int paramIdx)=0
Called by the user interface at the end of a parameter change gesture, in order to notify the host (v...
void OnTouchCancelled(const std::vector< IMouseInfo > &points)
Called when the platform class sends touch cancel events.
BEGIN_IPLUG_NAMESPACE T Clip(T x, T lo, T hi)
Clips the value x between lo and hi.
void ForControlWithParam(int paramIdx, std::function< void(IControl *pControl)> func)
For all standard controls in the main control stack that are linked to a specific parameter...
const IRECT & Bounds() const
virtual void FillEllipse(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0)
Fill an ellipse within a rectangular region of the graphics context.
void ClearGestureRegions()
Remove all gesture recognizers linked to regions.
virtual void DrawEllipse(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0, float thickness=1.f)
Draw an ellipse within a rectangular region of the graphics context.
void TransformPoint(double &x, double &y, double x0, double y0) const
Transforms the point x, y.
void DrawFittedLayer(const ILayerPtr &layer, const IRECT &bounds, const IBlend *pBlend)
Draw a layer to the main IGraphics context, fitting it to a rectangle that is different to the layer'...
A basic control to fill a rectangle with a color or gradient.
void PathTransformRotate(float angle)
Apply a rotation transform to the current path.
void SetTargetAndDrawRECTs(const IRECT &bounds)
Set BOTH the draw rect and the target area, within the graphics context for this control.
int GetParamIdxForPTAutomation(float x, float y)
[AAX only] This can be called by the ProTools API class (e.g.
void SetQwertyMidiKeyHandlerFunc(std::function< void(const IMidiMsg &msg)> func=nullptr)
A helper to set the IGraphics KeyHandlerFunc in order to make an instrument playable via QWERTY keys...
bool GetPromptShowsParamLabel() const
virtual void DrawTriangle(const IColor &color, float x1, float y1, float x2, float y2, float x3, float y3, const IBlend *pBlend=0, float thickness=1.f)
Draw a triangle to the graphics context.
virtual void DrawFittedBitmap(const IBitmap &bitmap, const IRECT &bounds, const IBlend *pBlend=0)
Draw a bitmap (raster) image to the graphics context, scaling the image to fit the bounds...
void ShowFPSDisplay(bool enable)
Shows a control to display the frame rate of drawing.
void SetControlBounds(int idx, const IRECT &r)
Set a controls target and draw rect to r, redrawing the interface correctly.
IRECT Union(const IRECT &rhs) const
Create a new IRECT that is a union of this IRECT and rhs.
void DrawLayer(const ILayerPtr &layer, const IBlend *pBlend=nullptr)
Draw a layer to the main IGraphics context.
void PathRoundRect(const IRECT &bounds, float ctl, float ctr, float cbl, float cbr)
Add a rounded rectangle to the current path, with independent corner roundness.
virtual IBitmap ScaleBitmap(const IBitmap &inBitmap, const char *cacheName, int targetScale)
Returns a new IBitmap, an integer scaled version of the input, and adds it to the cache...
virtual void DrawPTHighlight(IGraphics &g)
Implement this to customise how a colored highlight is drawn on the control in ProTools (AAX format o...
virtual ISVG LoadSVG(const char *fileNameOrResID, const char *units="px", float dpi=72.f)
Load an SVG from disk or from windows resource.
bool GetMouseOverWhenDisabled() const
virtual void DrawBitmap(const IBitmap &bitmap, const IRECT &bounds, int srcX, int srcY, const IBlend *pBlend=0)=0
Draw a bitmap (raster) image to the graphics context.
double ToNormalized(double nonNormalizedValue) const
Convert a real value to normalized value for this parameter.
void DrawHorizontalLine(const IColor &color, const IRECT &bounds, float y, const IBlend *pBlend=0, float thickness=1.f)
Draw a horizontal line, within a rectangular region of the graphics context.
A special control to draw contextual info as a slider etc is moved If used in the main IControl stack...
virtual bool OnGesture(const IGestureInfo &info)
A base class interface for a bitmap abstraction around the different drawing back end bitmap represen...
void ForControlInGroup(const char *group, std::function< void(IControl *pControl)> func)
For all standard controls in the main control stack that are linked to a group, execute a function...
double GetValue(int valIdx=0) const
Get the control's value.
IControl * AttachGestureRecognizer(EGestureType type, IGestureFunc func)
Add a IGestureFunc that should be triggered in response to a certain type of gesture.
EParamType Type() const
Get the parameter's type.
void AttachBubbleControl(const IText &text=DEFAULT_TEXT)
Attach the default control to show text as a control changes.
float GetDrawScale() const
float L
Left side of the rectangle (X)
virtual void DrawRotatedBitmap(const IBitmap &bitmap, float destCentreX, float destCentreY, double angle, const IBlend *pBlend=0)
Draw a bitmap (raster) image to the graphics context with rotation.
virtual void SetStyle(const IVStyle &style)
Set the Style of this IVControl.
ILayerPtr EndLayer()
End an IGraphics layer.
virtual void SetPosition(float x, float y)
Set the position of the control, preserving the width and height.
void SetGroup(const char *groupName)
Assign the control to a control group.
void PathTransformReset(bool clearStates=false)
Reset the affine transform of the current path, to the default state.
void OnDragResize(float x, float y)
Called by ICornerResizerControl as the corner is dragged to resize.
void DrawBitmapedText(const IBitmap &bitmap, const IRECT &bounds, IText &text, IBlend *pBlend, const char *str, bool vCenter=true, bool multiline=false, int charWidth=6, int charHeight=12, int charOffset=0)
Draws mono spaced bitmap text.
bool IsDirty(IRECTList &rects)
Called repeatedly at frame rate by the platform class to check what the graphics context says is dirt...
A special control to draw contextual info as a slider etc is moved If used in the main IControl stack...
void DrawVerticalLine(const IColor &color, const IRECT &bounds, float x, const IBlend *pBlend=0, float thickness=1.f)
Draw a vertical line, within a rectangular region of the graphics context.
virtual void OnRescale()
Implement to do something when graphics is scaled globally (e.g.
virtual void OnMouseDblClick(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouse double click event on this control.
IControl * AttachControl(IControl *pControl, int ctrlTag=kNoTag, const char *group="")
Attach an IControl to the graphics context and add it to the top of the control stack.
void AddStop(IColor color, float offset)
Add an IColorStop to the IPattern.
void PathRadialLine(float cx, float cy, float angle, float rMin, float rMax)
Add a radial line to the current path.
IRECT GetPadded(float padding) const
Get a copy of this IRECT with each value padded by padding N.B.
void SetDelegate(IGEditorDelegate &dlg)
Used internally to set the mDelegate (and mGraphics) variables.
virtual bool OnKeyDown(float x, float y, const IKeyPress &key)
Implement this method to respond to a key down event on this control.
void ForMatchingControls(T method, int paramIdx, Args...args)
For all standard controls in the main control stack that are linked to a specific parameter...
virtual void CreateContextMenu(IPopupMenu &contextMenu)
Called by default when the user right clicks a control.
void MakeNoteOnMsg(int noteNumber, int velocity, int offset, int channel=0)
Make a Note On message.
EParamType
Defines types or parameter.
bool GetWantsGestures() const
APIBitmap * GetAPIBitmap() const
A base interface to be combined with IControl for vectorial controls "IVControls", in order for them to share a common style If you need more flexibility, you're on your own!
virtual void DrawRotatedSVG(const ISVG &svg, float destCentreX, float destCentreY, float width, float height, double angle, const IBlend *pBlend=0)
Draw an SVG image to the graphics context with rotation.
virtual void DrawArc(const IColor &color, float cx, float cy, float r, float a1, float a2, const IBlend *pBlend=0, float thickness=1.f)
Draw an arc to the graphics context.
IMatrix & Rotate(float a)
Set the matrix for a rotation transform.
virtual void FillConvexPolygon(const IColor &color, float *x, float *y, int nPoints, const IBlend *pBlend=0)
Fill a convex polygon with a color.
void Add(const IRECT &rect)
Add a rectangle to the list.
std::unique_ptr< ILayer > ILayerPtr
ILayerPtr is a managed pointer for transferring the ownership of layers.
void SetControlValueAfterPopupMenu(IPopupMenu *pMenu)
Called by PopupMenuControl in order to update a control with a new value after returning from the non...
Performance display meter, based on code from NanoVG This is a special control that lives outside the...
virtual void DrawLine(const IColor &color, float x1, float y1, float x2, float y2, const IBlend *pBlend=0, float thickness=1.f)
Draw a line to the graphics context.
Used to store pattern information for gradients.
A basic control to draw an SVG image to the screen.
virtual bool LoadFont(const char *fontID, const char *fileNameOrResID)
Load a font to be used by the graphics context.
Used to store transformation matrices.
virtual void OnDrop(const char *str)
Implement to do something when something was drag 'n dropped onto this control.
Used for key press info, such as ASCII representation, virtual key (mapped to win32 codes) and modifi...
bool GetFramesAreHorizontal() const
virtual void SetSize(float w, float h)
Set the size of the control, preserving the current position.
float T
Top of the rectangle (Y)
virtual void FillTriangle(const IColor &color, float x1, float y1, float x2, float y2, float x3, float y3, const IBlend *pBlend=0)
Fill a triangle with a color.
A struct encapsulating a set of properties used to configure IVControls.
virtual float MeasureText(const IText &text, const char *str, IRECT &bounds) const
Measure the rectangular region that some text will occupy.
virtual void SetDirty(bool triggerAction=true, int valIdx=kNoValIdx)
Mark the control as dirty, i.e.
virtual void SetDisabled(bool disable)
Sets disabled mode for the control, the default implementation modifies the mBlend member...
A control for resizing the plug-in window by clicking and dragging in the bottom right-hand corner Th...
const IText & GetText() const
Get the Text object for the control.
void PathTriangle(float x1, float y1, float x2, float y2, float x3, float y3)
Add a triangle to the current path.
float B
Bottom of the rectangle (Y + H)
An abstraction that is used to store a temporary raster image/framebuffer.
virtual void OnMouseOut()
Implement this method to respond to a mouseout event on this control.