renaming to Thermion
This commit is contained in:
38
thermion_flutter/thermion_flutter/ios/.gitignore
vendored
Normal file
38
thermion_flutter/thermion_flutter/ios/.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
.idea/
|
||||
.vagrant/
|
||||
.sconsign.dblite
|
||||
.svn/
|
||||
|
||||
.DS_Store
|
||||
*.swp
|
||||
profile
|
||||
|
||||
DerivedData/
|
||||
build/
|
||||
GeneratedPluginRegistrant.h
|
||||
GeneratedPluginRegistrant.m
|
||||
|
||||
.generated/
|
||||
|
||||
*.pbxuser
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.perspectivev3
|
||||
|
||||
!default.pbxuser
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.perspectivev3
|
||||
|
||||
xcuserdata
|
||||
|
||||
*.moved-aside
|
||||
|
||||
*.pyc
|
||||
*sync/
|
||||
Icon?
|
||||
.tags*
|
||||
|
||||
/Flutter/Generated.xcconfig
|
||||
/Flutter/ephemeral/
|
||||
/Flutter/flutter_export_environment.sh
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "ResourceBuffer.hpp"
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
import GLKit
|
||||
|
||||
public class SwiftThermionFlutterPlugin: NSObject, FlutterPlugin {
|
||||
|
||||
var registrar : FlutterPluginRegistrar
|
||||
var registry: FlutterTextureRegistry
|
||||
var texture: ThermionFlutterTexture?
|
||||
|
||||
var createdAt = Date()
|
||||
|
||||
var resources:NSMutableDictionary = [:]
|
||||
|
||||
static var messenger : FlutterBinaryMessenger? = nil;
|
||||
|
||||
var loadResource : @convention(c) (UnsafePointer<Int8>?, UnsafeMutableRawPointer?) -> ResourceBuffer = { uri, resourcesPtr in
|
||||
|
||||
let instance:SwiftThermionFlutterPlugin = Unmanaged<SwiftThermionFlutterPlugin>.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:SwiftThermionFlutterPlugin = Unmanaged<SwiftThermionFlutterPlugin>.fromOpaque(resourcesPtr!).takeUnretainedValue()
|
||||
instance.resources.removeObject(forKey:rbuf.id)
|
||||
}
|
||||
|
||||
var markTextureFrameAvailable : @convention(c) (UnsafeMutableRawPointer?) -> () = { instancePtr in
|
||||
let instance:SwiftThermionFlutterPlugin = Unmanaged<SwiftThermionFlutterPlugin>.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 = SwiftThermionFlutterPlugin(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 = ThermionFlutterTexture(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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import Foundation
|
||||
import GLKit
|
||||
import Flutter
|
||||
|
||||
public class ThermionFlutterTexture : 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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef RESOURCE_BUFFER_H
|
||||
#define RESOURCE_BUFFER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//
|
||||
// A ResourceBuffer is a unified interface for working with
|
||||
// binary assets across various platforms.
|
||||
// This is simply:
|
||||
// 1) a pointer to some data
|
||||
// 2) the length of the data
|
||||
// 3) an ID that can be passed back to the native platform to release the underlying asset when needed.
|
||||
//
|
||||
struct ResourceBuffer
|
||||
{
|
||||
const void *const data;
|
||||
const int32_t size;
|
||||
const int32_t id;
|
||||
};
|
||||
|
||||
typedef struct ResourceBuffer ResourceBuffer;
|
||||
typedef ResourceBuffer (*LoadFilamentResource)(const char *uri);
|
||||
typedef ResourceBuffer (*LoadFilamentResourceFromOwner)(const char *const, void *const owner);
|
||||
typedef void (*FreeFilamentResource)(ResourceBuffer);
|
||||
typedef void (*FreeFilamentResourceFromOwner)(ResourceBuffer, void *const owner);
|
||||
|
||||
struct ResourceLoaderWrapper
|
||||
{
|
||||
LoadFilamentResource loadResource;
|
||||
FreeFilamentResource freeResource;
|
||||
LoadFilamentResourceFromOwner loadFromOwner;
|
||||
FreeFilamentResourceFromOwner freeFromOwner;
|
||||
void *owner;
|
||||
};
|
||||
typedef struct ResourceLoaderWrapper ResourceLoaderWrapper;
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
namespace thermion_flutter {
|
||||
|
||||
struct ResourceLoaderWrapperImpl : public ResourceLoaderWrapper
|
||||
{
|
||||
|
||||
ResourceLoaderWrapperImpl(LoadFilamentResource loader, FreeFilamentResource freeResource)
|
||||
{
|
||||
loadFromOwner = nullptr;
|
||||
freeFromOwner = nullptr;
|
||||
loadResource = loader;
|
||||
freeResource = freeResource;
|
||||
owner = nullptr;
|
||||
}
|
||||
|
||||
ResourceLoaderWrapperImpl(LoadFilamentResourceFromOwner loader, FreeFilamentResourceFromOwner freeResource, void * owner)
|
||||
{
|
||||
loadResource = nullptr;
|
||||
freeResource = nullptr;
|
||||
loadFromOwner = loader;
|
||||
freeFromOwner = freeResource;
|
||||
owner = owner;
|
||||
}
|
||||
|
||||
ResourceBuffer load(const char *uri) const
|
||||
{
|
||||
if (loadFromOwner)
|
||||
{
|
||||
auto rb = loadFromOwner(uri, owner);
|
||||
return rb;
|
||||
}
|
||||
auto rb = loadResource(uri);
|
||||
return rb;
|
||||
}
|
||||
|
||||
void free(ResourceBuffer rb) const
|
||||
{
|
||||
if (freeFromOwner)
|
||||
{
|
||||
freeFromOwner(rb, owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
freeResource(rb);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef SwiftThermionFlutterPlugin_Bridging_Header_h
|
||||
#define SwiftThermionFlutterPlugin_Bridging_Header_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ResourceBuffer.hpp"
|
||||
|
||||
ResourceLoaderWrapper *make_resource_loader(LoadFilamentResourceFromOwner loadFn, FreeFilamentResourceFromOwner freeFn, void *const owner);
|
||||
|
||||
// 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;
|
||||
// }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint thermion_flutter.podspec` to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'thermion_flutter'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'A new flutter plugin project.'
|
||||
s.description = <<-DESC
|
||||
A new flutter plugin project.
|
||||
DESC
|
||||
s.homepage = 'http://example.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Your Company' => 'email@example.com' }
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/*', 'include/SwiftThermionFlutterPlugin-Bridging-Header.h','include/ResourceBuffer.hpp', 'src/ResourceBuffer.c'
|
||||
s.public_header_files = 'include/SwiftThermionFlutterPlugin-Bridging-Header.h', 'include/ResourceBuffer.hpp'
|
||||
s.dependency 'Flutter'
|
||||
s.platform = :ios, '13.0'
|
||||
s.static_framework = true
|
||||
s.user_target_xcconfig = {
|
||||
'DEFINES_MODULE' => 'YES',
|
||||
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
|
||||
'OTHER_CFLAGS' => '"-fvisibility=default" "$(inherited)"',
|
||||
}
|
||||
|
||||
s.pod_target_xcconfig = {
|
||||
'DEFINES_MODULE' => 'YES',
|
||||
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
|
||||
}
|
||||
|
||||
s.swift_version = '5.0'
|
||||
end
|
||||
Reference in New Issue
Block a user