tidy up method call handler and add example project with camera panning
This commit is contained in:
23
ios/Classes/filament/FilamentMethodCallHandler.h
Normal file
23
ios/Classes/filament/FilamentMethodCallHandler.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef FilamentMethodCallHandler_h
|
||||
#define FilamentMethodCallHandler_h
|
||||
#endif /* FilamentNativeViewFactory_h */
|
||||
|
||||
#import <Flutter/Flutter.h>
|
||||
#import "FilamentViewController.h"
|
||||
|
||||
#include "FilamentViewer.hpp"
|
||||
|
||||
static const id VIEW_TYPE = @"mimetic.app/filament_view";
|
||||
|
||||
@interface FilamentMethodCallHandler : FlutterMethodChannel
|
||||
- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:( FlutterResult _Nonnull)result;
|
||||
- (mimetic::FilamentViewer*) _viewer;
|
||||
- (mimetic::ResourceBuffer)loadResource:(const char* const)path;
|
||||
- (void)freeResource:(void*)mem size:(size_t)size misc:(void*)misc;
|
||||
|
||||
- (instancetype)initWithController:(FilamentViewController*)controller
|
||||
registrar:(NSObject<FlutterPluginRegistrar>*)registrar
|
||||
viewId:(int64_t)viewId
|
||||
layer:(void*)layer;
|
||||
|
||||
@end
|
||||
97
ios/Classes/filament/FilamentMethodCallHandler.mm
Normal file
97
ios/Classes/filament/FilamentMethodCallHandler.mm
Normal file
@@ -0,0 +1,97 @@
|
||||
#import "FilamentMethodCallHandler.h"
|
||||
#import "FilamentViewController.h"
|
||||
#import "FilamentNativeViewFactory.h"
|
||||
|
||||
static const FilamentMethodCallHandler* _handler;
|
||||
|
||||
static mimetic::ResourceBuffer loadResourceGlobal(const char* name) {
|
||||
return [_handler loadResource:name];
|
||||
}
|
||||
|
||||
static void* freeResourceGlobal(void* mem, size_t size, void* misc) {
|
||||
[_handler freeResource:mem size:size misc:misc ];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@implementation FilamentMethodCallHandler {
|
||||
FilamentViewController *_controller;
|
||||
FlutterMethodChannel* _channel;
|
||||
mimetic::FilamentViewer* _viewer;
|
||||
void* _layer;
|
||||
|
||||
NSObject<FlutterPluginRegistrar>* _registrar;
|
||||
}
|
||||
- (instancetype)initWithController:(FilamentViewController*)controller
|
||||
registrar:(NSObject<FlutterPluginRegistrar>*)registrar
|
||||
viewId:(int64_t)viewId
|
||||
layer:(void*)layer
|
||||
{
|
||||
_layer = layer;
|
||||
_registrar = registrar;
|
||||
_controller = controller;
|
||||
NSString* channelName = [NSString stringWithFormat:@"%@_%d",VIEW_TYPE,viewId];
|
||||
_channel = [FlutterMethodChannel
|
||||
methodChannelWithName:channelName
|
||||
binaryMessenger:[registrar messenger]];
|
||||
[_channel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
|
||||
[self handleMethodCall:call result:result];
|
||||
}];
|
||||
_handler = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result {
|
||||
if([@"initialize" isEqualToString:call.method]) {
|
||||
_viewer = new mimetic::FilamentViewer(_layer, loadResourceGlobal, freeResourceGlobal);
|
||||
[_controller setViewer:_viewer];
|
||||
[_controller startDisplayLink];
|
||||
result(@"OK");
|
||||
} else if([@"loadSkybox" isEqualToString:call.method]) {
|
||||
if(!_viewer)
|
||||
return;
|
||||
_viewer->loadSkybox([call.arguments[0] UTF8String], [call.arguments[1] UTF8String]);
|
||||
result(@"OK");
|
||||
} else if([@"loadGltf" isEqualToString:call.method]) {
|
||||
if(!_viewer)
|
||||
return;
|
||||
_viewer->loadGltf([call.arguments[0] UTF8String], [call.arguments[1] UTF8String]);
|
||||
result(@"OK");
|
||||
} else if([@"panStart" isEqualToString:call.method]) {
|
||||
if(!_viewer)
|
||||
return;
|
||||
_viewer->manipulator->grabBegin([call.arguments[0] intValue], [call.arguments[1] intValue], true);
|
||||
} else if([@"panUpdate" isEqualToString:call.method]) {
|
||||
if(!_viewer)
|
||||
return;
|
||||
_viewer->manipulator->grabUpdate([call.arguments[0] intValue], [call.arguments[1] intValue]);
|
||||
} else if([@"panEnd" isEqualToString:call.method]) {
|
||||
if(!_viewer)
|
||||
return;
|
||||
_viewer->manipulator->grabEnd();
|
||||
} else {
|
||||
result(FlutterMethodNotImplemented);
|
||||
}
|
||||
}
|
||||
|
||||
- (mimetic::ResourceBuffer)loadResource:(const char* const)path {
|
||||
NSString* p = [NSString stringWithFormat:@"%s", path];
|
||||
NSString* key = [_registrar lookupKeyForAsset:p];
|
||||
NSString* nsPath = [[NSBundle mainBundle] pathForResource:key
|
||||
ofType:nil];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:nsPath]) {
|
||||
NSLog(@"Error: no file exists at %@", nsPath);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
NSData* buffer = [NSData dataWithContentsOfFile:nsPath];
|
||||
void* cpy = malloc([buffer length]);
|
||||
memcpy(cpy, [buffer bytes], [buffer length]); // can we avoid this copy somehow?
|
||||
mimetic::ResourceBuffer rbuf(cpy, [buffer length]);
|
||||
return rbuf;
|
||||
}
|
||||
|
||||
- (void)freeResource:(void*)mem size:(size_t)s misc:(void *)m {
|
||||
free(mem);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -3,17 +3,13 @@
|
||||
#endif /* FilamentNativeViewFactory_h */
|
||||
|
||||
#import <Flutter/Flutter.h>
|
||||
#import "FilamentViewer.hpp"
|
||||
#import "FilamentView.h"
|
||||
|
||||
#include "FilamentViewer.hpp"
|
||||
|
||||
@interface FilamentMethodCallHandler : FlutterMethodChannel
|
||||
- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:( FlutterResult _Nonnull)result;
|
||||
- (mimetic::FilamentViewer*) _viewer;
|
||||
@end
|
||||
|
||||
@interface FilamentNativeViewFactory : NSObject <FlutterPlatformViewFactory>
|
||||
- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar;
|
||||
- (mimetic::ResourceBuffer)loadResource:(const char* const)path;
|
||||
- (void)freeResource:(void*)mem size:(size_t)size misc:(void*)misc;
|
||||
@end
|
||||
|
||||
@interface FilamentNativeView : NSObject <FlutterPlatformView>
|
||||
|
||||
@@ -1,18 +1,6 @@
|
||||
#import "FilamentNativeViewFactory.h"
|
||||
#import "FilamentViewController.h"
|
||||
|
||||
static const id VIEW_TYPE = @"mimetic.app/filament_view";
|
||||
|
||||
static const FilamentNativeViewFactory* _factory;
|
||||
|
||||
static mimetic::ResourceBuffer loadResource(const char* const name) {
|
||||
return [_factory loadResource:name];
|
||||
}
|
||||
|
||||
static void* freeResource(void* mem, size_t size, void* misc) {
|
||||
[_factory freeResource:mem size:size misc:misc ];
|
||||
return nullptr;
|
||||
}
|
||||
#import "FilamentMethodCallHandler.h"
|
||||
|
||||
@implementation FilamentNativeViewFactory {
|
||||
NSObject<FlutterPluginRegistrar>* _registrar;
|
||||
@@ -23,7 +11,6 @@ static void* freeResource(void* mem, size_t size, void* misc) {
|
||||
if (self) {
|
||||
_registrar = registrar;
|
||||
}
|
||||
_factory = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -38,81 +25,27 @@ static void* freeResource(void* mem, size_t size, void* misc) {
|
||||
|
||||
@end
|
||||
|
||||
@implementation FilamentMethodCallHandler {
|
||||
FilamentViewController *_controller;
|
||||
FlutterMethodChannel* _channel;
|
||||
mimetic::FilamentViewer* _viewer;
|
||||
void* _layer;
|
||||
}
|
||||
- (instancetype)initWithController:(FilamentViewController*)controller
|
||||
registrar:(NSObject<FlutterPluginRegistrar>*)registrar
|
||||
viewId:(int64_t)viewId
|
||||
layer:(void*)layer
|
||||
{
|
||||
_layer = layer;
|
||||
_controller = controller;
|
||||
NSString* channelName = [NSString stringWithFormat:@"%@_%d",VIEW_TYPE,viewId];
|
||||
_channel = [FlutterMethodChannel
|
||||
methodChannelWithName:channelName
|
||||
binaryMessenger:[registrar messenger]];
|
||||
[_channel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
|
||||
[self handleMethodCall:call result:result];
|
||||
}];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)handleMethodCall:(FlutterMethodCall* _Nonnull)call result:(FlutterResult _Nonnull )result {
|
||||
if([@"initialize" isEqualToString:call.method]) {
|
||||
[self initialize];
|
||||
} else {
|
||||
result(FlutterMethodNotImplemented);
|
||||
}
|
||||
}
|
||||
|
||||
- (mimetic::ResourceBuffer)loadResource:(const char* const)path {
|
||||
|
||||
NSString* documentPath = [NSSearchPathForDirectoriesInDomains(
|
||||
NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
|
||||
NSString* pathComponent = [NSString stringWithUTF8String:path];
|
||||
NSString* nsPath = [documentPath stringByAppendingPathComponent:pathComponent];
|
||||
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:nsPath]) {
|
||||
NSLog(@"Error: no file exists at %@", nsPath);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
NSData* buffer = [NSData dataWithContentsOfFile:nsPath];
|
||||
|
||||
mimetic::ResourceBuffer rbuf([buffer bytes], [buffer length]);
|
||||
return rbuf;
|
||||
}
|
||||
|
||||
- (void)freeResource:(void*)mem size:(size_t)s misc:(void *)m {
|
||||
// TODO
|
||||
}
|
||||
|
||||
-(void)initialize {
|
||||
_viewer = new mimetic::FilamentViewer(_layer, loadResource, freeResource);
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation FilamentNativeView {
|
||||
FilamentView *_view;
|
||||
FilamentViewController *_controller;
|
||||
FilamentMethodCallHandler *_handler;
|
||||
FilamentView* _view;
|
||||
FilamentViewController* _controller;
|
||||
mimetic::FilamentViewer* _viewer;
|
||||
FilamentMethodCallHandler* _handler;
|
||||
void* _layer;
|
||||
}
|
||||
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
viewIdentifier:(int64_t)viewId
|
||||
arguments:(id _Nullable)args
|
||||
registrar:(NSObject<FlutterPluginRegistrar>*)registrar {
|
||||
if (self = [super init]) {
|
||||
_view = [[FilamentView alloc] init];
|
||||
_controller = [[FilamentViewController alloc] initWithRegistrar:registrar];
|
||||
_controller.modelView = _view;
|
||||
_controller = [[FilamentViewController alloc] initWithRegistrar:registrar view:_view];
|
||||
[_controller viewDidLoad];
|
||||
[_controller startDisplayLink];
|
||||
_handler = [[FilamentMethodCallHandler alloc] initWithController:_controller registrar:registrar viewId:viewId layer:(__bridge void*)[_view layer]];
|
||||
_layer = (__bridge_retained void*)[_view layer];
|
||||
_handler = [[FilamentMethodCallHandler alloc] initWithController:_controller registrar:registrar viewId:viewId layer:_layer];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#include "FilamentViewer.hpp"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
@@ -24,8 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*
|
||||
*/
|
||||
@interface FilamentView : UIView
|
||||
|
||||
|
||||
- (void)setViewer:(mimetic::FilamentViewer*)viewer;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -16,21 +16,26 @@
|
||||
|
||||
// These defines are set in the "Preprocessor Macros" build setting for each scheme.
|
||||
#include "FilamentView.h"
|
||||
|
||||
#include "FilamentViewer.hpp"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@interface FilamentView ()
|
||||
|
||||
- (void)initCommon;
|
||||
|
||||
- (void)setViewer:(mimetic::FilamentViewer*)viewer;
|
||||
@end
|
||||
|
||||
@implementation FilamentView {
|
||||
|
||||
mimetic::FilamentViewer* _viewer;
|
||||
}
|
||||
|
||||
- (void)setViewer:(mimetic::FilamentViewer*)viewer {
|
||||
_viewer = viewer;
|
||||
_viewer->updateViewportAndCameraProjection(self.bounds.size.width, self.bounds.size.height, self.contentScaleFactor);
|
||||
}
|
||||
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
[self initCommon];
|
||||
@@ -58,4 +63,18 @@ using namespace std;
|
||||
return [CAEAGLLayer class];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
if(_viewer) {
|
||||
_viewer->updateViewportAndCameraProjection(self.bounds.size.width, self.bounds.size.height, self.contentScaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setContentScaleFactor:(CGFloat)contentScaleFactor {
|
||||
[super setContentScaleFactor:contentScaleFactor];
|
||||
if(_viewer) {
|
||||
_viewer->updateViewportAndCameraProjection(self.bounds.size.width, self.bounds.size.height, self.contentScaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -18,14 +18,15 @@
|
||||
|
||||
#import "FilamentView.h"
|
||||
#import "Flutter/Flutter.h"
|
||||
#import "FilamentViewer.hpp"
|
||||
|
||||
@interface FilamentViewController : UIViewController
|
||||
|
||||
@property(weak, nonatomic) IBOutlet FilamentView* modelView;
|
||||
|
||||
- (void)setViewer:(mimetic::FilamentViewer*)viewer;
|
||||
- (void)startDisplayLink;
|
||||
- (void)stopDisplayLink;
|
||||
|
||||
-initWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar;
|
||||
-initWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar view:(FilamentView*)view;
|
||||
|
||||
@end
|
||||
|
||||
@@ -16,20 +16,29 @@
|
||||
|
||||
#import "FilamentViewController.h"
|
||||
#import "FilamentView.h"
|
||||
|
||||
#import "FilamentViewer.hpp"
|
||||
#import <Flutter/Flutter.h>
|
||||
|
||||
@implementation FilamentViewController {
|
||||
CADisplayLink* _displayLink;
|
||||
NSObject<FlutterPluginRegistrar>* _registrar;
|
||||
mimetic::FilamentViewer* _viewer;
|
||||
FilamentView* _view;
|
||||
}
|
||||
|
||||
- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
|
||||
- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar
|
||||
view:(FilamentView*)view {
|
||||
if (self = [super init]) {
|
||||
_registrar = registrar;
|
||||
_view = view;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
- (void)setViewer:(mimetic::FilamentViewer*)viewer {
|
||||
_viewer = viewer;
|
||||
[_view setViewer:_viewer];
|
||||
}
|
||||
#pragma mark UIViewController methods
|
||||
|
||||
- (void)viewDidLoad {
|
||||
@@ -58,8 +67,10 @@
|
||||
_displayLink = nil;
|
||||
}
|
||||
|
||||
- (void)render {
|
||||
|
||||
- (void)render {
|
||||
if(_viewer) {
|
||||
_viewer->render();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
||||
Reference in New Issue
Block a user