235 lines
5.2 KiB
Plaintext
235 lines
5.2 KiB
Plaintext
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#import "OpenVulkanoView.h"
|
|
|
|
#include "Input/Touch/InputDeviceTouch.hpp"
|
|
#include "Input/InputManager.hpp"
|
|
#include "MetalViewWindow.h"
|
|
#include <map>
|
|
|
|
#import <MetalKit/MTKView.h>
|
|
|
|
using namespace OpenVulkano;
|
|
|
|
#pragma mark MetalViewDelegate
|
|
@interface MetalViewDelegate : NSObject<MTKViewDelegate>
|
|
- (void) mtkView:(MTKView *) view drawableSizeWillChange:(CGSize) size;
|
|
- (void) drawInMTKView:(MTKView *) view;
|
|
@end
|
|
|
|
@implementation MetalViewDelegate
|
|
{
|
|
MetalViewWindow* window;
|
|
}
|
|
|
|
- (id)initWithWindow:(MetalViewWindow*)win
|
|
{
|
|
window = win;
|
|
return self;
|
|
}
|
|
|
|
- (void) mtkView:(MTKView *) view drawableSizeWillChange:(CGSize) size
|
|
{
|
|
window->OnResize(size.width, size.height);
|
|
}
|
|
|
|
- (void) drawInMTKView:(MTKView *) view
|
|
{
|
|
@autoreleasepool {
|
|
window->TickHandler();
|
|
}
|
|
}
|
|
@end
|
|
|
|
#pragma mark -
|
|
#pragma mark OpenVulkanoView
|
|
|
|
@interface OpenVulkanoView()
|
|
{
|
|
CADisplayLink* m_displayLink;
|
|
MetalViewDelegate* m_mtdelegate;
|
|
std::map<UITouch*, int32_t> m_touchToIdMap;
|
|
Input::InputDeviceTouch m_touchDevice;
|
|
MetalViewWindow m_window;
|
|
}
|
|
@end
|
|
|
|
#pragma mark OpenVulkanoView Implementation
|
|
@implementation OpenVulkanoView
|
|
/** Returns a Metal-compatible layer. */
|
|
+(Class) layerClass { return [CAMetalLayer class]; }
|
|
|
|
- (id)initWithFrame:(CGRect)frame {
|
|
self = [super initWithFrame:frame];
|
|
if (self) {
|
|
[self commonInit];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (id)initWithCoder:(NSCoder *)aDecoder {
|
|
self = [super initWithCoder:aDecoder];
|
|
if (self) {
|
|
[self commonInit];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)commonInit {
|
|
[self setMultipleTouchEnabled:YES];
|
|
|
|
self.contentScaleFactor = UIScreen.mainScreen.nativeScale / 1.5f;
|
|
|
|
auto size = self.bounds.size;
|
|
auto sizeX = size.width * self.contentScaleFactor;
|
|
auto sizeY = size.height * self.contentScaleFactor;
|
|
m_window.Init(self.layer, {sizeX, sizeY});
|
|
|
|
m_touchDevice.Init(); //TODO link window
|
|
Input::InputManager::GetInstance()->RegisterInputDevice(&m_touchDevice);
|
|
|
|
if ([self isKindOfClass:[MTKView class]]) {
|
|
MTKView* mtkView = (MTKView*)(self);
|
|
m_mtdelegate = [[MetalViewDelegate alloc] initWithWindow:&m_window];
|
|
[mtkView setDelegate:m_mtdelegate];
|
|
mtkView.preferredFramesPerSecond = 60;
|
|
} else {
|
|
m_displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderLoop)];
|
|
[m_displayLink setPreferredFramesPerSecond: 60];
|
|
[m_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode];
|
|
m_displayLink.paused = YES;
|
|
}
|
|
}
|
|
|
|
- (void)dealloc {
|
|
for(auto& it : m_touchToIdMap) {
|
|
m_touchDevice.RemoveTouch(it.second);
|
|
}
|
|
Input::InputManager::GetInstance()->UnregisterInputDevice(&m_touchDevice);
|
|
m_touchDevice.Close();
|
|
[m_displayLink release];
|
|
[m_mtdelegate release];
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)layoutSubviews {
|
|
[super layoutSubviews];
|
|
|
|
if (m_displayLink)
|
|
{ // Only use this update method if we use display link instead of metal delegate
|
|
auto size = self.bounds.size;
|
|
auto sizeX = size.width * self.contentScaleFactor;
|
|
auto sizeY = size.height * self.contentScaleFactor;
|
|
m_window.OnResize(sizeX, sizeY);
|
|
}
|
|
}
|
|
|
|
- (Math::Vector2f)getTouchPosition:(UITouch*)touch
|
|
{
|
|
CGPoint uitouchLocation = [touch locationInView:touch.view];
|
|
return { uitouchLocation.x * self.contentScaleFactor, uitouchLocation.y * self.contentScaleFactor };
|
|
}
|
|
|
|
- (void)touchesBegan:(NSSet*)inTouches withEvent:(UIEvent*)inEvent
|
|
{
|
|
for (UITouch* touch in inTouches)
|
|
{
|
|
Math::Vector2f touchLocation = [self getTouchPosition: touch];
|
|
uint32_t touchId = m_touchDevice.AddTouch(touchLocation);
|
|
m_touchDevice.TouchDown(touchId);
|
|
m_touchToIdMap.insert(std::make_pair(touch, touchId));
|
|
}
|
|
}
|
|
|
|
- (void)touchesCancelled:(NSSet*)inTouches withEvent:(UIEvent*)inEvent
|
|
{
|
|
for (UITouch* touch in inTouches)
|
|
{
|
|
Math::Vector2f touchLocation = [self getTouchPosition: touch];
|
|
|
|
auto it = m_touchToIdMap.find(touch);
|
|
if (it != m_touchToIdMap.end())
|
|
{
|
|
m_touchDevice.TouchUp(it->second);
|
|
m_touchDevice.RemoveTouch(it->second);
|
|
m_touchToIdMap.erase(it);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)touchesEnded:(NSSet*)inTouches withEvent:(UIEvent*)inEvent
|
|
{
|
|
for (UITouch* touch in inTouches)
|
|
{
|
|
Math::Vector2f touchLocation = [self getTouchPosition: touch];
|
|
|
|
auto it = m_touchToIdMap.find(touch);
|
|
if (it != m_touchToIdMap.end())
|
|
{
|
|
m_touchDevice.TouchUp(it->second);
|
|
m_touchDevice.RemoveTouch(it->second);
|
|
m_touchToIdMap.erase(it);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)touchesMoved:(NSSet*)inTouches withEvent:(UIEvent*)inEvent
|
|
{
|
|
for (UITouch* touch in inTouches)
|
|
{
|
|
Math::Vector2f touchLocation = [self getTouchPosition: touch];
|
|
|
|
auto it = m_touchToIdMap.find(touch);
|
|
if (it != m_touchToIdMap.end())
|
|
{
|
|
m_touchDevice.TouchMoved(it->second, touchLocation);
|
|
}
|
|
}
|
|
}
|
|
|
|
-(void*)GetWindow
|
|
{
|
|
return &m_window;
|
|
}
|
|
|
|
-(void) renderLoop
|
|
{
|
|
m_window.TickHandler();
|
|
}
|
|
|
|
-(void)WillAppear
|
|
{
|
|
if (m_displayLink) m_displayLink.paused = NO;
|
|
}
|
|
|
|
-(void)DidAppear
|
|
{
|
|
if (m_displayLink) m_displayLink.paused = NO;
|
|
}
|
|
|
|
-(void)WillDisappear
|
|
{
|
|
if (m_displayLink) m_displayLink.paused = YES;
|
|
}
|
|
|
|
-(void)DidDisappear
|
|
{
|
|
if (m_displayLink) m_displayLink.paused = YES;
|
|
}
|
|
|
|
-(void)DidUnload
|
|
{
|
|
if (m_displayLink)
|
|
{
|
|
[m_displayLink invalidate];
|
|
[m_displayLink release];
|
|
m_displayLink = nil;
|
|
}
|
|
}
|
|
@end
|
|
|