move flutter_filament plugin to federated structure

This commit is contained in:
Nick Fisher
2024-05-15 22:25:46 +08:00
parent 66e5e38324
commit 6b50dc9d36
325 changed files with 32625 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
import Foundation
import GLKit
import Flutter
public class FlutterFilamentTexture : NSObject, FlutterTexture {
public var pixelBuffer: CVPixelBuffer?
var pixelBufferAttrs = [
kCVPixelBufferPixelFormatTypeKey: NSNumber(value: kCVPixelFormatType_32BGRA),
kCVPixelBufferOpenGLCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferOpenGLESCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferIOSurfacePropertiesKey: [:]
] as CFDictionary
var flutterTextureId: Int64 = -1
var registry: FlutterTextureRegistry?
init(width:Int64, height:Int64, registry:FlutterTextureRegistry) {
self.registry = registry
super.init()
if(CVPixelBufferCreate(kCFAllocatorDefault, Int(width), Int(height),
kCVPixelFormatType_32BGRA, pixelBufferAttrs, &pixelBuffer) != kCVReturnSuccess) {
print("Error allocating pixel buffer")
} else {
self.flutterTextureId = registry.register(self)
}
}
public func copyPixelBuffer() -> Unmanaged<CVPixelBuffer>? {
return Unmanaged.passRetained(pixelBuffer!);
}
public func onTextureUnregistered(_ texture:FlutterTexture) {
print("Texture unregistered")
}
public func destroy() {
if(self.flutterTextureId != -1) {
self.registry!.unregisterTexture(self.flutterTextureId)
}
self.pixelBuffer = nil
}
}

View File

@@ -0,0 +1,10 @@
#include "ResourceBuffer.h"
ResourceLoaderWrapper *make_resource_loader(LoadFilamentResourceFromOwner loadFn, FreeFilamentResourceFromOwner freeFn, void *const owner)
{
ResourceLoaderWrapper *rlw = (ResourceLoaderWrapper *)malloc(sizeof(ResourceLoaderWrapper));
rlw->loadFromOwner = loadFn;
rlw->freeFromOwner = freeFn;
rlw->owner = owner;
return rlw;
}

View File

@@ -0,0 +1,175 @@
import Flutter
import UIKit
import GLKit
public class SwiftFlutterFilamentPlugin: NSObject, FlutterPlugin {
var registrar : FlutterPluginRegistrar
var registry: FlutterTextureRegistry
var texture: FlutterFilamentTexture?
var createdAt = Date()
var resources:NSMutableDictionary = [:]
static var messenger : FlutterBinaryMessenger? = nil;
var loadResource : @convention(c) (UnsafePointer<Int8>?, UnsafeMutableRawPointer?) -> ResourceBuffer = { uri, resourcesPtr in
let instance:SwiftFlutterFilamentPlugin = Unmanaged<SwiftFlutterFilamentPlugin>.fromOpaque(resourcesPtr!).takeUnretainedValue()
let uriString = String(cString:uri!)
var path:String? = nil
// check for hot-reloaded asset
var found : URL? = nil
if(uriString.hasPrefix("asset://")) {
let assetPath = String(uriString.dropFirst(8))
print("Searching for hot reloaded asset under path : \(assetPath)")
let appFolder = Bundle.main.resourceURL
let dirPaths = NSSearchPathForDirectoriesInDomains(.applicationDirectory,
.userDomainMask, true)
let supportDirPaths = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory,
.userDomainMask, true)
let devFsPath = URL(fileURLWithPath: supportDirPaths.first!, isDirectory:true).deletingLastPathComponent().deletingLastPathComponent().appendingPathComponent("tmp")
let orderedURLs = try? FileManager.default.enumerator(at: devFsPath, includingPropertiesForKeys: [ .pathKey, .creationDateKey], options: .skipsHiddenFiles)
for case let fileURL as URL in orderedURLs! {
if !(fileURL.path.hasSuffix(assetPath)) {
continue
}
print("Found hot reloaded asset : \(fileURL)")
if found == nil {
found = fileURL
} else {
do {
let c1 = try found!.resourceValues(forKeys: [.creationDateKey]).creationDate
let c2 = try fileURL.resourceValues(forKeys: [.creationDateKey]).creationDate
if c1! < c2! {
found = fileURL
print("\(fileURL) is newer, replacing")
} else {
print("Ignoring older asset")
}
} catch {
}
}
}
}
do {
if let cd = try found?.resourceValues(forKeys:[.creationDateKey]).creationDate {
if cd > instance.createdAt {
print("Using hot reloaded asset : \(found)")
path = found!.path
}
}
} catch {
}
if path == nil {
if(uriString.hasPrefix("file://")) {
path = String(uriString.dropFirst(7))
} else if(uriString.hasPrefix("asset://")) {
let key = instance.registrar.lookupKey(forAsset:String(uriString.dropFirst(8)))
path = Bundle.main.path(forResource: key, ofType:nil)
print("Found path \(path) for uri \(uriString)")
guard path != nil else {
print("File not present in bundle : \(uri)")
return ResourceBuffer()
}
} else {
let key = instance.registrar.lookupKey(forAsset:uriString)
path = Bundle.main.path(forResource: key, ofType:nil)
print("Found path \(path) for uri \(uriString)")
guard path != nil else {
print("File not present in bundle : \(uri)")
return ResourceBuffer()
}
}
}
do {
let data = try Data(contentsOf: URL(fileURLWithPath:path!))
let resId = instance.resources.count
let nsData = data as NSData
instance.resources[resId] = nsData
let rawPtr = nsData.bytes
let length = Int32(nsData.count)
print("Opened asset of length \(Int32(length)) at path \(path!)")
return ResourceBuffer(data:rawPtr, size:length, id:Int32(resId))
} catch {
print("Error opening file: \(error)")
}
return ResourceBuffer()
}
var freeResource : @convention(c) (ResourceBuffer,UnsafeMutableRawPointer?) -> () = { rbuf, resourcesPtr in
let instance:SwiftFlutterFilamentPlugin = Unmanaged<SwiftFlutterFilamentPlugin>.fromOpaque(resourcesPtr!).takeUnretainedValue()
instance.resources.removeObject(forKey:rbuf.id)
}
var markTextureFrameAvailable : @convention(c) (UnsafeMutableRawPointer?) -> () = { instancePtr in
let instance:SwiftFlutterFilamentPlugin = Unmanaged<SwiftFlutterFilamentPlugin>.fromOpaque(instancePtr!).takeUnretainedValue()
if(instance.texture != nil) {
instance.registry.textureFrameAvailable(instance.texture!.flutterTextureId)
}
}
public static func register(with registrar: FlutterPluginRegistrar) {
let _messenger = registrar.messenger();
messenger = _messenger;
let channel = FlutterMethodChannel(name: "app.polyvox.filament/event", binaryMessenger: _messenger)
let instance = SwiftFlutterFilamentPlugin(textureRegistry: registrar.textures(), registrar:registrar)
registrar.addMethodCallDelegate(instance, channel: channel)
}
init(textureRegistry: FlutterTextureRegistry, registrar:FlutterPluginRegistrar) {
self.registry = textureRegistry;
self.registrar = registrar
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let methodName = call.method;
switch methodName {
case "getResourceLoaderWrapper":
let resourceLoaderWrapper = make_resource_loader(loadResource, freeResource, Unmanaged.passUnretained(self).toOpaque())
result(unsafeBitCast(resourceLoaderWrapper, to:Int64.self))
case "getRenderCallback":
let renderCallback = markTextureFrameAvailable
result([
unsafeBitCast(renderCallback, to:Int64.self), unsafeBitCast(Unmanaged.passUnretained(self), to:UInt64.self)])
case "getDriverPlatform":
result(nil)
case "getSharedContext":
result(nil)
case "createTexture":
let args = call.arguments as! [Any]
let width = args[0] as! Int64
let height = args[1] as! Int64
self.texture = FlutterFilamentTexture(width: width, height: height, registry: registry)
let pixelBufferPtr = unsafeBitCast(self.texture!.pixelBuffer, to:UnsafeRawPointer.self)
let pixelBufferAddress = Int(bitPattern:pixelBufferPtr);
result([self.texture!.flutterTextureId as Any, nil, pixelBufferAddress])
case "destroyTexture":
let texture = self.texture
self.texture = nil
texture?.destroy()
result(true)
default:
result(FlutterMethodNotImplemented)
}
}
}