Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/vsg/platform/ios/iOS_ViewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <UIKit/UIKit.h>


#include <vsg/viewer/WindowTraits.h>
#include <vsg/viewer/Window.h>

#pragma mark -
#pragma mark vsg_iOS_View
@interface vsg_iOS_View : UIView
@end


#pragma mark -
#pragma mark vsg_iOS_ViewController
@interface vsg_iOS_ViewController : UIViewController
@property vsg::ref_ptr<vsg::Window> vsgWindow;
- (instancetype)initWithTraits:(vsg::ref_ptr<vsg::WindowTraits>)traits andVsgViewer:(vsg::ref_ptr<vsg::Viewer>) vsgViewer;
@end

98 changes: 98 additions & 0 deletions include/vsg/platform/ios/iOS_Window.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// vsg_iOS_ApplicationDelegate.h
// IOS_vsg_native_example
//
// Created by jaume dominguez faus on 23/5/21.
//

#ifndef vsg_iOS_Window_h
#define vsg_iOS_Window_h



#include <vsg/viewer/Window.h>
#include <vsg/ui/KeyEvent.h>
#include <vulkan/vulkan_metal.h>
#include <UIKit/UiKit.h>

@interface vsg_iOS_Window : UIWindow
- (vsg::ref_ptr<vsg::Window>) vsgWindow;
- (instancetype)initWithTraits:(vsg::ref_ptr<vsg::WindowTraits>)traits andVsgViewer:(vsg::ref_ptr<vsg::Viewer>) vsgViewer;
@end


@class vsg_iOS_View;

namespace vsgiOS
{
extern vsg::Names getInstanceExtensions();

class KeyboardMap : public vsg::Object
{
public:
KeyboardMap();

using kVKKeyCodeToKeySymbolMap = std::map<unsigned short, vsg::KeySymbol>;

bool getKeySymbol(UIEvent* anEvent, vsg::KeySymbol& keySymbol, vsg::KeySymbol& modifiedKeySymbol, vsg::KeyModifier& keyModifier);

protected:
kVKKeyCodeToKeySymbolMap _keycodeMap;
};


class iOS_Window : public vsg::Inherit<vsg::Window, iOS_Window>
{
public:

iOS_Window(vsg::ref_ptr<vsg::WindowTraits> traits);
iOS_Window() = delete;
iOS_Window(const iOS_Window&) = delete;
iOS_Window operator = (const iOS_Window&) = delete;

const char* instanceExtensionSurfaceName() const override { return VK_EXT_METAL_SURFACE_EXTENSION_NAME; }

bool valid() const override { return _window; }

bool pollEvents(vsg::UIEvents& events) override;

// bool resized() const override;

void resize() override;

bool handleUIEvent(UIEvent* anEvent);

// OS native objects
vsg_iOS_Window* window() { return _window; };
// vsg_iOS_View* view() { return _view; };
CAMetalLayer* layer() { return _metalLayer; };

vsg::clock::time_point getEventTime(double eventTime)
{
long elapsedmilli = long(double(eventTime - _first_macos_timestamp) * 1000.0f);
return _first_macos_time_point + std::chrono::milliseconds(elapsedmilli);
}

void queueEvent(vsg::UIEvent* anEvent) { _bufferedEvents.emplace_back(anEvent); }

protected:
virtual ~iOS_Window();

void _initSurface() override;

vsg_iOS_Window* _window;
vsg_iOS_View* _view;
CAMetalLayer* _metalLayer;

double _first_macos_timestamp = 0;
vsg::clock::time_point _first_macos_time_point;

vsg::UIEvents _bufferedEvents;
vsg::ref_ptr<KeyboardMap> _keyboard;
};

} // namespace vsgMacOS

EVSG_type_name(vsgiOS::iOS_Window);

#endif /* vsg_iOS_Window_h */
6 changes: 5 additions & 1 deletion include/vsg/viewer/Trackball.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#include <vsg/ui/KeyEvent.h>
#include <vsg/ui/PointerEvent.h>
#include <vsg/ui/ScrollWheelEvent.h>
#include <vsg/ui/TouchEvent.h>
#include <vsg/viewer/Camera.h>
#include <vsg/viewer/EllipsoidModel.h>

Expand All @@ -38,8 +39,11 @@ namespace vsg
void apply(ButtonReleaseEvent& buttonRelease) override;
void apply(MoveEvent& moveEvent) override;
void apply(ScrollWheelEvent& scrollWheel) override;
void apply(TouchDownEvent& touchDown) override;
void apply(TouchUpEvent& touchUp) override;
void apply(TouchMoveEvent& touchMove) override;
void apply(FrameEvent& frame) override;

virtual void rotate(double angle, const dvec3& axis);
virtual void zoom(double ratio);
virtual void pan(const dvec2& delta);
Expand Down
10 changes: 10 additions & 0 deletions src/vsg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,16 @@ if (ANDROID)

elseif (WIN32)
set(SOURCES ${SOURCES} platform/win32/Win32_Window.cpp)
elseif (IOS)
set(HEADERS ${HEADERS}
${CMAKE_SOURCE_DIR}/include/vsg/platform/ios/iOS_Window.h
${CMAKE_SOURCE_DIR}/include/vsg/platform/ios/iOS_ViewController.h
)
set(SOURCES ${SOURCES}
platform/ios/iOS_Window.mm
platform/ios/iOS_ViewController.mm
)
set(LIBRARIES ${LIBRARIES} PRIVATE ${UIKIT_LIBRARY} PRIVATE ${QUARTZCORE_LIBRARY})
elseif (APPLE)
set(SOURCES ${SOURCES} platform/macos/MacOS_Window.mm)
set(LIBRARIES ${LIBRARIES} PRIVATE ${COCOA_LIBRARY} PRIVATE ${QUARTZCORE_LIBRARY})
Expand Down
84 changes: 84 additions & 0 deletions src/vsg/platform/ios/iOS_ViewController.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <vsg/platform/ios/iOS_ViewController.h>
#include <vsg/platform/ios/iOS_Window.h>
#include <vsg/viewer/Viewer.h>

#pragma mark -
#pragma mark vsg_iOS_ViewController

@implementation vsg_iOS_ViewController {
CADisplayLink* _displayLink;
vsg::ref_ptr<vsg::WindowTraits> _traits;
vsg::ref_ptr<vsg::Viewer> _vsgViewer;
}

- (instancetype)initWithTraits:(vsg::ref_ptr<vsg::WindowTraits>)traits andVsgViewer:(vsg::ref_ptr<vsg::Viewer>) vsgViewer
{
self = [super init];
_traits = traits;
_vsgViewer = vsgViewer;
return self;
}

- (void)loadView
{
// We need to create a vsgView because doing so we ensure it has a CAMetalLayer
// otherwise it will make a view with a CALayer which is not compatible with MoltenVK.
// Also, very important to give it a size or it won't let access to any CAMetalDrawable
// which will cause a massive hang in the device forcing it to be rebooted in order
// to regain control of it.
CGRect frame;
frame.origin.x = _traits->x;
frame.origin.y = _traits->y;
frame.size.width = _traits->width <= 0 ? 1 : _traits->width;
frame.size.height = _traits->height <= 0 ? 1 : _traits->height;
vsg_iOS_View* view = [[vsg_iOS_View alloc] initWithFrame:frame];
self.view = view;

}

-(void) dealloc {
_traits = nullptr;
_vsgViewer = nullptr;
_vsgWindow = nullptr;
}


-(void) viewDidLoad {
[super viewDidLoad];

self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
uint32_t fps = 60;
_displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderLoop)];
[_displayLink setPreferredFramesPerSecond: fps];
[_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode];
}

-(void) renderLoop {
if (self->_vsgViewer->advanceToNextFrame())
{
self->_vsgViewer->compile();
self->_vsgViewer->handleEvents();
self->_vsgViewer->update();
self->_vsgViewer->recordAndSubmit();
self->_vsgViewer->present();
}
}

// Allow device rotation to resize the swapchain
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// TODO implement this
}

@end


#pragma mark -
#pragma mark vsg_iOS_View

@implementation vsg_iOS_View

/** Returns a Metal-compatible layer (required by Vulkan/MoltenVK. */
+(Class) layerClass { return [CAMetalLayer class]; }

@end
Loading