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