Add keyboard support for iOS and macOS under MoltenVK.
This commit is contained in:
parent
626ab5803f
commit
6ba784053b
7 changed files with 134 additions and 40 deletions
|
|
@ -53,12 +53,38 @@
|
|||
#define KEY_O 0xF
|
||||
#define KEY_T 0x10
|
||||
|
||||
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
|
||||
#define KEY_ESCAPE 0x35
|
||||
#define KEY_F1 0x7A
|
||||
#define KEY_F2 0x78
|
||||
#define KEY_F3 0x63
|
||||
#define KEY_F4 0x76
|
||||
#elif defined(VK_USE_PLATFORM_IOS_MVK)
|
||||
// Use numeric keys instead of function keys.
|
||||
// Use Delete key instead of Escape key.
|
||||
#define KEY_ESCAPE 0x33
|
||||
#define KEY_F1 '1'
|
||||
#define KEY_F2 '2'
|
||||
#define KEY_F3 '3'
|
||||
#define KEY_F4 '4'
|
||||
#define KEY_W 'w'
|
||||
#define KEY_A 'a'
|
||||
#define KEY_S 's'
|
||||
#define KEY_D 'd'
|
||||
#define KEY_P 'p'
|
||||
#define KEY_SPACE ' '
|
||||
#define KEY_KPADD '+'
|
||||
#define KEY_KPSUB '-'
|
||||
#define KEY_B 'b'
|
||||
#define KEY_F 'f'
|
||||
#define KEY_L 'l'
|
||||
#define KEY_N 'n'
|
||||
#define KEY_O 'o'
|
||||
#define KEY_T 't'
|
||||
|
||||
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
|
||||
// For iOS UX compatibility:
|
||||
// - Use numeric keys instead of function keys
|
||||
// - Use Delete key instead of Escape key
|
||||
#define KEY_ESCAPE 0x33
|
||||
#define KEY_F1 0x12
|
||||
#define KEY_F2 0x13
|
||||
#define KEY_F3 0x14
|
||||
#define KEY_F4 0x15
|
||||
#define KEY_W 0x0D
|
||||
#define KEY_A 0x00
|
||||
#define KEY_S 0x01
|
||||
|
|
|
|||
|
|
@ -62,3 +62,10 @@ in this repository on either *iOS* or *macOS*. To do so, follow these instructio
|
|||
3. Run either the `examples-iOS` or `examples-macOS` *Xcode Scheme* to run the example in *iOS*
|
||||
or *macOS*, repectively.
|
||||
|
||||
4. Many of the examples include an option to press keys to control the display of features
|
||||
and scene components:
|
||||
|
||||
- On *iOS*, tap on the scene to display the keyboard. Tap again on the scene to hide the keyboard.
|
||||
- On both *iOS* and *macOS*, use the numeric keys (*1, 2, 3...*) instead of function keys (*F1, F2, F3...*).
|
||||
- On both *iOS* and *macOS*, use the *delete* key instead of the *escape* key.
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
*
|
||||
* For example, to run the pipelines example, you would add the MVK_pipelines define macro
|
||||
* to the Preprocessor Macros (aka GCC_PREPROCESSOR_DEFINITIONS) entry of the Xcode project,
|
||||
* overwriting any other value there.
|
||||
* overwriting any otheor value there.
|
||||
*
|
||||
* If you choose to add a #define statement to this file, be sure to clear the existing macro
|
||||
* from the Preprocessor Macros (aka GCC_PREPROCESSOR_DEFINITIONS) compiler setting in Xcode.
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
# include "../pipelines/pipelines.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_texture // inverse() function not available in MSL
|
||||
#ifdef MVK_texture
|
||||
# include "../texture/texture.cpp"
|
||||
#endif
|
||||
|
||||
|
|
@ -64,19 +64,19 @@
|
|||
# include "../specializationconstants/specializationconstants.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_offscreen
|
||||
#ifdef MVK_offscreen // Bad access on iOS
|
||||
# include "../offscreen/offscreen.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_radialblur // Runs but textureSize() function not available in MSL
|
||||
#ifdef MVK_radialblur
|
||||
# include "../radialblur/radialblur.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_textoverlay // inverse() function not available in MSL
|
||||
#ifdef MVK_textoverlay
|
||||
# include "../textoverlay/textoverlay.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_particlefire // Runs but inversesqrt() function not available in MSL
|
||||
#ifdef MVK_particlefire
|
||||
# include "../particlefire/particlefire.cpp"
|
||||
#endif
|
||||
|
||||
|
|
@ -87,11 +87,11 @@
|
|||
# include "../multithreading/multithreading.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_scenerendering
|
||||
#ifdef MVK_scenerendering // Bad access on macOS
|
||||
# include "../scenerendering/scenerendering.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_instancing // inverse() function not available in MSL
|
||||
#ifdef MVK_instancing
|
||||
# include "../instancing/instancing.cpp"
|
||||
#endif
|
||||
|
||||
|
|
@ -107,31 +107,31 @@
|
|||
# include "../occlusionquery/occlusionquery.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_texturemipmapgen // inverse() function not available in MSL + SPIRV->MSL conversion error
|
||||
#ifdef MVK_texturemipmapgen // SPIRV->GLSL conversion error
|
||||
# include "../texturemipmapgen/texturemipmapgen.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_multisampling
|
||||
#ifdef MVK_multisampling // Multisampling too low on iOS
|
||||
# include "../multisampling/multisampling.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_shadowmapping // textureSize() function not available in MSL
|
||||
#ifdef MVK_shadowmapping // Bad access on iOS
|
||||
# include "../shadowmapping/shadowmapping.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_shadowmappingomni
|
||||
#ifdef MVK_shadowmappingomni // Bad access on iOS
|
||||
# include "../shadowmappingomni/shadowmappingomni.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_skeletalanimation // inverse() function not available in MSL
|
||||
#ifdef MVK_skeletalanimation // Bad access on macOS
|
||||
# include "../skeletalanimation/skeletalanimation.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_bloom // Runs but textureSize() function not available in MSL
|
||||
#ifdef MVK_bloom // Bad access on iOS
|
||||
# include "../bloom/bloom.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_deferred // inverse() function not available in MSL
|
||||
#ifdef MVK_deferred // buffer overload
|
||||
# include "../deferred/deferred.cpp"
|
||||
#endif
|
||||
|
||||
|
|
@ -170,7 +170,7 @@
|
|||
# include "../gears/gears.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef MVK_distancefieldfonts
|
||||
#ifdef MVK_distancefieldfonts // Endless loop during loading on macOS
|
||||
# include "../distancefieldfonts/distancefieldfonts.cpp"
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -348,6 +348,9 @@
|
|||
attributes = {
|
||||
LastUpgradeCheck = 0820;
|
||||
TargetAttributes = {
|
||||
1D6058900D05DD3D006BFB54 = {
|
||||
DevelopmentTeam = VU3TCKU48B;
|
||||
};
|
||||
A977BCBD1B66BB010067E5BF = {
|
||||
DevelopmentTeam = VU3TCKU48B;
|
||||
};
|
||||
|
|
@ -434,7 +437,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = VU3TCKU48B;
|
||||
FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/iOS\"";
|
||||
GCC_PREFIX_HEADER = "$(SRCROOT)/iOS/Prefix.pch";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
|
@ -457,7 +460,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = VU3TCKU48B;
|
||||
FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/iOS\"";
|
||||
GCC_PREFIX_HEADER = "$(SRCROOT)/iOS/Prefix.pch";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
|
@ -531,7 +534,7 @@
|
|||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = MVK_vulkanscene;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = MVK_skeletalanimation;
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
|
|
@ -555,7 +558,7 @@
|
|||
ENABLE_BITCODE = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = MVK_vulkanscene;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = MVK_skeletalanimation;
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#pragma mark DemoViewController
|
||||
|
||||
/** The main view controller for the demo storyboard. */
|
||||
@interface DemoViewController : UIViewController
|
||||
@interface DemoViewController : UIViewController <UIKeyInput>
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,15 @@ const std::string VulkanExampleBase::getAssetPath() {
|
|||
@implementation DemoViewController {
|
||||
VulkanExample* _vulkanExample;
|
||||
CADisplayLink* _displayLink;
|
||||
BOOL _viewHasAppeared;
|
||||
}
|
||||
|
||||
/** Since this is a single-view app, init Vulkan when the view is loaded. */
|
||||
-(void) viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
|
||||
|
||||
_vulkanExample = new VulkanExample();
|
||||
_vulkanExample->initVulkan();
|
||||
_vulkanExample->setupWindow(self.view);
|
||||
|
|
@ -37,8 +40,24 @@ const std::string VulkanExampleBase::getAssetPath() {
|
|||
_displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderFrame)];
|
||||
[_displayLink setFrameInterval: 60 / fps];
|
||||
[_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode];
|
||||
|
||||
// Setup tap gesture to toggle virtual keyboard
|
||||
UITapGestureRecognizer* tapSelector = [[UITapGestureRecognizer alloc]
|
||||
initWithTarget: self action: @selector(handleTapGesture:)];
|
||||
tapSelector.numberOfTapsRequired = 1;
|
||||
tapSelector.cancelsTouchesInView = YES;
|
||||
[self.view addGestureRecognizer: tapSelector];
|
||||
|
||||
_viewHasAppeared = NO;
|
||||
}
|
||||
|
||||
-(void) viewDidAppear: (BOOL) animated {
|
||||
[super viewDidAppear: animated];
|
||||
_viewHasAppeared = YES;
|
||||
}
|
||||
|
||||
-(BOOL) canBecomeFirstResponder { return _viewHasAppeared; }
|
||||
|
||||
-(void) renderFrame {
|
||||
_vulkanExample->renderFrame();
|
||||
}
|
||||
|
|
@ -48,6 +67,45 @@ const std::string VulkanExampleBase::getAssetPath() {
|
|||
[super dealloc];
|
||||
}
|
||||
|
||||
// Toggle the display of the virtual keyboard
|
||||
-(void) toggleKeyboard {
|
||||
if (self.isFirstResponder) {
|
||||
[self resignFirstResponder];
|
||||
} else {
|
||||
[self becomeFirstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
// Display and hide the keyboard by tapping on the view
|
||||
-(void) handleTapGesture: (UITapGestureRecognizer*) gestureRecognizer {
|
||||
if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
|
||||
[self toggleKeyboard];
|
||||
}
|
||||
}
|
||||
|
||||
// Handle keyboard input
|
||||
-(void) handleKeyboardInput: (unichar) keycode {
|
||||
_vulkanExample->keyPressed(keycode);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark UIKeyInput methods
|
||||
|
||||
// Returns whether text is available
|
||||
-(BOOL) hasText { return YES; }
|
||||
|
||||
// A key on the keyboard has been pressed.
|
||||
-(void) insertText: (NSString*) text {
|
||||
unichar keycode = (text.length > 0) ? [text characterAtIndex: 0] : 0;
|
||||
[self handleKeyboardInput: keycode];
|
||||
}
|
||||
|
||||
// The delete backward key has been pressed.
|
||||
-(void) deleteBackward {
|
||||
[self handleKeyboardInput: 0x33];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,24 +52,17 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink,
|
|||
CVDisplayLinkStart(_displayLink);
|
||||
}
|
||||
|
||||
/** Resize the window to fit the size of the content as set by the sample code. */
|
||||
-(void) viewWillAppear {
|
||||
[super viewWillAppear];
|
||||
|
||||
CGSize vSz = self.view.bounds.size;
|
||||
NSWindow *window = self.view.window;
|
||||
NSRect wFrm = [window contentRectForFrameRect: window.frame];
|
||||
NSRect newWFrm = [window frameRectForContentRect: NSMakeRect(wFrm.origin.x, wFrm.origin.y, vSz.width, vSz.height)];
|
||||
[window setFrame: newWFrm display: YES animate: window.isVisible];
|
||||
[window center];
|
||||
}
|
||||
|
||||
-(void) dealloc {
|
||||
CVDisplayLinkRelease(_displayLink);
|
||||
delete(_vulkanExample);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
// Handle keyboard input
|
||||
-(void) keyDown:(NSEvent*) theEvent {
|
||||
_vulkanExample->keyPressed(theEvent.keyCode);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
@ -85,6 +78,13 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink,
|
|||
+(Class) layerClass { return [CAMetalLayer class]; }
|
||||
|
||||
/** If the wantsLayer property is set to YES, this method will be invoked to return a layer instance. */
|
||||
-(CALayer*) makeBackingLayer { return [self.class.layerClass layer]; }
|
||||
-(CALayer*) makeBackingLayer {
|
||||
CALayer* layer = [self.class.layerClass layer];
|
||||
CGSize viewScale = [self convertSizeToBacking: CGSizeMake(1.0, 1.0)];
|
||||
layer.contentsScale = MIN(viewScale.width, viewScale.height);
|
||||
return layer;
|
||||
}
|
||||
|
||||
-(BOOL) acceptsFirstResponder { return YES; }
|
||||
|
||||
@end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue