iPlug2 - C++ Audio Plug-in Framework
IGraphicsIOS.mm
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 #import <QuartzCore/QuartzCore.h>
12 #import <MetalKit/MetalKit.h>
13 
14 #include "IGraphicsIOS.h"
15 #include "IGraphicsCoreText.h"
16 
17 #import "IGraphicsIOS_view.h"
18 
19 #include <map>
20 #include <string>
21 
22 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
23 
24 BEGIN_IPLUG_NAMESPACE
25 BEGIN_IGRAPHICS_NAMESPACE
26 
27 void GetScreenDimensions(int& width, int& height)
28 {
29  CGRect bounds = [[UIScreen mainScreen] bounds];
30  width = bounds.size.width;
31  height = bounds.size.height;
32 }
33 
34 float GetScaleForScreen(int plugWidth, int plugHeight)
35 {
36  int width, height;
37  GetScreenDimensions(width, height);
38  return std::min((float) width / (float) plugWidth, (float) height / (float) plugHeight);
39 }
40 
41 END_IGRAPHICS_NAMESPACE
42 END_IPLUG_NAMESPACE
43 
44 using namespace iplug;
45 using namespace igraphics;
46 
47 StaticStorage<CoreTextFontDescriptor> sFontDescriptorCache;
48 
49 #pragma mark -
50 
51 std::map<std::string, MTLTexturePtr> gTextureMap;
52 NSArray<id<MTLTexture>>* gTextures;
53 
54 IGraphicsIOS::IGraphicsIOS(IGEditorDelegate& dlg, int w, int h, int fps, float scale)
55 : IGRAPHICS_DRAW_CLASS(dlg, w, h, fps, scale)
56 {
57 
58 #if defined IGRAPHICS_METAL && !defined IGRAPHICS_SKIA
59  if(!gTextureMap.size())
60  {
61  NSBundle* pBundle = [NSBundle mainBundle];
62 
63  if(IsAuv3AppExtension())
64  pBundle = [NSBundle bundleWithPath: [[[pBundle bundlePath] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]];
65 
66  NSArray<NSURL*>* pTextureFiles = [pBundle URLsForResourcesWithExtension:@"ktx" subdirectory:@""];
67 
68  if ([pTextureFiles count])
69  {
70  MTKTextureLoader* textureLoader = [[MTKTextureLoader alloc] initWithDevice:MTLCreateSystemDefaultDevice()];
71 
72  NSError* pError = nil;
73  NSDictionary* textureOptions = @{ MTKTextureLoaderOptionSRGB: [NSNumber numberWithBool:NO] };
74 
75  gTextures = [textureLoader newTexturesWithContentsOfURLs:pTextureFiles options:textureOptions error:&pError];
76 
77  for(int i=0; i < gTextures.count; i++)
78  {
79  gTextureMap.insert(std::make_pair([[[pTextureFiles[i] lastPathComponent] stringByDeletingPathExtension] cStringUsingEncoding:NSUTF8StringEncoding], (MTLTexturePtr) gTextures[i]));
80  }
81 
82  DBGMSG("Preloaded %i textures\n", (int) [pTextureFiles count]);
83 
84  [textureLoader release];
85  textureLoader = nil;
86  }
87  }
88 #endif
89 }
90 
91 IGraphicsIOS::~IGraphicsIOS()
92 {
93  CloseWindow();
94 }
95 
96 void* IGraphicsIOS::OpenWindow(void* pParent)
97 {
98  TRACE
99  CloseWindow();
100  IGRAPHICS_VIEW* view = [[IGRAPHICS_VIEW alloc] initWithIGraphics: this];
101  mView = (void*) view;
102 
103  OnViewInitialized((void*) [view metalLayer]);
104 
105  SetScreenScale([UIScreen mainScreen].scale);
106 
107  GetDelegate()->LayoutUI(this);
108  GetDelegate()->OnUIOpen();
109 
110  [view setMultipleTouchEnabled:MultiTouchEnabled()];
111 
112  if (pParent)
113  {
114  [(UIView*) pParent addSubview: view];
115  }
116 
117  return mView;
118 }
119 
120 void IGraphicsIOS::CloseWindow()
121 {
122  if (mView)
123  {
124 #ifdef IGRAPHICS_IMGUI
125  if(mImGuiView)
126  {
127  IGRAPHICS_IMGUIVIEW* pImGuiView = (IGRAPHICS_IMGUIVIEW*) mImGuiView;
128  [pImGuiView removeFromSuperview];
129  [pImGuiView release];
130  mImGuiView = nullptr;
131  }
132 #endif
133 
134  IGRAPHICS_VIEW* pView = (IGRAPHICS_VIEW*) mView;
135  [pView removeFromSuperview];
136  [pView release];
137  mView = nullptr;
138 
139  OnViewDestroyed();
140  }
141 }
142 
143 bool IGraphicsIOS::WindowIsOpen()
144 {
145  return mView;
146 }
147 
148 void IGraphicsIOS::PlatformResize(bool parentHasResized)
149 {
150  if (mView)
151  {
152  CGRect r = CGRectMake(0., 0., static_cast<CGFloat>(WindowWidth()), static_cast<CGFloat>(WindowHeight()));
153  [(IGRAPHICS_VIEW*) mView setFrame: r ];
154  }
155 }
156 
157 void IGraphicsIOS::AttachPlatformView(const IRECT& r, void* pView)
158 {
159  IGRAPHICS_VIEW* pMainView = (IGRAPHICS_VIEW*) mView;
160 
161  UIView* pNewSubView = (UIView*) pView;
162  [pNewSubView setFrame:ToCGRect(this, r)];
163 
164  [pMainView addSubview:pNewSubView];
165 }
166 
167 void IGraphicsIOS::RemovePlatformView(void* pView)
168 {
169  [(UIView*) pView removeFromSuperview];
170 }
171 
172 EMsgBoxResult IGraphicsIOS::ShowMessageBox(const char* str, const char* caption, EMsgBoxType type, IMsgBoxCompletionHanderFunc completionHandler)
173 {
174  ReleaseMouseCapture();
175  [(IGRAPHICS_VIEW*) mView showMessageBox:str :caption :type :completionHandler];
176  return EMsgBoxResult::kNoResult; // we need to rely on completionHandler
177 }
178 
179 void IGraphicsIOS::AttachGestureRecognizer(EGestureType type)
180 {
182  [(IGRAPHICS_VIEW*) mView attachGestureRecognizer:type];
183 }
184 
185 void IGraphicsIOS::ForceEndUserEdit()
186 {
187  if (mView)
188  {
189  [(IGRAPHICS_VIEW*) mView endUserInput];
190  }
191 }
192 
193 const char* IGraphicsIOS::GetPlatformAPIStr()
194 {
195  return "iOS";
196 }
197 
198 void IGraphicsIOS::GetMouseLocation(float& x, float&y) const
199 {
200  [(IGRAPHICS_VIEW*) mView getLastTouchLocation: x : y];
201 }
202 
203 void IGraphicsIOS::PromptForFile(WDL_String& fileName, WDL_String& path, EFileAction action, const char* ext)
204 {
205 }
206 
207 void IGraphicsIOS::PromptForDirectory(WDL_String& dir)
208 {
209 }
210 
211 bool IGraphicsIOS::PromptForColor(IColor& color, const char* str, IColorPickerHandlerFunc func)
212 {
213  [(IGRAPHICS_VIEW*) mView promptForColor: color: str: func];
214  return false;
215 }
216 
217 IPopupMenu* IGraphicsIOS::CreatePlatformPopupMenu(IPopupMenu& menu, const IRECT& bounds, bool& isAsync)
218 {
219  IPopupMenu* pReturnMenu = nullptr;
220  isAsync = true;
221  if (mView)
222  {
223  CGRect areaRect = ToCGRect(this, bounds);
224  pReturnMenu = [(IGRAPHICS_VIEW*) mView createPopupMenu: menu: areaRect];
225  }
226 
227  //synchronous
228  if(pReturnMenu && pReturnMenu->GetFunction())
229  pReturnMenu->ExecFunction();
230 
231  return pReturnMenu;
232 }
233 
234 void IGraphicsIOS::CreatePlatformTextEntry(int paramIdx, const IText& text, const IRECT& bounds, int length, const char* str)
235 {
236  ReleaseMouseCapture();
237  CGRect areaRect = ToCGRect(this, bounds);
238  [(IGRAPHICS_VIEW*) mView createTextEntry: paramIdx : text: str: length: areaRect];
239 }
240 
241 bool IGraphicsIOS::OpenURL(const char* url, const char* msgWindowTitle, const char* confirmMsg, const char* errMsgOnFailure)
242 {
243  NSURL* pNSURL = nullptr;
244  if (strstr(url, "http"))
245  pNSURL = [NSURL URLWithString:[NSString stringWithCString:url encoding:NSUTF8StringEncoding]];
246  else
247  pNSURL = [NSURL fileURLWithPath:[NSString stringWithCString:url encoding:NSUTF8StringEncoding]];
248 
249  if (pNSURL)
250  {
251  UIResponder* pResponder = (UIResponder*) mView;
252  while(pResponder) {
253  if ([pResponder respondsToSelector: @selector(openURL:)])
254  [pResponder performSelector: @selector(openURL:) withObject: pNSURL];
255 
256  pResponder = [pResponder nextResponder];
257  }
258  return true;
259  }
260  return false;
261 }
262 
263 void* IGraphicsIOS::GetWindow()
264 {
265  if (mView)
266  return mView;
267  else
268  return 0;
269 }
270 
271 // static
272 int IGraphicsIOS::GetUserOSVersion()
273 {
274  return (int) 0; //TODO
275 }
276 
277 bool IGraphicsIOS::GetTextFromClipboard(WDL_String& str)
278 {
279  return false;
280 }
281 
282 bool IGraphicsIOS::SetTextInClipboard(const char* str)
283 {
284  return false;
285 }
286 
287 void IGraphicsIOS::CreatePlatformImGui()
288 {
289 #ifdef IGRAPHICS_IMGUI
290  if(mView)
291  {
292  IGRAPHICS_VIEW* pView = (IGRAPHICS_VIEW*) mView;
293 
294  IGRAPHICS_IMGUIVIEW* pImGuiView = [[IGRAPHICS_IMGUIVIEW alloc] initWithIGraphicsView:pView];
295  [pView addSubview: pImGuiView];
296  mImGuiView = pImGuiView;
297  }
298 #endif
299 }
300 
301 PlatformFontPtr IGraphicsIOS::LoadPlatformFont(const char* fontID, const char* fileNameOrResID)
302 {
303  return CoreTextHelpers::LoadPlatformFont(fontID, fileNameOrResID, GetBundleID());
304 }
305 
306 PlatformFontPtr IGraphicsIOS::LoadPlatformFont(const char* fontID, const char* fontName, ETextStyle style)
307 {
308  return CoreTextHelpers::LoadPlatformFont(fontID, fontName, style);
309 }
310 
311 PlatformFontPtr IGraphicsIOS::LoadPlatformFont(const char* fontID, void* pData, int dataSize)
312 {
313  return CoreTextHelpers::LoadPlatformFont(fontID, pData, dataSize);
314 }
315 
316 void IGraphicsIOS::CachePlatformFont(const char* fontID, const PlatformFontPtr& font)
317 {
318  CoreTextHelpers::CachePlatformFont(fontID, font, sFontDescriptorCache);
319 }
320 
321 void IGraphicsIOS::LaunchBluetoothMidiDialog(float x, float y)
322 {
323  ReleaseMouseCapture();
324  NSDictionary* dic = @{@"x": @(x), @"y": @(y)};
325  [[NSNotificationCenter defaultCenter] postNotificationName:@"LaunchBTMidiDialog" object:nil userInfo:dic];
326 }
327 
328 #if defined IGRAPHICS_NANOVG
329  #include "IGraphicsNanoVG.cpp"
330 #elif defined IGRAPHICS_SKIA
331  #include "IGraphicsSkia.cpp"
332 #else
333  #error Either NO_IGRAPHICS or one and only one choice of graphics library must be defined!
334 #endif
Used to manage a rectangular area, independent of draw class/platform.
Used to manage color data, independent of draw class/platform.
virtual void AttachGestureRecognizer(EGestureType type)
Registers a gesture recognizer with the graphics context.
Definition: IGraphics.cpp:2355
An editor delegate base class for a SOMETHING that uses IGraphics for it&#39;s UI.
A class for setting the contents of a pop up menu.
IText is used to manage font and text/text entry style for a piece of text on the UI...