diff --git a/flutter_filament_federated/flutter_filament/.gitattributes b/flutter_filament_federated/flutter_filament/.gitattributes new file mode 100644 index 00000000..cb63127d --- /dev/null +++ b/flutter_filament_federated/flutter_filament/.gitattributes @@ -0,0 +1,12 @@ +*.a filter=lfs diff=lfs merge=lfs -text +*.lib filter=lfs diff=lfs merge=lfs -text +*.dll filter=lfs diff=lfs merge=lfs -text +*.pdb filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text +*.uberz filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.ktx filter=lfs diff=lfs merge=lfs -text +*.blend filter=lfs diff=lfs merge=lfs -text +*.gltf filter=lfs diff=lfs merge=lfs -text +*.glb filter=lfs diff=lfs merge=lfs -text diff --git a/flutter_filament_federated/flutter_filament/.gitignore b/flutter_filament_federated/flutter_filament/.gitignore new file mode 100644 index 00000000..a0f0e538 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/.gitignore @@ -0,0 +1,2 @@ +.vscode +.DS_Store diff --git a/flutter_filament_federated/flutter_filament/LICENSE b/flutter_filament_federated/flutter_filament/LICENSE new file mode 100644 index 00000000..ba75c69f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/flutter_filament_federated/flutter_filament/analysis_options.yaml b/flutter_filament_federated/flutter_filament/analysis_options.yaml new file mode 100644 index 00000000..a5744c1c --- /dev/null +++ b/flutter_filament_federated/flutter_filament/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/flutter_filament_federated/flutter_filament/android/.gitignore b/flutter_filament_federated/flutter_filament/android/.gitignore new file mode 100644 index 00000000..c6cbe562 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/flutter_filament_federated/flutter_filament/android/CMakeLists.txt b/flutter_filament_federated/flutter_filament/android/CMakeLists.txt new file mode 100644 index 00000000..d52dff40 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 3.10) + +include_directories(../ios/src) +include_directories(../ios/include) +include_directories(../ios/include/filament) +include_directories(src/main/cpp) +link_directories(src/main/jniLibs/${ANDROID_ABI}) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + +add_library(flutter_filament_android SHARED + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FlutterFilamentApi.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FlutterFilamentFFIApi.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/FilamentAndroid.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/SceneManager.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FilamentViewer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/StreamBufferAdapter.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/TimeIt.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/camutils/Manipulator.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/camutils/Bookmark.cpp" +) + +add_library(FILAMENT_SHADERS SHARED + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/include/material/image.c" +) + +target_link_libraries( + flutter_filament_android + FILAMENT_SHADERS + -landroid + -llog + -lgltfio_core + -lfilament + -lbackend + -lgeometry + -lfilameshio + -lfilamat + -lfilabridge + -lcamutils + -lfilaflat + -ldracodec + -libl + -lktxreader + -limageio + -limage + -lutils + -ltinyexr + -lstb + -lbluevk + -lvkshaders + -luberzlib + -lsmol-v + -luberarchive + -lmeshoptimizer + -lgeometry + -lbasis_transcoder + -lGLESv3 + -lEGL + -lpng + -lz + -lzstd +) \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/android/build.gradle b/flutter_filament_federated/flutter_filament/android/build.gradle new file mode 100644 index 00000000..43e9f803 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/build.gradle @@ -0,0 +1,63 @@ +group 'app.polyvox.filament' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion 33 + ndkVersion '25.2.9519653' + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + minSdkVersion 22 + ndk { + abiFilters 'arm64-v8a' // 'x86_64' 'armeabi-v7a' + } + } + + externalNativeBuild { + cmake { + path "CMakeLists.txt" + version "3.18.1" + } + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation 'net.java.dev.jna:jna:5.10.0@aar' + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2" +} diff --git a/flutter_filament_federated/flutter_filament/android/gradle.properties b/flutter_filament_federated/flutter_filament/android/gradle.properties new file mode 100644 index 00000000..94adc3a3 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/flutter_filament_federated/flutter_filament/android/gradle/wrapper/gradle-wrapper.properties b/flutter_filament_federated/flutter_filament/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..8048ce64 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/android/settings.gradle b/flutter_filament_federated/flutter_filament/android/settings.gradle new file mode 100644 index 00000000..d7463b36 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'flutter_filament' diff --git a/flutter_filament_federated/flutter_filament/android/src/main/AndroidManifest.xml b/flutter_filament_federated/flutter_filament/android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..e3327c11 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/flutter_filament_federated/flutter_filament/android/src/main/cpp/FilamentAndroid.cpp b/flutter_filament_federated/flutter_filament/android/src/main/cpp/FilamentAndroid.cpp new file mode 100644 index 00000000..1e0c4695 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/src/main/cpp/FilamentAndroid.cpp @@ -0,0 +1,21 @@ +#include +#include + +extern "C" { + + #include "FlutterFilamentFFIApi.h" + + void* get_native_window_from_surface( + jobject surface, + JNIEnv* env + ) { + void* window = ANativeWindow_fromSurface(env, surface); + return window; + } + + // this does nothing, but we need it for JNA to return the correct pointer + FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback callback) { + return callback; + } + +} diff --git a/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/FilamentInterop.kt b/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/FilamentInterop.kt new file mode 100644 index 00000000..5d5e9693 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/FilamentInterop.kt @@ -0,0 +1,48 @@ +package app.polyvox.filament + +import com.sun.jna.ptr.PointerByReference +import com.sun.jna.ptr.IntByReference + +import android.view.Surface + +import android.content.res.AssetManager +import com.sun.jna.* + +open class ResourceBuffer: Structure(), Structure.ByValue { + @JvmField var data: Pointer = Pointer(0); + @JvmField var size: Int = 0; + @JvmField var id: Int = 0; + override fun getFieldOrder(): List { + return listOf("data", "size", "id") + } +} + +interface LoadFilamentResourceFromOwner : Callback { + fun loadResourceFromOwner(resourceName: String?, owner: Pointer?): ResourceBuffer +} + +interface FreeFilamentResourceFromOwner : Callback { + fun freeResourceFromOwner(rb: ResourceBuffer, owner: Pointer?) +} + +interface RenderCallback : Callback { + fun renderCallback(owner:Pointer?) +} + +interface FilamentInterop : Library { + +fun get_native_window_from_surface(surface:Object, env:JNIEnv) : Pointer?; +fun make_render_callback_fn_pointer(renderCallback:RenderCallback) : Pointer +fun make_resource_loader(loadResourceFromOwner: LoadFilamentResourceFromOwner, freeResource: FreeFilamentResourceFromOwner, owner:Pointer?) : Pointer; +fun create_filament_viewer_ffi(context:Pointer, platform:Pointer, loader:Pointer, rc:Pointer, rco:Pointer) : Pointer; +fun create_swap_chain_ffi(vieer:Pointer?, surface:Pointer?, width:Int, height:Int) +fun set_background_color_ffi(viewer: Pointer?, r: Float, g: Float, b: Float, a: Float) +fun update_viewport_and_camera_projection_ffi(viewer: Pointer?, width: Int, height: Int, scale_factor: Float) +fun render_ffi(viewer: Pointer?) +fun create_filament_viewer(context:Pointer?, platform:Pointer?, loader:Pointer?) : Pointer; +fun create_swap_chain(vieer:Pointer?, surface:Pointer?, width:Int, height:Int) +fun set_background_color(viewer: Pointer?, r: Float, g: Float, b: Float, a: Float) +fun update_viewport_and_camera_projection(viewer: Pointer?, width: Int, height: Int, scale_factor: Float) +fun render(viewer: Pointer?, u:Long, a:Pointer?, b:Pointer?, c:Pointer?) +} + diff --git a/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/FlutterFilamentPlugin.kt b/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/FlutterFilamentPlugin.kt new file mode 100644 index 00000000..2807f757 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/FlutterFilamentPlugin.kt @@ -0,0 +1,226 @@ +package app.polyvox.filament + + +import HotReloadPathHelper +import android.app.Activity +import android.content.res.AssetManager +import android.graphics.* +import android.os.Build +import android.util.Log +import android.view.Choreographer +import android.view.Surface +import androidx.annotation.NonNull +import androidx.annotation.RequiresApi +import androidx.lifecycle.Lifecycle +import com.sun.jna.* +import io.flutter.FlutterInjector +import io.flutter.embedding.engine.FlutterJNI +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.activity.ActivityAware +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding +import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.view.TextureRegistry.SurfaceTextureEntry +import java.io.File +import java.util.* + +class LoadFilamentResourceFromOwnerImpl(plugin:FlutterFilamentPlugin) : LoadFilamentResourceFromOwner { + var plugin = plugin + override fun loadResourceFromOwner(path: String?, owner: Pointer?): ResourceBuffer { + return plugin.loadResourceFromOwner(path, owner) + } +} + +class FreeFilamentResourceFromOwnerImpl(plugin:FlutterFilamentPlugin) : FreeFilamentResourceFromOwner { + var plugin = plugin + override fun freeResourceFromOwner(rb: ResourceBuffer, owner: Pointer?) { + plugin.freeResourceFromOwner(rb, owner) + } +} + +class RenderCallbackImpl(plugin:FlutterFilamentPlugin) : RenderCallback { + var plugin = plugin + override fun renderCallback(owner:Pointer?) { + plugin.renderCallback(); + + if(!plugin._surface!!.isValid) { + Log.e("ERR", "ERR", null) + } + } +} + +/** FlutterFilamentPlugin */ +class FlutterFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, LoadFilamentResourceFromOwner, FreeFilamentResourceFromOwner { + + companion object { + const val CHANNEL_NAME = "app.polyvox.filament/event" + const val TAG = "FilamentPlugin" + } + + private lateinit var channel : MethodChannel + + private lateinit var flutterPluginBinding : FlutterPlugin.FlutterPluginBinding + + private var lifecycle: Lifecycle? = null + + private lateinit var _lib : FilamentInterop + + var _surfaceTexture: SurfaceTexture? = null + private var _surfaceTextureEntry: SurfaceTextureEntry? = null + var _surface: Surface? = null + + private lateinit var activity:Activity + + private var loadResourceWrapper:LoadFilamentResourceFromOwnerImpl = LoadFilamentResourceFromOwnerImpl(this) + private var freeResourceWrapper:FreeFilamentResourceFromOwnerImpl = FreeFilamentResourceFromOwnerImpl(this) + + override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + this.flutterPluginBinding = flutterPluginBinding + channel = MethodChannel(flutterPluginBinding.binaryMessenger, CHANNEL_NAME) + channel.setMethodCallHandler(this) + _lib = Native.loadLibrary("flutter_filament_android", FilamentInterop::class.java, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, true)) + } + + override fun onAttachedToActivity(binding: ActivityPluginBinding) { + lifecycle = (binding.lifecycle as? HiddenLifecycleReference)?.lifecycle + activity = binding.activity + activity.window.setFormat(PixelFormat.RGBA_8888) + } + + val _resources:MutableMap = mutableMapOf(); + var _lastId = 1 + + override fun loadResourceFromOwner(path: String?, owner: Pointer?): ResourceBuffer { + Log.i("flutter_filament", "Loading resource from path $path") + var data:ByteArray? = null + if(path!!.startsWith("file://")) { + data = File(path!!.substring(6)).readBytes() + } else { + var assetPath = path + if(assetPath.startsWith("asset://")) { + assetPath = assetPath!!.substring(8) + } + val loader = FlutterInjector.instance().flutterLoader() + val key = loader.getLookupKeyForAsset(assetPath) + val hotReloadPath = HotReloadPathHelper.getAssetPath(key, activity.getPackageName()) + if (hotReloadPath != null) { + data = File(hotReloadPath).readBytes() + } else { + Log.i("flutter_filament", "Loading resource from main asset bundle at ${assetPath}") + + val assetManager: AssetManager = activity.assets + try { + data = assetManager.open(key).readBytes() + Log.i("flutter_filament", "Loaded ${data.size} bytes") + } catch (e:Exception) { + Log.e("flutter_filament", "Failed to open asset at ${assetPath}", null) + } + } + } + val rb = ResourceBuffer(); + try { + if (data != null) { + val dataPtr = Memory(data.size.toLong()) + dataPtr.write(0, data, 0, data.size) + rb.data = dataPtr + rb.size = data.size + rb.id = _lastId + _resources[rb] = dataPtr; + _lastId++ + } else { + rb.id = 0 + rb.size = 0 + rb.data = Pointer(0) + } + } catch(e:Exception) { + Log.e("flutter_filament", "Error setting resource buffer : $e", null); + } + rb.write(); + return rb; + + } + + override fun freeResourceFromOwner(rb: ResourceBuffer, owner: Pointer?) { + _resources.remove(rb) + } + + fun renderCallback() { + // noop, log or check surface.valid() is you want + } + + + @RequiresApi(Build.VERSION_CODES.M) + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + Log.e("flutter_filament", call.method, null) + when (call.method) { + "createTexture" -> { + if(_surfaceTextureEntry != null) { + result.error("TEXTURE_EXISTS", "Texture already exist. Make sure you call destroyTexture first", null) + return + } + val args = call.arguments as List<*> + val width = args[0] as Double + val height = args[1] as Double + if(width <1 || height < 1) { + result.error("DIMENSION_MISMATCH","Both dimensions must be greater than zero (you provided $width x $height)", null); + return; + } + Log.i("flutter_filament", "Creating Surface Texture of size ${width}x${height}"); + + _surfaceTextureEntry = flutterPluginBinding.textureRegistry.createSurfaceTexture() + _surfaceTexture = _surfaceTextureEntry!!.surfaceTexture(); + _surfaceTexture!!.setDefaultBufferSize(width.toInt(), height.toInt()) + + _surface = Surface(_surfaceTexture) + + if(!_surface!!.isValid) { + Log.e("ERR", "ERR", null) + } + + val nativeWindow = _lib.get_native_window_from_surface(_surface!! as Object, JNIEnv.CURRENT) + + val resultList = listOf(_surfaceTextureEntry!!.id(), Pointer.nativeValue(nativeWindow), null, null ) + + result.success(resultList) + } + "getResourceLoaderWrapper" -> { + val resourceLoader = _lib.make_resource_loader(loadResourceWrapper, freeResourceWrapper, Pointer(0)) + result.success(Pointer.nativeValue(resourceLoader)) + } + "getRenderCallback" -> { + val renderCallbackFnPointer = _lib.make_render_callback_fn_pointer(RenderCallbackImpl(this)) + result.success(listOf(Pointer.nativeValue(renderCallbackFnPointer), 0)) + } + "destroyTexture" -> { + _surface!!.release(); + _surfaceTextureEntry!!.release(); + _surface = null + _surfaceTextureEntry = null + result.success(true) + } + else -> { + result.notImplemented() + } + } +} + + override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + channel.setMethodCallHandler(null) + } + + + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + onAttachedToActivity(binding) + } + + override fun onDetachedFromActivityForConfigChanges() { + onDetachedFromActivity() + } + + override fun onDetachedFromActivity() { + lifecycle = null + } + +} diff --git a/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/HotReloadPathHelper.kt b/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/HotReloadPathHelper.kt new file mode 100644 index 00000000..f347d2c2 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/android/src/main/kotlin/app/polyvox/filament/HotReloadPathHelper.kt @@ -0,0 +1,28 @@ +import java.io.* +import java.nio.file.FileSystems +import java.nio.file.Files +import java.nio.file.Path +import kotlin.io.path.absolutePathString +import kotlin.io.path.listDirectoryEntries +import android.util.Log + + +class HotReloadPathHelper { + companion object { + fun getAssetPath(path: String, packageName: String): String? { + val packagePath = "/data/user/0/${packageName}/code_cache/" + Log.v("flutter_filament", "Looking for hot reloaded asset ${path} under package path ${packagePath}") + val files = File(packagePath).walkBottomUp().filter { + it.path.endsWith(path) + }.sortedBy { + it.lastModified() + }.toList() + if(files.size > 0) { + Log.v("flutter_filament", "Using hot reloaded asset at ${files.last().path}") + return files.last().path; + } + Log.v("flutter_filament", "No hot reloaded asset found.") + return null; + } + } +} \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/docs/drawing.png b/flutter_filament_federated/flutter_filament/docs/drawing.png new file mode 100644 index 00000000..57684da7 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/docs/drawing.png differ diff --git a/flutter_filament_federated/flutter_filament/docs/drawing.svg b/flutter_filament_federated/flutter_filament/docs/drawing.svg new file mode 100644 index 00000000..73a72d26 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/docs/drawing.svg @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FilamentController (Dart) + FlutterFilamentFFI + FilamentViewer / Filament Engine (etc) + Render thread + Main Flutter Thread + Platform Channel + + + + + + + Sets up OpenGL/Metal/etc rendering context, render target textures/window, etc + Asset loading + + diff --git a/flutter_filament_federated/flutter_filament/example/.fvm/fvm_config.json b/flutter_filament_federated/flutter_filament/example/.fvm/fvm_config.json new file mode 100644 index 00000000..8fd7d3ea --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/.fvm/fvm_config.json @@ -0,0 +1,4 @@ +{ + "flutterSdkVersion": "3.16.0-0.2.pre", + "flavors": {} +} \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/example/.gitattributes b/flutter_filament_federated/flutter_filament/example/.gitattributes new file mode 100644 index 00000000..588e746e --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/.gitattributes @@ -0,0 +1,30 @@ +assets/lit_opaque_43.uberz filter=lfs diff=lfs merge=lfs -text +assets/BusterDrone filter=lfs diff=lfs merge=lfs -text +assets/FlightHelmet filter=lfs diff=lfs merge=lfs -text +assets/lit_opaque_32.uberz filter=lfs diff=lfs merge=lfs -text +windows/lib/**/*.* filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/12_Settonemappingtolinear.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/3_loadIBL.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/6_zoomin.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/13_Movecameratoasset.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/14_movecamerato.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/7_rotate.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/9_transformtounitcube.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/0_fresh.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/10_setshapespositionto.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/2_loadskybox.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/4_Renderingfalse.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/8_pan.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/11_Disablefrustumculling.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/15_setcameratofirstcamerainshapesGLB.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/1_createviewerdefaultubershader.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/5_loadshapesGLB.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/16_resize.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/3_loadskybox.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/4_loadIBL.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/19_resize.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/17_resize.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/2_Renderingfalse.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/18_resize.png filter=lfs diff=lfs merge=lfs -text +integration_test/goldens/ios/diffs filter=lfs diff=lfs merge=lfs -text diff --git a/flutter_filament_federated/flutter_filament/example/.gitignore b/flutter_filament_federated/flutter_filament/example/.gitignore new file mode 100644 index 00000000..40b27f75 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/.gitignore @@ -0,0 +1,51 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release + +/android/.cxx/**/* + +# fvm +.fvm/flutter_sdk \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/example/.metadata b/flutter_filament_federated/flutter_filament/example/.metadata new file mode 100644 index 00000000..de6eb858 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "12d54de962782853206992fedce29723fcb4a95b" + channel: "master" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 12d54de962782853206992fedce29723fcb4a95b + base_revision: 12d54de962782853206992fedce29723fcb4a95b + - platform: macos + create_revision: 12d54de962782853206992fedce29723fcb4a95b + base_revision: 12d54de962782853206992fedce29723fcb4a95b + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter_filament_federated/flutter_filament/example/README.md b/flutter_filament_federated/flutter_filament/example/README.md new file mode 100644 index 00000000..8f831b07 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/README.md @@ -0,0 +1,21 @@ +# flutter_filament_example + +Demonstrates how to use the flutter_filament plugin. + +## Linux + +export PKG_CONFIG_PATH=/usr/lib/pkgconfig/:/usr/lib64/pkgconfig/ +export CPLUS_INCLUDE_PATH=/usr/include/gtk-3.0/:/usr/include/pango-1.0/:/usr/include/harfbuzz:/usr/include/cairo/:/usr/include/gdk-pixbuf-2.0/:/usr/include/atk-1.0/ + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/flutter_filament_federated/flutter_filament/example/analysis_options.yaml b/flutter_filament_federated/flutter_filament/example/analysis_options.yaml new file mode 100644 index 00000000..61b6c4de --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/flutter_filament_federated/flutter_filament/example/android/.gitignore b/flutter_filament_federated/flutter_filament/example/android/.gitignore new file mode 100644 index 00000000..473d8bd3 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/.gitignore @@ -0,0 +1,15 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/flutter_filament_federated/flutter_filament/example/android/app/build.gradle b/flutter_filament_federated/flutter_filament/example/android/app/build.gradle new file mode 100644 index 00000000..f5e12798 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/build.gradle @@ -0,0 +1,81 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 34 + ndkVersion "25.2.9519653" + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + applicationId "app.polyvox.flutter_filament_example" + minSdkVersion 22 + targetSdkVersion 31 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + ndk { + abiFilters 'arm64-v8a' // 'x86_64' 'armeabi-v7a' + } + } + + buildTypes { + release { + signingConfig signingConfigs.debug + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile( + 'proguard-android-optimize.txt'), + 'proguard-rules.pro' + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2" + implementation "androidx.annotation:annotation:1.3.0" + implementation "androidx.core:core:1.7.0" + implementation 'net.java.dev.jna:jna:5.10.0@aar' +} diff --git a/flutter_filament_federated/flutter_filament/example/android/app/proguard-rules.pro b/flutter_filament_federated/flutter_filament/example/android/app/proguard-rules.pro new file mode 100644 index 00000000..f67c58ea --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/proguard-rules.pro @@ -0,0 +1,9 @@ +-keep class io.flutter.app.** { *; } +-keep class io.flutter.plugin.** { *; } +-keep class io.flutter.util.** { *; } +-keep class io.flutter.view.** { *; } +-keep class io.flutter.** { *; } +-keep class io.flutter.plugins.** { *; } +-dontwarn java.awt.* +-keep class com.sun.jna.* { *; } +-keepclassmembers class * extends com.sun.jna.* { public *; } \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/debug/AndroidManifest.xml b/flutter_filament_federated/flutter_filament/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..3fac46b6 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/AndroidManifest.xml b/flutter_filament_federated/flutter_filament/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..10e1b0cb --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/kotlin/app/polyvox/flutter_filament_example/MainActivity.kt b/flutter_filament_federated/flutter_filament/example/android/app/src/main/kotlin/app/polyvox/flutter_filament_example/MainActivity.kt new file mode 100644 index 00000000..fbdcbc30 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/src/main/kotlin/app/polyvox/flutter_filament_example/MainActivity.kt @@ -0,0 +1,10 @@ +package app.polyvox.flutter_filament_example + +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.android.TransparencyMode + +class MainActivity: FlutterActivity() { + override fun getTransparencyMode(): TransparencyMode { + return TransparencyMode.transparent + } +} diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/drawable-v21/launch_background.xml b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 00000000..f74085f3 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/drawable/launch_background.xml b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..db77bb4b Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..17987b79 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..09d43914 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..d5f1c8d3 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..4d6372ee Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/values-night/styles.xml b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 00000000..449a9f93 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/values/styles.xml b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..d563b149 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/android/app/src/profile/AndroidManifest.xml b/flutter_filament_federated/flutter_filament/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..3fac46b6 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/flutter_filament_federated/flutter_filament/example/android/build.gradle b/flutter_filament_federated/flutter_filament/example/android/build.gradle new file mode 100644 index 00000000..2f76fefa --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/build.gradle @@ -0,0 +1,30 @@ +buildscript { + ext.kotlin_version = '1.6.0' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/flutter_filament_federated/flutter_filament/example/android/gradle.properties b/flutter_filament_federated/flutter_filament/example/android/gradle.properties new file mode 100644 index 00000000..0387ff25 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/gradle.properties @@ -0,0 +1,9 @@ +org.gradle.jvmargs=-Xmx1536M \ +--add-exports=java.base/sun.nio.ch=ALL-UNNAMED \ +--add-opens=java.base/java.lang=ALL-UNNAMED \ +--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \ +--add-opens=java.base/java.io=ALL-UNNAMED \ +--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED +android.useAndroidX=true +android.enableJetifier=true + diff --git a/flutter_filament_federated/flutter_filament/example/android/gradle/wrapper/gradle-wrapper.properties b/flutter_filament_federated/flutter_filament/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..8048ce64 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/example/android/settings.gradle b/flutter_filament_federated/flutter_filament/example/android/settings.gradle new file mode 100644 index 00000000..121d30d8 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/example/assets/1.glb b/flutter_filament_federated/flutter_filament/example/assets/1.glb new file mode 100644 index 00000000..452cb005 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/1.glb differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/2.glb b/flutter_filament_federated/flutter_filament/example/assets/2.glb new file mode 100644 index 00000000..6ddb654f Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/2.glb differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/3.glb b/flutter_filament_federated/flutter_filament/example/assets/3.glb new file mode 100644 index 00000000..728cd1f7 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/3.glb differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/scene.bin b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/scene.bin new file mode 100644 index 00000000..2f55da9e Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/scene.bin differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/scene.gltf b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/scene.gltf new file mode 100644 index 00000000..a6370a1a --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/scene.gltf @@ -0,0 +1,11876 @@ +{ + "accessors": [ + { + "bufferView": 0, + "byteOffset": 490368, + "componentType": 5126, + "count": 13, + "max": [ + 2.603024959564209, + 2.6610217094421387, + 0.004141807556152344 + ], + "min": [ + -2.603024959564209, + -2.6610217094421387, + -0.004141807556152344 + ], + "type": "VEC3" + }, + { + "bufferView": 0, + "byteOffset": 490524, + "componentType": 5126, + "count": 13, + "max": [ + 0.000011948728570132516, + 0.000011688098311424255, + 1.1920928955078125e-7 + ], + "min": [ + -0.000011948726751143113, + -0.00001168833114206791, + -1.1920928955078125e-7 + ], + "type": "VEC3" + }, + { + "bufferView": 0, + "byteOffset": 490680, + "componentType": 5126, + "count": 13, + "max": [ + 0.5079542994499207, + 0.44970205426216125, + 0.0007009506225585938 + ], + "min": [ + -0.5079542994499207, + -0.44970205426216125, + -0.0007009506225585938 + ], + "type": "VEC3" + }, + { + "bufferView": 0, + "byteOffset": 490836, + "componentType": 5126, + "count": 13, + "max": [ + 0.000027996353310300037, + 0.000027456902898848057, + 1.1920928955078125e-7 + ], + "min": [ + -0.000027996351491310634, + -0.00002745713572949171, + -5.960464477539063e-8 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "componentType": 5126, + "count": 291, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR", + "byteOffset": 0 + }, + { + "bufferView": 2, + "componentType": 5126, + "count": 291, + "max": [ + 0.766411542892456, + -100, + 34.548770904541016 + ], + "min": [ + 0, + -100, + -92.53174591064453 + ], + "type": "VEC3", + "byteOffset": 0 + }, + { + "bufferView": 1, + "byteOffset": 1164, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 3492, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 1172, + "componentType": 5126, + "count": 528, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "componentType": 5126, + "count": 528, + "max": [ + 3.018394628351309e-17, + 0.4277789890766144, + 1.0350706219500598e-16, + 1 + ], + "min": [ + -5.146233374338227e-17, + -0.4226182699203491, + -8.386759746129016e-17, + 0.9038833975791931 + ], + "type": "VEC4", + "byteOffset": 0 + }, + { + "bufferView": 1, + "byteOffset": 3284, + "componentType": 5126, + "count": 1025, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 3516, + "componentType": 5126, + "count": 1025, + "max": [ + 1.0658141036401503e-14, + 0.00003388613185961731, + 0.000014036095308256336 + ], + "min": [ + -7.105427357601002e-15, + 0.00003388613185961731, + 0.000014036095308256336 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 7384, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 15816, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 7392, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 8448, + "componentType": 5126, + "count": 1141, + "max": [ + 0.5891698598861694, + 9.724578803145729e-17, + 1.0542189266883763e-16, + 0.9999997019767761 + ], + "min": [ + -0.10293252021074295, + -1.8182581299328222e-16, + -1.0802358083610882e-16, + 0.8080092072486877 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 11956, + "componentType": 5126, + "count": 199, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 15840, + "componentType": 5126, + "count": 199, + "max": [ + -0.01574668288230896, + -7.34735107421875, + 0.081717349588871 + ], + "min": [ + -0.01574668288230896, + -11.282759666442871, + 0.081717349588871 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 12752, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 18228, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 12760, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 26704, + "componentType": 5126, + "count": 1141, + "max": [ + 8.326672684688674e-17, + 8.326672684688674e-17, + 9.71445146547012e-17, + 1 + ], + "min": [ + -1.3877787807814457e-16, + -1.1102230246251565e-16, + -5.898059818321144e-17, + 1 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 17324, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 18252, + "componentType": 5126, + "count": 2, + "max": [ + 0, + 0, + 0 + ], + "min": [ + 0, + 0, + 0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 17332, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 18276, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 17340, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 44960, + "componentType": 5126, + "count": 1141, + "max": [ + 6.941919929111294e-16, + 0.9612559676170349, + 0.8191520571708679, + 1.4523389702766784e-16 + ], + "min": [ + -7.690622409705619e-16, + -0.6991849541664124, + -0.6942344903945923, + -1.3729081909501104e-16 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 21904, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 18300, + "componentType": 5126, + "count": 2, + "max": [ + 0.00007688588812015951, + -22.9158935546875, + 0.02676698938012123 + ], + "min": [ + 0.00007688588812015951, + -22.9158935546875, + 0.02676698938012123 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 21912, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 18324, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 21920, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 63216, + "componentType": 5126, + "count": 1141, + "max": [ + -3.559834546828236e-23, + -4.1108839354819793e-7, + 4.2806183109312906e-17, + 1 + ], + "min": [ + -3.357394022152527e-16, + -0.130526602268219, + -2.134869384146925e-16, + 0.9914448261260986 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 26484, + "componentType": 5126, + "count": 1016, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 18348, + "componentType": 5126, + "count": 1016, + "max": [ + 1.4210854715202004e-14, + -0.00004080753933521919, + 7.105427357601002e-15 + ], + "min": [ + -7.105427357601002e-15, + -0.00004080753933521919, + -3.552713678800501e-15 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 30548, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 30540, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 30556, + "componentType": 5126, + "count": 1132, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 81472, + "componentType": 5126, + "count": 1132, + "max": [ + 0.4777144193649292, + 0.696681559085846, + -0.12097440659999847, + 0.696681559085846 + ], + "min": [ + 0.12097441405057907, + 0.5213338136672974, + -0.4777144193649292, + 0.5213338136672974 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 35084, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 30564, + "componentType": 5126, + "count": 2, + "max": [ + 0.006630018353462219, + -5.510501384735107, + -0.09275053441524506 + ], + "min": [ + 0.006630018353462219, + -5.510501384735107, + -0.09275053441524506 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 35092, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 30588, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 35100, + "componentType": 5126, + "count": 1094, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 99584, + "componentType": 5126, + "count": 1094, + "max": [ + 3.45120668043819e-7, + 0.755711019039154, + 3.411899740513036e-7, + 0.7933533191680908 + ], + "min": [ + -3.018524452613747e-8, + 0.6087614297866821, + -3.14133004053474e-8, + 0.6549052000045776 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 39476, + "componentType": 5126, + "count": 1058, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 30612, + "componentType": 5126, + "count": 1058, + "max": [ + -9.947598300641403e-14, + -0.000002192010470025707, + -9.079604410544562e-7 + ], + "min": [ + -1.2789769243681803e-13, + -0.000002192010470025707, + -9.07960497897875e-7 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 43708, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 43308, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 43716, + "componentType": 5126, + "count": 1140, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 117088, + "componentType": 5126, + "count": 1140, + "max": [ + 0.648327112197876, + 3.148856819734647e-8, + -2.9930738776329235e-8, + 1 + ], + "min": [ + -0.02535569667816162, + 3.4723754982479704e-9, + -4.330498626359258e-8, + 0.7613618969917297 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 48276, + "componentType": 5126, + "count": 199, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 43332, + "componentType": 5126, + "count": 199, + "max": [ + 0.010783359408378601, + -7.360301494598389, + 0.08223113417625427 + ], + "min": [ + 0.010783359408378601, + -11.28590202331543, + 0.08223113417625427 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 49072, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45720, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 49080, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 135328, + "componentType": 5126, + "count": 1141, + "max": [ + 0.0000031865668006503256, + 1.1102240834163406e-16, + 8.326664082010304e-17, + 1 + ], + "min": [ + 0.0000031865668006503256, + -1.3877787807814457e-16, + -1.1102234216718506e-16, + 1 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 53644, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45744, + "componentType": 5126, + "count": 2, + "max": [ + 0.004904936067759991, + 0.0029711532406508923, + -0.0014322279021143913 + ], + "min": [ + 0.004904936067759991, + 0.0029711532406508923, + -0.0014322279021143913 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 53652, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45768, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 53660, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 153584, + "componentType": 5126, + "count": 1141, + "max": [ + 2.946721479681508e-16, + 0.9721843600273132, + 0.7976794838905334, + 1.0801055108709988e-16 + ], + "min": [ + -3.3080178246791135e-16, + -0.7050051093101501, + -0.706916868686676, + -1.4904984662949747e-16 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 58224, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45792, + "componentType": 5126, + "count": 2, + "max": [ + 0.002689761109650135, + -22.916383743286133, + 0.02693275175988674 + ], + "min": [ + 0.002689761109650135, + -22.916383743286133, + 0.02693275175988674 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 58232, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45816, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 58240, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 171840, + "componentType": 5126, + "count": 1141, + "max": [ + 5.287900693557693e-16, + 0.0033429425675421953, + 1.98237960436973e-15, + 1 + ], + "min": [ + 2.0879800224670911e-16, + -0.13052618503570557, + -1.0767316595280767e-15, + 0.9914448857307434 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 62804, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45840, + "componentType": 5126, + "count": 2, + "max": [ + 0, + 0, + 0 + ], + "min": [ + 0, + 0, + 0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 62812, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45864, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 62820, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 190096, + "componentType": 5126, + "count": 1141, + "max": [ + 0.6187881231307983, + 1.357208038226058e-16, + 1.405753349317774e-16, + 0.9999972581863403 + ], + "min": [ + 0.0023439584765583277, + -1.4041348546440282e-16, + -1.441803997995203e-16, + 0.7855579257011414 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 67384, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45888, + "componentType": 5126, + "count": 2, + "max": [ + 2.4154791831970215, + -4.842290878295898, + -0.006652138661593199 + ], + "min": [ + 2.4154791831970215, + -4.842290878295898, + -0.006652138661593199 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 67392, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45912, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 67400, + "componentType": 5126, + "count": 1074, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 208352, + "componentType": 5126, + "count": 1074, + "max": [ + 2.2694037404499823e-13, + 0.7933533191680908, + 5.5178372315072347e-14, + 0.7933533191680908 + ], + "min": [ + -5.5019523144276064e-14, + 0.6087614297866821, + -2.269895290609933e-13, + 0.6087614297866821 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 71696, + "componentType": 5126, + "count": 23, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 45936, + "componentType": 5126, + "count": 23, + "max": [ + 0.6785002946853638, + -0.37506112456321716, + 4.957866191864014 + ], + "min": [ + 0.6785002946853638, + -0.37506112456321716, + 1.9578661918640137 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 71788, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 46212, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 71796, + "componentType": 5126, + "count": 1058, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 225536, + "componentType": 5126, + "count": 1058, + "max": [ + 1.3877787807814457e-16, + 2.62250594573743e-8, + 7.2789162079351655e-25, + 1 + ], + "min": [ + -1.614377034830916e-16, + 2.62250594573743e-8, + -1.942890293094024e-16, + 1 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 76028, + "componentType": 5126, + "count": 23, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 46236, + "componentType": 5126, + "count": 23, + "max": [ + -19.23712730407715, + -26.57673454284668, + -0.748199999332428 + ], + "min": [ + -26.78019905090332, + -31.10906982421875, + -0.748199999332428 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 76120, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 46512, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 76128, + "componentType": 5126, + "count": 913, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 242464, + "componentType": 5126, + "count": 913, + "max": [ + 0.1889660805463791, + -0.6813896298408508, + 0.1889660656452179, + 0.6813896298408508 + ], + "min": [ + 0.1889660805463791, + -0.6813896298408508, + 0.1889660656452179, + 0.6813896298408508 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 79780, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 46536, + "componentType": 5126, + "count": 2, + "max": [ + 0.01226816326379776, + 0.00024394220963586122, + 0.0002562310837674886 + ], + "min": [ + 0.01226816326379776, + 0.00024394220963586122, + 0.0002562310837674886 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 79788, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 46560, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 79796, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 257072, + "componentType": 5126, + "count": 1141, + "max": [ + 0.7071067690849304, + 2.4532694660665106e-16, + 2.0842673711801571e-16, + 0.9999963045120239 + ], + "min": [ + -0.03856799378991127, + -1.783470619137986e-16, + -1.6837262692005858e-16, + 0.7071067690849304 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 84360, + "componentType": 5126, + "count": 199, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 46584, + "componentType": 5126, + "count": 199, + "max": [ + 0.1428087055683136, + -7.303253173828125, + 0.08181961625814438 + ], + "min": [ + 0.05688011273741722, + -11.236658096313477, + 0.08181961625814438 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 85156, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 48972, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 85164, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 275328, + "componentType": 5126, + "count": 1141, + "max": [ + 0.000012702583262580447, + 0.000003925847522623371, + -0.010920972563326359, + 0.9999403357505798 + ], + "min": [ + 0.000012702583262580447, + 0.000003925847522623371, + -0.010920972563326359, + 0.9999403357505798 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 89728, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 48996, + "componentType": 5126, + "count": 2, + "max": [ + -0.004460121039301157, + 0.000007818744961696211, + 0.00005186478665564209 + ], + "min": [ + -0.004460121039301157, + 0.000007818744961696211, + 0.00005186478665564209 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 89736, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49020, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 89744, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 293584, + "componentType": 5126, + "count": 1141, + "max": [ + 3.20862724334609e-16, + 0.9717717170715332, + 0.7435351014137268, + 1.614297890189907e-16 + ], + "min": [ + -5.413126573875361e-16, + -0.705666184425354, + -0.6964223980903625, + -8.255817716906362e-17 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 94308, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49044, + "componentType": 5126, + "count": 2, + "max": [ + 0.0002644560590852052, + -22.915939331054688, + 0.026753252372145653 + ], + "min": [ + 0.0002644560590852052, + -22.915939331054688, + 0.026753252372145653 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 94316, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49068, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 94324, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 311840, + "componentType": 5126, + "count": 1141, + "max": [ + 1.195374466078647e-9, + 0.1054544672369957, + 2.520133251659052e-14, + 1 + ], + "min": [ + -3.591690217505763e-16, + -0.13052618503570557, + -3.68308051971241e-15, + 0.9914448857307434 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 98888, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49092, + "componentType": 5126, + "count": 2, + "max": [ + 0, + 0, + 0 + ], + "min": [ + 0, + 0, + 0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 98896, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49116, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 98904, + "componentType": 5126, + "count": 1141, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 330096, + "componentType": 5126, + "count": 1141, + "max": [ + 0.5984764695167542, + 1.7411764252628359e-9, + 1.0605889453239737e-16, + 1 + ], + "min": [ + -0.014889945276081562, + -8.390695802355788e-17, + -2.3159511641779318e-8, + 0.8011403679847717 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 103468, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49140, + "componentType": 5126, + "count": 2, + "max": [ + -2.415479898452759, + -4.84229040145874, + -0.006640426814556122 + ], + "min": [ + -2.415479898452759, + -4.84229040145874, + -0.006640426814556122 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 103476, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49164, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 103484, + "componentType": 5126, + "count": 1078, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 348352, + "componentType": 5126, + "count": 1078, + "max": [ + 3.052628814873351e-14, + -0.6410675048828125, + 3.0506660701279734e-14, + 0.7674844861030579 + ], + "min": [ + -6.372444347375883e-14, + -0.7933533191680908, + -6.362619442814091e-14, + 0.6087614297866821 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 107796, + "componentType": 5126, + "count": 29, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49188, + "componentType": 5126, + "count": 29, + "max": [ + -0.6784976124763489, + -0.3758923411369324, + 4.957706451416016 + ], + "min": [ + -0.6784976124763489, + -0.37716609239578247, + 1.9577068090438843 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 107912, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49536, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 107920, + "componentType": 5126, + "count": 1058, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 365600, + "componentType": 5126, + "count": 1058, + "max": [ + 0.0002122838923241943, + 2.747205307684908e-8, + -5.831902235436948e-12, + 1 + ], + "min": [ + 0.0002122838923241943, + 2.747205307684908e-8, + -5.832034074421122e-12, + 1 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 112152, + "componentType": 5126, + "count": 23, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49560, + "componentType": 5126, + "count": 23, + "max": [ + 26.78019905090332, + -26.57673454284668, + -0.748199999332428 + ], + "min": [ + 19.23712730407715, + -31.10906982421875, + -0.748199999332428 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 112244, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49836, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 112252, + "componentType": 5126, + "count": 966, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 382528, + "componentType": 5126, + "count": 966, + "max": [ + 0.1889660805463791, + 0.6813896298408508, + -0.1889660656452179, + 0.6813896298408508 + ], + "min": [ + 0.1889660805463791, + 0.6813896298408508, + -0.1889660656452179, + 0.6813896298408508 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 116116, + "componentType": 5126, + "count": 27, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 49860, + "componentType": 5126, + "count": 27, + "max": [ + -22.55685806274414, + -8.625173568725586, + 0.14466851949691772 + ], + "min": [ + -28.345199584960938, + -10.20475959777832, + 0.14466851949691772 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 116224, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 50184, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 116232, + "componentType": 5126, + "count": 958, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 397984, + "componentType": 5126, + "count": 958, + "max": [ + 0.09390988200902939, + -0.7008429765701294, + 0.09390988200902939, + 0.7008430361747742 + ], + "min": [ + 0.09390988200902939, + -0.7008429765701294, + 0.09390988200902939, + 0.7008430361747742 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 120064, + "componentType": 5126, + "count": 27, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 50208, + "componentType": 5126, + "count": 27, + "max": [ + 28.230527877807617, + -9.64864730834961, + -0.07694999873638153 + ], + "min": [ + 22.442184448242188, + -11.228233337402344, + -0.07694999873638153 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 120172, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 50532, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 120180, + "componentType": 5126, + "count": 971, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 413312, + "componentType": 5126, + "count": 971, + "max": [ + 0.09390988200902939, + 0.7008429765701294, + -0.09390988200902939, + 0.7008430361747742 + ], + "min": [ + 0.09390988200902939, + 0.7008429765701294, + -0.09390988200902939, + 0.7008430361747742 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 124064, + "componentType": 5126, + "count": 859, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 50556, + "componentType": 5126, + "count": 859, + "max": [ + 5.329070518200751e-15, + 38.9765510559082, + -3.073050022125244 + ], + "min": [ + -7.105427357601002e-15, + 33.4765510559082, + -3.073050022125244 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 127500, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 60864, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 127508, + "componentType": 5126, + "count": 998, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 428848, + "componentType": 5126, + "count": 998, + "max": [ + 5.551115123125783e-17, + 1.1102230246251565e-16, + 5.551115123125783e-17, + 1 + ], + "min": [ + -6.938893903907228e-17, + -8.326672684688674e-17, + -5.551115123125783e-17, + 1 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 131500, + "componentType": 5126, + "count": 824, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 60888, + "componentType": 5126, + "count": 824, + "max": [ + 3.552713678800501e-15, + -0.018226023763418198, + -8.908537864685059 + ], + "min": [ + -7.105427357601002e-15, + -0.018226023763418198, + -8.908537864685059 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 134796, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70776, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 134804, + "componentType": 5126, + "count": 1142, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 444816, + "componentType": 5126, + "count": 1142, + "max": [ + 0.002140095690265298, + 1, + 0.04749816656112671, + 0.08700844645500183 + ], + "min": [ + -0.002407652325928211, + 0.9933873414993286, + -0.02874644845724106, + -0.11379626393318176 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 139372, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70800, + "componentType": 5126, + "count": 2, + "max": [ + -0.000021889296476729214, + -36.155147552490234, + -10.966755867004395 + ], + "min": [ + -0.000021889296476729214, + -36.155147552490234, + -10.966755867004395 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 139380, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70824, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 139388, + "componentType": 5126, + "count": 1216, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 463088, + "componentType": 5126, + "count": 1216, + "max": [ + 0.8032023310661316, + 0.6148953437805176, + 0.8032018542289734, + 0.614924967288971 + ], + "min": [ + -0.5634948015213013, + -0.4302464425563812, + -0.5672827363014221, + -0.4291868805885315 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 144252, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70848, + "componentType": 5126, + "count": 2, + "max": [ + 19.973400115966797, + 24.55685043334961, + -6.007046699523926 + ], + "min": [ + 19.973400115966797, + 24.55685043334961, + -6.007046699523926 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 144260, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70872, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 144268, + "componentType": 5126, + "count": 1174, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 482544, + "componentType": 5126, + "count": 1174, + "max": [ + 0.6970846056938171, + 0.6561663746833801, + 0.6592297554016113, + 0.6099482774734497 + ], + "min": [ + -0.6526466608047485, + -0.652332067489624, + -0.6243375539779663, + -0.49005988240242004 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 148964, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70896, + "componentType": 5126, + "count": 2, + "max": [ + 0.000051651491958182305, + -36.1551513671875, + -10.966744422912598 + ], + "min": [ + 0.000051651491958182305, + -36.1551513671875, + -10.966744422912598 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 148972, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70920, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 148980, + "componentType": 5126, + "count": 1216, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 501328, + "componentType": 5126, + "count": 1216, + "max": [ + 0.8032023310661316, + 0.6148953437805176, + 0.8032018542289734, + 0.614924967288971 + ], + "min": [ + -0.5647227764129639, + -0.45769572257995605, + -0.567910373210907, + -0.431105375289917 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 153844, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70944, + "componentType": 5126, + "count": 2, + "max": [ + -19.973400115966797, + 24.556848526000977, + -6.007049560546875 + ], + "min": [ + -19.973400115966797, + 24.556848526000977, + -6.007049560546875 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 153852, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70968, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 153860, + "componentType": 5126, + "count": 1174, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 520784, + "componentType": 5126, + "count": 1174, + "max": [ + 0.697971761226654, + 0.5453841686248779, + 0.6412535309791565, + 0.6099480986595154 + ], + "min": [ + -0.49868083000183105, + -0.5850634574890137, + -0.5260052680969238, + -0.4971546530723572 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 158556, + "componentType": 5126, + "count": 1044, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 70992, + "componentType": 5126, + "count": 1044, + "max": [ + 0.30994635820388794, + 88.4124526977539, + 3.357822895050049 + ], + "min": [ + 0, + 0.11856790632009506, + -12.910046577453613 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 162732, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 83520, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 162740, + "componentType": 5126, + "count": 1059, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 539568, + "componentType": 5126, + "count": 1059, + "max": [ + 0.8156683444976807, + 0.10349708050489426, + 0.07732612639665604, + 0.7898205518722534 + ], + "min": [ + 0.6133379936218262, + -0.15155479311943054, + -0.13645820319652557, + 0.5717355012893677 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 166976, + "componentType": 5126, + "count": 279, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 83544, + "componentType": 5126, + "count": 279, + "max": [ + 0, + 0, + 21.310029983520508 + ], + "min": [ + 0, + 0, + -42.39506530761719 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 168092, + "componentType": 5126, + "count": 2, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 86892, + "componentType": 5126, + "count": 2, + "max": [ + 1, + 1, + 1 + ], + "min": [ + 1, + 1, + 1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 168100, + "componentType": 5126, + "count": 367, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 3, + "byteOffset": 556512, + "componentType": 5126, + "count": 367, + "max": [ + 8.359196102885279e-17, + 0.9999496340751648, + 8.359196102885279e-17, + 1 + ], + "min": [ + -8.659445459885287e-17, + -0.8649336099624634, + -8.659445459885287e-17, + -0.4979607164859772 + ], + "type": "VEC4" + }, + { + "bufferView": 1, + "byteOffset": 169568, + "componentType": 5126, + "count": 509, + "max": [ + 25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 171604, + "componentType": 5126, + "count": 1018, + "max": [ + 1 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5125, + "count": 18, + "max": [ + 6 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 7, + "max": [ + 0, + 0, + -1 + ], + "min": [ + 0, + 0, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 7, + "max": [ + 180, + 155.8845672607422, + 0 + ], + "min": [ + -180, + -155.8845672607422, + 0 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 7, + "max": [ + 1, + 6.123234262925839e-17, + 0, + 1 + ], + "min": [ + 1, + 0, + 0, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 7, + "max": [ + 1, + 0.9330127239227295 + ], + "min": [ + 0, + 0.06698727607727051 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 7, + "max": [ + 1, + 0.9330127239227295 + ], + "min": [ + 0, + 0.06698727607727051 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 6624, + "max": [ + 1597 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1598, + "max": [ + 0.9999938607215881, + 1, + 1 + ], + "min": [ + -0.9999938607215881, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1598, + "max": [ + 24.47800064086914, + 40.60210037231445, + 43.78879928588867 + ], + "min": [ + -24.47800064086914, + -39.97100067138672, + -32.2958984375 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1598, + "max": [ + 1, + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1598, + "max": [ + 0.9494781494140625, + 0.9984400272369385 + ], + "min": [ + 0.050515174865722656, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1598, + "max": [ + 0.9494781494140625, + 0.9984400272369385 + ], + "min": [ + 0.050515174865722656, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1598, + "max": [ + 0.9494781494140625, + 0.9984400272369385 + ], + "min": [ + 0.050515174865722656, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1598, + "max": [ + 0.9494781494140625, + 0.9984400272369385 + ], + "min": [ + 0.050515174865722656, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1598, + "max": [ + 0.9494781494140625, + 0.9984400272369385 + ], + "min": [ + 0.050515174865722656, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 192, + "max": [ + 59 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9462724328041077, + 0.00002637715806486085, + 0.9238796234130859 + ], + "min": [ + -0.9462687969207764, + -0.9339421987533569, + -0.9238765835762024 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 3.158555030822754, + 0, + 2.7355499267578125 + ], + "min": [ + -3.158555030822754, + -4.489299774169922, + -2.7355499267578125 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.6912197470664978, + 0.8588380813598633, + 0.9905509352684021, + 1 + ], + "min": [ + -0.6913442611694336, + -1, + -0.6705939173698425, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9791259765625, + 0.6324005126953125 + ], + "min": [ + 0.0011079907417297363, + 0.229583740234375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9791259765625, + 0.6324005126953125 + ], + "min": [ + 0.0011079907417297363, + 0.229583740234375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9791259765625, + 0.6324005126953125 + ], + "min": [ + 0.0011079907417297363, + 0.229583740234375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9791259765625, + 0.6324005126953125 + ], + "min": [ + 0.0011079907417297363, + 0.229583740234375 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 2.8378965854644775, + 2.837851047515869, + 3.1812357902526855 + ], + "min": [ + -2.8378965854644775, + -2.837851047515869, + -3.1812357902526855 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9705880284309387, + 0.970474362373352, + 0.9334462881088257, + 1 + ], + "min": [ + -0.9705855250358582, + -0.9705935716629028, + -0.9999987483024597, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.98150634765625, + 0.9824953079223633 + ], + "min": [ + 0.011077880859375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.98150634765625, + 0.9824953079223633 + ], + "min": [ + 0.011077880859375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.98150634765625, + 0.9824953079223633 + ], + "min": [ + 0.011077880859375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.98150634765625, + 0.9824953079223633 + ], + "min": [ + 0.011077880859375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 4872, + "max": [ + 1512 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 3.8741042613983154, + 1.7617741823196411, + 3.0504395961761475 + ], + "min": [ + -3.9423036575317383, + -22.016210556030273, + -4.033937454223633 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 1, + 0.9999995827674866, + 0.9992985129356384, + 1 + ], + "min": [ + -1, + -1, + -0.9996975660324097, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 0.998046875, + 0.9980460405349731 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 0.998046875, + 0.9980460405349731 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 0.998046875, + 0.9980460405349731 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 0.998046875, + 0.9980460405349731 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 2.805872678756714, + 2.503127098083496, + 2.5030744075775146 + ], + "min": [ + -2.8058857917785645, + -2.503126382827759, + -2.5030744075775146 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9999423027038574, + 0.9715058207511902, + 0.9705548882484436, + 1 + ], + "min": [ + -0.9334924221038818, + -0.970590353012085, + -0.970612645149231, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.8618621826171875, + 0.997859001159668 + ], + "min": [ + 0.03627777099609375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.8618621826171875, + 0.997859001159668 + ], + "min": [ + 0.03627777099609375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.8618621826171875, + 0.997859001159668 + ], + "min": [ + 0.03627777099609375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.8618621826171875, + 0.997859001159668 + ], + "min": [ + 0.03627777099609375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 4128, + "max": [ + 1189 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 6.140176773071289, + 7.9751200675964355, + 9.091413497924805 + ], + "min": [ + -6.138557434082031, + -12.837050437927246, + -2.774056911468506 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9986715912818909, + 1, + 0.932191789150238, + 1 + ], + "min": [ + -1, + -1, + -0.9457818865776062, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9821929931640625, + 0.9979920387268066 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9821929931640625, + 0.9979920387268066 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9821929931640625, + 0.9979920387268066 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9821929931640625, + 0.9979920387268066 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 192, + "max": [ + 59 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9462646245956421, + 0.00006607881368836388, + 0.9043453931808472 + ], + "min": [ + -0.9462745189666748, + -0.9273982048034668, + -0.904350757598877 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 2.1719820499420166, + -4.440892098500626e-16, + 2.284182071685791 + ], + "min": [ + -2.1719820499420166, + -8.425638198852539, + -2.284182071685791 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.6912132501602173, + 0.8564750552177429, + 0.9907793998718262, + 1 + ], + "min": [ + -0.6912415623664856, + -1, + -0.6705775260925293, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.5562744140625, + 0.8839511871337891 + ], + "min": [ + 0.24591445922851562, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.5562744140625, + 0.8839511871337891 + ], + "min": [ + 0.24591445922851562, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.5562744140625, + 0.8839511871337891 + ], + "min": [ + 0.24591445922851562, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.5562744140625, + 0.8839511871337891 + ], + "min": [ + 0.24591445922851562, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 2.805861473083496, + 2.503016948699951, + 2.503002166748047 + ], + "min": [ + -2.8058581352233887, + -2.5030174255371094, + -2.503002166748047 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9334709048271179, + 0.9943826198577881, + 0.9705744981765747, + 1 + ], + "min": [ + -0.9999973773956299, + -0.9915933012962341, + -0.9705973267555237, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9977874755859375, + 0.9978030323982239 + ], + "min": [ + 0.011077880859375, + 0.0384979248046875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9977874755859375, + 0.9978030323982239 + ], + "min": [ + 0.011077880859375, + 0.0384979248046875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9977874755859375, + 0.9978030323982239 + ], + "min": [ + 0.011077880859375, + 0.0384979248046875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9977874755859375, + 0.9978030323982239 + ], + "min": [ + 0.011077880859375, + 0.0384979248046875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 3792, + "max": [ + 1128 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -0.7994152307510376, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 6.352692127227783, + 7.272726058959961, + 6.740703105926514 + ], + "min": [ + -6.337584495544434, + -25.38535499572754, + -2.6904826164245605 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.9445861577987671, + 1, + 0.9917267560958862, + 1 + ], + "min": [ + -0.999998927116394, + -1, + -0.9903827905654907, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.99798583984375, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.054290771484375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.99798583984375, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.054290771484375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.99798583984375, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.054290771484375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.99798583984375, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.054290771484375 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 858, + "max": [ + 209 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.9999997615814209, + 0.9804182648658752, + 0.9717621207237244 + ], + "min": [ + -0.9999998211860657, + -0.9752709269523621, + -0.9717718958854675 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 22.505199432373047, + 16.118268966674805, + 0.014730009250342846 + ], + "min": [ + -19.017000198364258, + -16.7448787689209, + -12.467525482177734 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.7160800695419312, + 0.9986988306045532, + 0.9983847141265869, + 1 + ], + "min": [ + -0.9804638028144836, + -0.9959992170333862, + -0.9985447525978088, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.3270263671875, + 0.9985079765319824 + ], + "min": [ + 0.013447999954223633, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.3270263671875, + 0.9985079765319824 + ], + "min": [ + 0.013447999954223633, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.3270263671875, + 0.9985079765319824 + ], + "min": [ + 0.013447999954223633, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.3270263671875, + 0.9985079765319824 + ], + "min": [ + 0.013447999954223633, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.3270263671875, + 0.9985079765319824 + ], + "min": [ + 0.013447999954223633, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 684, + "max": [ + 181 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.9812500476837158, + 0.98042231798172, + 0.9717556834220886 + ], + "min": [ + -0.9812499284744263, + -0.9752631783485413, + -0.9804222583770752 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 22.49679946899414, + 16.087291717529297, + 0.015429569408297539 + ], + "min": [ + -22.48870086669922, + -16.78112030029297, + -7.136616230010986 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.6957566142082214, + 0.9961112141609192, + 0.9974663853645325, + 1 + ], + "min": [ + -0.7036730647087097, + -0.9936772584915161, + -0.9909072518348694, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.34142303466796875, + 0.9984639883041382 + ], + "min": [ + 0.04077434539794922, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.34142303466796875, + 0.9984639883041382 + ], + "min": [ + 0.04077434539794922, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.34142303466796875, + 0.9984639883041382 + ], + "min": [ + 0.04077434539794922, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.34142303466796875, + 0.9984639883041382 + ], + "min": [ + 0.04077434539794922, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.34142303466796875, + 0.9984639883041382 + ], + "min": [ + 0.04077434539794922, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 192, + "max": [ + 59 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9203706383705139, + 0.08052149415016174, + 0.9462553858757019 + ], + "min": [ + -0.9203649163246155, + -0.9591649174690247, + -0.9462553858757019 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 5.528401851654053, + 0.8937630653381348, + 3.1585500240325928 + ], + "min": [ + -0.07819413393735886, + -3.9569084644317627, + -3.1585500240325928 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.6124923825263977, + 0.8991279602050781, + 0.6859615445137024, + -1 + ], + "min": [ + -0.9984928965568542, + -0.9968492984771729, + -0.6886578798294067, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.511199951171875, + 0.9978490471839905 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.511199951171875, + 0.9978490471839905 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.511199951171875, + 0.9978490471839905 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.511199951171875, + 0.9978490471839905 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 3.1813101768493652, + 2.837909698486328, + 2.837886095046997 + ], + "min": [ + -3.181349039077759, + -2.837909698486328, + -2.837886095046997 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9334935545921326, + 0.9705367088317871, + 0.9705860018730164, + -1 + ], + "min": [ + -0.9999493956565857, + -0.9706282615661621, + -0.9704942107200623, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9978485107421875, + 0.9978020191192627 + ], + "min": [ + 0.005537986755371094, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9978485107421875, + 0.9978020191192627 + ], + "min": [ + 0.005537986755371094, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9978485107421875, + 0.9978020191192627 + ], + "min": [ + 0.005537986755371094, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9978485107421875, + 0.9978020191192627 + ], + "min": [ + 0.005537986755371094, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 4872, + "max": [ + 1512 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 3.944369077682495, + 1.761652946472168, + 3.050240993499756 + ], + "min": [ + -3.873849868774414, + -22.01688575744629, + -4.03395414352417 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 1, + 0.9999986886978149, + 0.9997035264968872, + -1 + ], + "min": [ + -1, + -1, + -0.999306321144104, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 0.998046875, + 0.9980520009994507 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 0.998046875, + 0.9980520009994507 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 0.998046875, + 0.9980520009994507 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1513, + "max": [ + 0.998046875, + 0.9980520009994507 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 2.8058583736419678, + 2.503086566925049, + 2.5030324459075928 + ], + "min": [ + -2.8059232234954834, + -2.5030837059020996, + -2.5030324459075928 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9334862232208252, + 0.9717816710472107, + 0.9705871343612671, + -1 + ], + "min": [ + -0.9999354481697083, + -0.9705882668495178, + -0.9704800844192505, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9752960205078125, + 0.997859001159668 + ], + "min": [ + 0.04209327697753906, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9752960205078125, + 0.997859001159668 + ], + "min": [ + 0.04209327697753906, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9752960205078125, + 0.997859001159668 + ], + "min": [ + 0.04209327697753906, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9752960205078125, + 0.997859001159668 + ], + "min": [ + 0.04209327697753906, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 4128, + "max": [ + 1189 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 6.134866237640381, + 7.972114086151123, + 9.091575622558594 + ], + "min": [ + -6.143898010253906, + -12.839866638183594, + -2.773728847503662 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 1, + 1, + 0.9237611889839172, + -1 + ], + "min": [ + -0.9987005591392517, + -1, + -0.9384349584579468, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9978179931640625, + 0.9980350136756897 + ], + "min": [ + 0.011077880859375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9978179931640625, + 0.9980350136756897 + ], + "min": [ + 0.011077880859375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9978179931640625, + 0.9980350136756897 + ], + "min": [ + 0.011077880859375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9978179931640625, + 0.9980350136756897 + ], + "min": [ + 0.011077880859375, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 192, + "max": [ + 59 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9462710022926331, + 0.00001421624983777292, + 0.9043461680412292 + ], + "min": [ + -0.9462725520133972, + -0.9274078011512756, + -0.9043479561805725 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 2.1718454360961914, + -3.3487545825520645e-14, + 2.2841246128082275 + ], + "min": [ + -2.1718454360961914, + -8.425505638122559, + -2.2841246128082275 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.6912213563919067, + 0.8617174625396729, + 0.9907815456390381, + -1 + ], + "min": [ + -0.6912751197814941, + -1, + -0.6705557703971863, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.39041900634765625, + 0.9979940056800842 + ], + "min": [ + 0.029907703399658203, + 0.2353973388671875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.39041900634765625, + 0.9979940056800842 + ], + "min": [ + 0.029907703399658203, + 0.2353973388671875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.39041900634765625, + 0.9979940056800842 + ], + "min": [ + 0.029907703399658203, + 0.2353973388671875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.39041900634765625, + 0.9979940056800842 + ], + "min": [ + 0.029907703399658203, + 0.2353973388671875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 2.805884599685669, + 2.503038167953491, + 2.5029942989349365 + ], + "min": [ + -2.8058927059173584, + -2.503038167953491, + -2.5029942989349365 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9334784746170044, + 0.9944380521774292, + 0.9705901741981506, + -1 + ], + "min": [ + -0.9999455809593201, + -0.9916284084320068, + -0.9705632925033569, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9980010986328125, + 0.9980420470237732 + ], + "min": [ + 0.023261547088623047, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9980010986328125, + 0.9980420470237732 + ], + "min": [ + 0.023261547088623047, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9980010986328125, + 0.9980420470237732 + ], + "min": [ + 0.023261547088623047, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9980010986328125, + 0.9980420470237732 + ], + "min": [ + 0.023261547088623047, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 3792, + "max": [ + 1128 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.9999979138374329, + 0.9999978542327881, + 1 + ], + "min": [ + -0.9999978542327881, + -0.8000316023826599, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 6.356159210205078, + 7.2811970710754395, + 6.741055011749268 + ], + "min": [ + -6.334109306335449, + -25.386653900146484, + -2.690229654312134 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.9999987483024597, + 0.9999978542327881, + 0.9899260401725769, + -1 + ], + "min": [ + -0.9441795349121094, + -0.9999979138374329, + -0.9884353280067444, + -1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.97637939453125, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.97637939453125, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.97637939453125, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.97637939453125, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 858, + "max": [ + 209 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.9999998211860657, + 0.9804549217224121, + 0.9718173146247864 + ], + "min": [ + -0.9999997615814209, + -0.9752144813537598, + -0.9718270897865295 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 19.017000198364258, + 16.119686126708984, + 0.017575301229953766 + ], + "min": [ + -22.505199432373047, + -16.74315071105957, + -12.473467826843262 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.7163847088813782, + 0.9960353970527649, + 0.9985222220420837, + 1 + ], + "min": [ + -0.9804637432098389, + -0.9986840486526489, + -0.9983941912651062, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.986541748046875, + 0.9985079765319824 + ], + "min": [ + 0.6729278564453125, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.986541748046875, + 0.9985079765319824 + ], + "min": [ + 0.6729278564453125, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.986541748046875, + 0.9985079765319824 + ], + "min": [ + 0.6729278564453125, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.986541748046875, + 0.9985079765319824 + ], + "min": [ + 0.6729278564453125, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 210, + "max": [ + 0.986541748046875, + 0.9985079765319824 + ], + "min": [ + 0.6729278564453125, + 0.1425018310546875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 684, + "max": [ + 181 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.9812499284744263, + 0.9804224371910095, + 0.9717556834220886 + ], + "min": [ + -0.9812500476837158, + -0.9752631783485413, + -0.9804222583770752 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 22.488698959350586, + 16.08729362487793, + 0.015429651364684105 + ], + "min": [ + -22.49679946899414, + -16.7811222076416, + -7.136616230010986 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.7016284465789795, + 0.993878185749054, + 0.9915738105773926, + 1 + ], + "min": [ + -0.7065384984016418, + -0.9980297684669495, + -0.9960659742355347, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.9592132568359375, + 0.9984700083732605 + ], + "min": [ + 0.6585693359375, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.9592132568359375, + 0.9984700083732605 + ], + "min": [ + 0.6585693359375, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.9592132568359375, + 0.9984700083732605 + ], + "min": [ + 0.6585693359375, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.9592132568359375, + 0.9984700083732605 + ], + "min": [ + 0.6585693359375, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 182, + "max": [ + 0.9592132568359375, + 0.9984700083732605 + ], + "min": [ + 0.6585693359375, + 0.16192626953125 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 192, + "max": [ + 59 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9203649163246155, + 0.08052149415016174, + 0.9462553858757019 + ], + "min": [ + -0.9203706383705139, + -0.9591649174690247, + -0.9462553858757019 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.07819413393735886, + 0.8937630653381348, + 3.1585500240325928 + ], + "min": [ + -5.528401851654053, + -3.9569084644317627, + -3.1585500240325928 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9984928965568542, + 0.900946855545044, + 0.6860498189926147, + 1 + ], + "min": [ + -0.6124934554100037, + -0.9968502521514893, + -0.6886581778526306, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.997955322265625, + 0.9978790283203125 + ], + "min": [ + 0.14649581909179688, + 0.2284698486328125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.997955322265625, + 0.9978790283203125 + ], + "min": [ + 0.14649581909179688, + 0.2284698486328125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.997955322265625, + 0.9978790283203125 + ], + "min": [ + 0.14649581909179688, + 0.2284698486328125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.997955322265625, + 0.9978790283203125 + ], + "min": [ + 0.14649581909179688, + 0.2284698486328125 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 3.181283950805664, + 2.837909698486328, + 2.837886095046997 + ], + "min": [ + -3.181283950805664, + -2.837909698486328, + -2.837886095046997 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9999459981918335, + 0.9705654978752136, + 0.9705774784088135, + 1 + ], + "min": [ + -0.9334567785263062, + -0.9705967903137207, + -0.9705893993377686, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9878692626953125, + 0.9980520009994507 + ], + "min": [ + 0.037108421325683594, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9878692626953125, + 0.9980520009994507 + ], + "min": [ + 0.037108421325683594, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9878692626953125, + 0.9980520009994507 + ], + "min": [ + 0.037108421325683594, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9878692626953125, + 0.9980520009994507 + ], + "min": [ + 0.037108421325683594, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 4872, + "max": [ + 1456 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1457, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1457, + "max": [ + 3.8742127418518066, + 1.7617069482803345, + 3.050255298614502 + ], + "min": [ + -3.9421558380126953, + -22.016254425048828, + -4.034045219421387 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1457, + "max": [ + 1, + 0.9999988079071045, + 0.999301552772522, + 1 + ], + "min": [ + -1, + -1, + -0.9996956586837769, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1457, + "max": [ + 0.998046875, + 0.997937023639679 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1457, + "max": [ + 0.998046875, + 0.997937023639679 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1457, + "max": [ + 0.998046875, + 0.997937023639679 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1457, + "max": [ + 0.998046875, + 0.997937023639679 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 1, + 0.9987014532089233, + 0.9986981749534607 + ], + "min": [ + -1, + -0.9987033605575562, + -0.9986976981163025 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 2.805882692337036, + 2.4998340606689453, + 2.4997761249542236 + ], + "min": [ + -2.805903196334839, + -2.4998345375061035, + -2.4997763633728027 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9999436140060425, + 0.9696629643440247, + 0.969977080821991, + 1 + ], + "min": [ + -0.9334853291511536, + -0.9695192575454712, + -0.9701146483421326, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9880218505859375, + 0.9815201759338379 + ], + "min": [ + 0.03489208221435547, + 0.0645294189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9880218505859375, + 0.9815201759338379 + ], + "min": [ + 0.03489208221435547, + 0.0645294189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9880218505859375, + 0.9815201759338379 + ], + "min": [ + 0.03489208221435547, + 0.0645294189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9880218505859375, + 0.9815201759338379 + ], + "min": [ + 0.03489208221435547, + 0.0645294189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 4128, + "max": [ + 1189 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 6.144484043121338, + 7.975264549255371, + 9.09143352508545 + ], + "min": [ + -6.134279727935791, + -12.836573600769043, + -2.7741191387176514 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.9986706972122192, + 1, + 0.9321260452270508, + 1 + ], + "min": [ + -1, + -1, + -0.9456865191459656, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.969451904296875, + 0.9978950023651123 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.969451904296875, + 0.9978950023651123 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.969451904296875, + 0.9978950023651123 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1190, + "max": [ + 0.969451904296875, + 0.9978950023651123 + ], + "min": [ + 0.0011079907417297363, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 192, + "max": [ + 59 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.9460511803627014, + 0.020673329010605812, + 0.9043437838554382 + ], + "min": [ + -0.9460495114326477, + -0.9307563900947571, + -0.9043524265289307 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 2.2373239994049072, + -5.258825228852005e-15, + 2.284106492996216 + ], + "min": [ + -2.2373239994049072, + -8.501056671142578, + -2.284106492996216 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.7061308026313782, + 0.8601000308990479, + 0.9907819628715515, + 1 + ], + "min": [ + -0.6760434508323669, + -0.9998863935470581, + -0.6705630421638489, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.882232666015625, + 0.9979940056800842 + ], + "min": [ + 0.14953994750976562, + 0.4477996826171875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.882232666015625, + 0.9979940056800842 + ], + "min": [ + 0.14953994750976562, + 0.4477996826171875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.882232666015625, + 0.9979940056800842 + ], + "min": [ + 0.14953994750976562, + 0.4477996826171875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 60, + "max": [ + 0.882232666015625, + 0.9979940056800842 + ], + "min": [ + 0.14953994750976562, + 0.4477996826171875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 2736, + "max": [ + 668 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9997609853744507, + 0.9997621774673462, + 1 + ], + "min": [ + -0.9997605681419373, + -0.9997619986534119, + -1 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 2.814361095428467, + 2.5024404525756836, + 2.5029942989349365 + ], + "min": [ + -2.814356803894043, + -2.5024402141571045, + -2.5029942989349365 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.9410112500190735, + 0.9957802891731262, + 0.9705701470375061, + 1 + ], + "min": [ + -0.9999746680259705, + -0.9924947619438171, + -0.9705852270126343, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.950103759765625, + 0.9767532348632812 + ], + "min": [ + 0.005815982818603516, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.950103759765625, + 0.9767532348632812 + ], + "min": [ + 0.005815982818603516, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.950103759765625, + 0.9767532348632812 + ], + "min": [ + 0.005815982818603516, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 669, + "max": [ + 0.950103759765625, + 0.9767532348632812 + ], + "min": [ + 0.005815982818603516, + 0.0011138916015625 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 3792, + "max": [ + 1128 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.9997616410255432, + 0.9998812675476074, + 0.9998799562454224 + ], + "min": [ + -0.9997621774673462, + -0.8040514588356018, + -0.9998816251754761 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 6.410318374633789, + 7.331780910491943, + 6.804128170013428 + ], + "min": [ + -6.276950359344482, + -25.39360809326172, + -2.7138583660125732 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.9514473676681519, + 0.9999784231185913, + 0.9934725165367126, + 1 + ], + "min": [ + -0.9999739527702332, + -0.9999784827232361, + -0.9883590936660767, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.971954345703125, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.0448760986328125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.971954345703125, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.0448760986328125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.971954345703125, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.0448760986328125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1129, + "max": [ + 0.971954345703125, + 0.9980530142784119 + ], + "min": [ + 0.0011079907417297363, + 0.0448760986328125 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 198, + "max": [ + 47 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.9800400733947754, + 0.9815039038658142, + 0.9692381620407104 + ], + "min": [ + -0.9800400733947754, + -0.9815108776092529, + -0.009044792503118515 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 22.25983238220215, + 3.6992530785930143e-16, + 5.172183990478516 + ], + "min": [ + -22.703067779541016, + -2.035116672515869, + -4.854550361633301 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.711862325668335, + 0.009239021688699722, + 1, + 1 + ], + "min": [ + -0.7126688957214355, + -0.9862862229347229, + -0.9999582171440125, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.34128570556640625, + 0.3702392578125 + ], + "min": [ + 0.2750701904296875, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.34128570556640625, + 0.3702392578125 + ], + "min": [ + 0.2750701904296875, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.34128570556640625, + 0.3702392578125 + ], + "min": [ + 0.2750701904296875, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.34128570556640625, + 0.3702392578125 + ], + "min": [ + 0.2750701904296875, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.34128570556640625, + 0.3702392578125 + ], + "min": [ + 0.2750701904296875, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 198, + "max": [ + 47 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.9800400733947754, + 0.9815039038658142, + 0.9692381620407104 + ], + "min": [ + -0.9800400733947754, + -0.9815108776092529, + -0.00904479343444109 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 22.481449127197266, + 1.0175585746765137, + 5.013367176055908 + ], + "min": [ + -22.481449127197266, + -1.0175585746765137, + -5.013367176055908 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.7118115425109863, + 0.9863398671150208, + 0.999962568283081, + 1 + ], + "min": [ + -0.7124660015106201, + -0.0099171232432127, + -0.9999998807907104, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.72491455078125, + 0.37017822265625 + ], + "min": [ + 0.658599853515625, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.72491455078125, + 0.37017822265625 + ], + "min": [ + 0.658599853515625, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.72491455078125, + 0.37017822265625 + ], + "min": [ + 0.658599853515625, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.72491455078125, + 0.37017822265625 + ], + "min": [ + 0.658599853515625, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 48, + "max": [ + 0.72491455078125, + 0.37017822265625 + ], + "min": [ + 0.658599853515625, + 0.1679534912109375 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 198, + "max": [ + 51 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 52, + "max": [ + 0.980785071849823, + 0.963556170463562, + 0.980782151222229 + ], + "min": [ + -0.980785071849823, + 0, + -0.9807981252670288 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 52, + "max": [ + 5.742680072784424, + 7.674149990081787, + 16.58354949951172 + ], + "min": [ + -5.742680072784424, + -7.674149990081787, + -16.58354949951172 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 52, + "max": [ + -0.000021119056327734143, + 1, + 0.7062842845916748, + 1 + ], + "min": [ + -0.9896541237831116, + -1, + -0.7070288062095642, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 52, + "max": [ + 0.27196502685546875, + 0.6553955078125 + ], + "min": [ + 0.14226150512695312, + 0.457794189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 52, + "max": [ + 0.27196502685546875, + 0.6553955078125 + ], + "min": [ + 0.14226150512695312, + 0.457794189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 52, + "max": [ + 0.27196502685546875, + 0.6553955078125 + ], + "min": [ + 0.14226150512695312, + 0.457794189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 52, + "max": [ + 0.27196502685546875, + 0.6553955078125 + ], + "min": [ + 0.14226150512695312, + 0.457794189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 52, + "max": [ + 0.27196502685546875, + 0.6553955078125 + ], + "min": [ + 0.14226150512695312, + 0.457794189453125 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 324, + "max": [ + 60 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 61, + "max": [ + 0.9253151416778564, + 0.9224124550819397, + 0.9999999403953552 + ], + "min": [ + -0.9253151416778564, + -0.922246515750885, + 0.3791990280151367 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 61, + "max": [ + 3.422339916229248, + 3.4983837604522705, + 1.0367803573608398 + ], + "min": [ + -3.422339916229248, + -3.4988362789154053, + -0.0045692152343690395 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 61, + "max": [ + -0.37807369232177734, + 0.16984163224697113, + 0.923377513885498, + 1 + ], + "min": [ + -1, + -0.25828370451927185, + -0.922590970993042, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 61, + "max": [ + 0.5171157717704773, + 0.4423835277557373 + ], + "min": [ + 0.48266905546188354, + 0.4072730541229248 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 61, + "max": [ + 0.5171157717704773, + 0.4423835277557373 + ], + "min": [ + 0.48266905546188354, + 0.4072730541229248 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 61, + "max": [ + 0.5171157717704773, + 0.4423835277557373 + ], + "min": [ + 0.48266905546188354, + 0.4072730541229248 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 61, + "max": [ + 0.5171157717704773, + 0.4423835277557373 + ], + "min": [ + 0.48266905546188354, + 0.4072730541229248 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 61, + "max": [ + 0.5171157717704773, + 0.4423835277557373 + ], + "min": [ + 0.48266905546188354, + 0.4072730541229248 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 36, + "max": [ + 12 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 13, + "max": [ + 0.00007492514851037413, + -0.0015094821574166417, + -0.9999987483024597 + ], + "min": [ + -0.00007492515578633174, + -0.0015759739326313138, + -0.999998927116394 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 13, + "max": [ + 0.5206102132797241, + 0.5319043397903442, + -9.52561092376709 + ], + "min": [ + -0.5205997824668884, + -0.5325044393539429, + -9.527267456054688 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 13, + "max": [ + 1, + 0.0016572648892179132, + 0.00007750481745461002, + 1 + ], + "min": [ + 0.9999986290931702, + -0.001644145231693983, + -0.000077527787652798, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 13, + "max": [ + 0.5069850087165833, + 0.45840930938720703 + ], + "min": [ + 0.492599755525589, + 0.44371509552001953 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 13, + "max": [ + 0.5069850087165833, + 0.45840930938720703 + ], + "min": [ + 0.492599755525589, + 0.44371509552001953 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 13, + "max": [ + 0.5069850087165833, + 0.45840930938720703 + ], + "min": [ + 0.492599755525589, + 0.44371509552001953 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 13, + "max": [ + 0.5069850087165833, + 0.45840930938720703 + ], + "min": [ + 0.492599755525589, + 0.44371509552001953 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 13, + "max": [ + 0.5069850087165833, + 0.45840930938720703 + ], + "min": [ + 0.492599755525589, + 0.44371509552001953 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 6768, + "max": [ + 1394 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 1, + 0.9952672719955444, + 0.9951035976409912 + ], + "min": [ + -1, + -0.9998235106468201, + -0.999494731426239 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 37.781776428222656, + 7.368798732757568, + 5.318163871765137 + ], + "min": [ + -37.78172302246094, + -72.43864440917969, + -26.958742141723633 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.9951720833778381, + 0.9952999949455261, + 0.9998140335083008, + 1 + ], + "min": [ + -0.9951794147491455, + -0.9994944930076599, + -0.9952681660652161, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.9985809326171875, + 0.998432993888855 + ], + "min": [ + 0.587646484375, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.9985809326171875, + 0.998432993888855 + ], + "min": [ + 0.587646484375, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.9985809326171875, + 0.998432993888855 + ], + "min": [ + 0.587646484375, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.9985809326171875, + 0.998432993888855 + ], + "min": [ + 0.587646484375, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.9985809326171875, + 0.998432993888855 + ], + "min": [ + 0.587646484375, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 4896, + "max": [ + 1187 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9985098242759705, + 1, + 0.9985183477401733 + ], + "min": [ + -0.9985097050666809, + -1, + -0.9985119104385376 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 32.348899841308594, + 5.063899993896484, + 32.348899841308594 + ], + "min": [ + -32.348899841308594, + -5.063899993896484, + -32.34890365600586 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9971701502799988, + 0.9981505870819092, + 1, + 1 + ], + "min": [ + -0.9971259236335754, + -0.9981384873390198, + -1, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9985198974609375, + 0.9985760450363159 + ], + "min": [ + 0.5195770263671875, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9985198974609375, + 0.9985760450363159 + ], + "min": [ + 0.5195770263671875, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9985198974609375, + 0.9985760450363159 + ], + "min": [ + 0.5195770263671875, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9985198974609375, + 0.9985760450363159 + ], + "min": [ + 0.5195770263671875, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9985198974609375, + 0.9985760450363159 + ], + "min": [ + 0.5195770263671875, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 6768, + "max": [ + 1394 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 1, + 0.9952672719955444, + 0.9951035976409912 + ], + "min": [ + -1, + -0.9998235702514648, + -0.999494731426239 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 37.78175354003906, + 7.36879825592041, + 5.3181657791137695 + ], + "min": [ + -37.7817497253418, + -72.43864440917969, + -26.958721160888672 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.9951218962669373, + 0.9994943141937256, + 0.9952681660652161, + 1 + ], + "min": [ + -0.9952056407928467, + -0.9952999949455261, + -0.9998233318328857, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.4123382568359375, + 0.9985350370407104 + ], + "min": [ + 0.001408994197845459, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.4123382568359375, + 0.9985350370407104 + ], + "min": [ + 0.001408994197845459, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.4123382568359375, + 0.9985350370407104 + ], + "min": [ + 0.001408994197845459, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.4123382568359375, + 0.9985350370407104 + ], + "min": [ + 0.001408994197845459, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1395, + "max": [ + 0.4123382568359375, + 0.9985350370407104 + ], + "min": [ + 0.001408994197845459, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5125, + "count": 4896, + "max": [ + 1187 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9985119104385376, + 1, + 0.9985097646713257 + ], + "min": [ + -0.9985182881355286, + -1, + -0.9985126256942749 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 32.348899841308594, + 5.063899993896484, + 32.348899841308594 + ], + "min": [ + -32.348899841308594, + -5.063899993896484, + -32.348899841308594 + ], + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.9999992251396179, + 0.9981393814086914, + 0.9971155524253845, + 1 + ], + "min": [ + -0.9999951124191284, + -0.998076856136322, + -0.9971383810043335, + 1 + ], + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.48041534423828125, + 0.9985830187797546 + ], + "min": [ + 0.001475989818572998, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.48041534423828125, + 0.9985830187797546 + ], + "min": [ + 0.001475989818572998, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.48041534423828125, + 0.9985830187797546 + ], + "min": [ + 0.001475989818572998, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.48041534423828125, + 0.9985830187797546 + ], + "min": [ + 0.001475989818572998, + 0.00115966796875 + ], + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 1188, + "max": [ + 0.48041534423828125, + 0.9985830187797546 + ], + "min": [ + 0.001475989818572998, + 0.00115966796875 + ], + "type": "VEC2" + } + ], + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "node": 10, + "path": "translation" + } + }, + { + "sampler": 1, + "target": { + "node": 10, + "path": "scale" + } + }, + { + "sampler": 2, + "target": { + "node": 10, + "path": "rotation" + } + }, + { + "sampler": 3, + "target": { + "node": 33, + "path": "translation" + } + }, + { + "sampler": 4, + "target": { + "node": 33, + "path": "scale" + } + }, + { + "sampler": 5, + "target": { + "node": 33, + "path": "rotation" + } + }, + { + "sampler": 6, + "target": { + "node": 29, + "path": "translation" + } + }, + { + "sampler": 7, + "target": { + "node": 29, + "path": "scale" + } + }, + { + "sampler": 8, + "target": { + "node": 29, + "path": "rotation" + } + }, + { + "sampler": 9, + "target": { + "node": 27, + "path": "translation" + } + }, + { + "sampler": 10, + "target": { + "node": 27, + "path": "scale" + } + }, + { + "sampler": 11, + "target": { + "node": 27, + "path": "rotation" + } + }, + { + "sampler": 12, + "target": { + "node": 25, + "path": "translation" + } + }, + { + "sampler": 13, + "target": { + "node": 25, + "path": "scale" + } + }, + { + "sampler": 14, + "target": { + "node": 25, + "path": "rotation" + } + }, + { + "sampler": 15, + "target": { + "node": 23, + "path": "translation" + } + }, + { + "sampler": 16, + "target": { + "node": 23, + "path": "scale" + } + }, + { + "sampler": 17, + "target": { + "node": 23, + "path": "rotation" + } + }, + { + "sampler": 18, + "target": { + "node": 21, + "path": "translation" + } + }, + { + "sampler": 19, + "target": { + "node": 21, + "path": "scale" + } + }, + { + "sampler": 20, + "target": { + "node": 21, + "path": "rotation" + } + }, + { + "sampler": 21, + "target": { + "node": 53, + "path": "translation" + } + }, + { + "sampler": 22, + "target": { + "node": 53, + "path": "scale" + } + }, + { + "sampler": 23, + "target": { + "node": 53, + "path": "rotation" + } + }, + { + "sampler": 24, + "target": { + "node": 49, + "path": "translation" + } + }, + { + "sampler": 25, + "target": { + "node": 49, + "path": "scale" + } + }, + { + "sampler": 26, + "target": { + "node": 49, + "path": "rotation" + } + }, + { + "sampler": 27, + "target": { + "node": 47, + "path": "translation" + } + }, + { + "sampler": 28, + "target": { + "node": 47, + "path": "scale" + } + }, + { + "sampler": 29, + "target": { + "node": 47, + "path": "rotation" + } + }, + { + "sampler": 30, + "target": { + "node": 45, + "path": "translation" + } + }, + { + "sampler": 31, + "target": { + "node": 45, + "path": "scale" + } + }, + { + "sampler": 32, + "target": { + "node": 45, + "path": "rotation" + } + }, + { + "sampler": 33, + "target": { + "node": 43, + "path": "translation" + } + }, + { + "sampler": 34, + "target": { + "node": 43, + "path": "scale" + } + }, + { + "sampler": 35, + "target": { + "node": 43, + "path": "rotation" + } + }, + { + "sampler": 36, + "target": { + "node": 41, + "path": "translation" + } + }, + { + "sampler": 37, + "target": { + "node": 41, + "path": "scale" + } + }, + { + "sampler": 38, + "target": { + "node": 41, + "path": "rotation" + } + }, + { + "sampler": 39, + "target": { + "node": 37, + "path": "translation" + } + }, + { + "sampler": 40, + "target": { + "node": 37, + "path": "scale" + } + }, + { + "sampler": 41, + "target": { + "node": 37, + "path": "rotation" + } + }, + { + "sampler": 42, + "target": { + "node": 35, + "path": "translation" + } + }, + { + "sampler": 43, + "target": { + "node": 35, + "path": "scale" + } + }, + { + "sampler": 44, + "target": { + "node": 35, + "path": "rotation" + } + }, + { + "sampler": 45, + "target": { + "node": 73, + "path": "translation" + } + }, + { + "sampler": 46, + "target": { + "node": 73, + "path": "scale" + } + }, + { + "sampler": 47, + "target": { + "node": 73, + "path": "rotation" + } + }, + { + "sampler": 48, + "target": { + "node": 69, + "path": "translation" + } + }, + { + "sampler": 49, + "target": { + "node": 69, + "path": "scale" + } + }, + { + "sampler": 50, + "target": { + "node": 69, + "path": "rotation" + } + }, + { + "sampler": 51, + "target": { + "node": 67, + "path": "translation" + } + }, + { + "sampler": 52, + "target": { + "node": 67, + "path": "scale" + } + }, + { + "sampler": 53, + "target": { + "node": 67, + "path": "rotation" + } + }, + { + "sampler": 54, + "target": { + "node": 65, + "path": "translation" + } + }, + { + "sampler": 55, + "target": { + "node": 65, + "path": "scale" + } + }, + { + "sampler": 56, + "target": { + "node": 65, + "path": "rotation" + } + }, + { + "sampler": 57, + "target": { + "node": 63, + "path": "translation" + } + }, + { + "sampler": 58, + "target": { + "node": 63, + "path": "scale" + } + }, + { + "sampler": 59, + "target": { + "node": 63, + "path": "rotation" + } + }, + { + "sampler": 60, + "target": { + "node": 61, + "path": "translation" + } + }, + { + "sampler": 61, + "target": { + "node": 61, + "path": "scale" + } + }, + { + "sampler": 62, + "target": { + "node": 61, + "path": "rotation" + } + }, + { + "sampler": 63, + "target": { + "node": 57, + "path": "translation" + } + }, + { + "sampler": 64, + "target": { + "node": 57, + "path": "scale" + } + }, + { + "sampler": 65, + "target": { + "node": 57, + "path": "rotation" + } + }, + { + "sampler": 66, + "target": { + "node": 55, + "path": "translation" + } + }, + { + "sampler": 67, + "target": { + "node": 55, + "path": "scale" + } + }, + { + "sampler": 68, + "target": { + "node": 55, + "path": "rotation" + } + }, + { + "sampler": 69, + "target": { + "node": 75, + "path": "translation" + } + }, + { + "sampler": 70, + "target": { + "node": 75, + "path": "scale" + } + }, + { + "sampler": 71, + "target": { + "node": 75, + "path": "rotation" + } + }, + { + "sampler": 72, + "target": { + "node": 77, + "path": "translation" + } + }, + { + "sampler": 73, + "target": { + "node": 77, + "path": "scale" + } + }, + { + "sampler": 74, + "target": { + "node": 77, + "path": "rotation" + } + }, + { + "sampler": 75, + "target": { + "node": 79, + "path": "translation" + } + }, + { + "sampler": 76, + "target": { + "node": 79, + "path": "scale" + } + }, + { + "sampler": 77, + "target": { + "node": 79, + "path": "rotation" + } + }, + { + "sampler": 78, + "target": { + "node": 83, + "path": "translation" + } + }, + { + "sampler": 79, + "target": { + "node": 83, + "path": "scale" + } + }, + { + "sampler": 80, + "target": { + "node": 83, + "path": "rotation" + } + }, + { + "sampler": 81, + "target": { + "node": 87, + "path": "translation" + } + }, + { + "sampler": 82, + "target": { + "node": 87, + "path": "scale" + } + }, + { + "sampler": 83, + "target": { + "node": 87, + "path": "rotation" + } + }, + { + "sampler": 84, + "target": { + "node": 85, + "path": "translation" + } + }, + { + "sampler": 85, + "target": { + "node": 85, + "path": "scale" + } + }, + { + "sampler": 86, + "target": { + "node": 85, + "path": "rotation" + } + }, + { + "sampler": 87, + "target": { + "node": 91, + "path": "translation" + } + }, + { + "sampler": 88, + "target": { + "node": 91, + "path": "scale" + } + }, + { + "sampler": 89, + "target": { + "node": 91, + "path": "rotation" + } + }, + { + "sampler": 90, + "target": { + "node": 89, + "path": "translation" + } + }, + { + "sampler": 91, + "target": { + "node": 89, + "path": "scale" + } + }, + { + "sampler": 92, + "target": { + "node": 89, + "path": "rotation" + } + }, + { + "sampler": 93, + "target": { + "node": 13, + "path": "translation" + } + }, + { + "sampler": 94, + "target": { + "node": 13, + "path": "scale" + } + }, + { + "sampler": 95, + "target": { + "node": 13, + "path": "rotation" + } + }, + { + "sampler": 96, + "target": { + "node": 9, + "path": "translation" + } + }, + { + "sampler": 97, + "target": { + "node": 9, + "path": "scale" + } + }, + { + "sampler": 98, + "target": { + "node": 9, + "path": "rotation" + } + }, + { + "sampler": 99, + "target": { + "node": 84, + "path": "weights" + } + } + ], + "name": "CINEMA_4D_Basis", + "samplers": [ + { + "input": 4, + "interpolation": "LINEAR", + "output": 5 + }, + { + "input": 6, + "interpolation": "LINEAR", + "output": 7 + }, + { + "input": 8, + "interpolation": "LINEAR", + "output": 9 + }, + { + "input": 10, + "interpolation": "LINEAR", + "output": 11 + }, + { + "input": 12, + "interpolation": "LINEAR", + "output": 13 + }, + { + "input": 14, + "interpolation": "LINEAR", + "output": 15 + }, + { + "input": 16, + "interpolation": "LINEAR", + "output": 17 + }, + { + "input": 18, + "interpolation": "LINEAR", + "output": 19 + }, + { + "input": 20, + "interpolation": "LINEAR", + "output": 21 + }, + { + "input": 22, + "interpolation": "LINEAR", + "output": 23 + }, + { + "input": 24, + "interpolation": "LINEAR", + "output": 25 + }, + { + "input": 26, + "interpolation": "LINEAR", + "output": 27 + }, + { + "input": 28, + "interpolation": "LINEAR", + "output": 29 + }, + { + "input": 30, + "interpolation": "LINEAR", + "output": 31 + }, + { + "input": 32, + "interpolation": "LINEAR", + "output": 33 + }, + { + "input": 34, + "interpolation": "LINEAR", + "output": 35 + }, + { + "input": 36, + "interpolation": "LINEAR", + "output": 37 + }, + { + "input": 38, + "interpolation": "LINEAR", + "output": 39 + }, + { + "input": 40, + "interpolation": "LINEAR", + "output": 41 + }, + { + "input": 42, + "interpolation": "LINEAR", + "output": 43 + }, + { + "input": 44, + "interpolation": "LINEAR", + "output": 45 + }, + { + "input": 46, + "interpolation": "LINEAR", + "output": 47 + }, + { + "input": 48, + "interpolation": "LINEAR", + "output": 49 + }, + { + "input": 50, + "interpolation": "LINEAR", + "output": 51 + }, + { + "input": 52, + "interpolation": "LINEAR", + "output": 53 + }, + { + "input": 54, + "interpolation": "LINEAR", + "output": 55 + }, + { + "input": 56, + "interpolation": "LINEAR", + "output": 57 + }, + { + "input": 58, + "interpolation": "LINEAR", + "output": 59 + }, + { + "input": 60, + "interpolation": "LINEAR", + "output": 61 + }, + { + "input": 62, + "interpolation": "LINEAR", + "output": 63 + }, + { + "input": 64, + "interpolation": "LINEAR", + "output": 65 + }, + { + "input": 66, + "interpolation": "LINEAR", + "output": 67 + }, + { + "input": 68, + "interpolation": "LINEAR", + "output": 69 + }, + { + "input": 70, + "interpolation": "LINEAR", + "output": 71 + }, + { + "input": 72, + "interpolation": "LINEAR", + "output": 73 + }, + { + "input": 74, + "interpolation": "LINEAR", + "output": 75 + }, + { + "input": 76, + "interpolation": "LINEAR", + "output": 77 + }, + { + "input": 78, + "interpolation": "LINEAR", + "output": 79 + }, + { + "input": 80, + "interpolation": "LINEAR", + "output": 81 + }, + { + "input": 82, + "interpolation": "LINEAR", + "output": 83 + }, + { + "input": 84, + "interpolation": "LINEAR", + "output": 85 + }, + { + "input": 86, + "interpolation": "LINEAR", + "output": 87 + }, + { + "input": 88, + "interpolation": "LINEAR", + "output": 89 + }, + { + "input": 90, + "interpolation": "LINEAR", + "output": 91 + }, + { + "input": 92, + "interpolation": "LINEAR", + "output": 93 + }, + { + "input": 94, + "interpolation": "LINEAR", + "output": 95 + }, + { + "input": 96, + "interpolation": "LINEAR", + "output": 97 + }, + { + "input": 98, + "interpolation": "LINEAR", + "output": 99 + }, + { + "input": 100, + "interpolation": "LINEAR", + "output": 101 + }, + { + "input": 102, + "interpolation": "LINEAR", + "output": 103 + }, + { + "input": 104, + "interpolation": "LINEAR", + "output": 105 + }, + { + "input": 106, + "interpolation": "LINEAR", + "output": 107 + }, + { + "input": 108, + "interpolation": "LINEAR", + "output": 109 + }, + { + "input": 110, + "interpolation": "LINEAR", + "output": 111 + }, + { + "input": 112, + "interpolation": "LINEAR", + "output": 113 + }, + { + "input": 114, + "interpolation": "LINEAR", + "output": 115 + }, + { + "input": 116, + "interpolation": "LINEAR", + "output": 117 + }, + { + "input": 118, + "interpolation": "LINEAR", + "output": 119 + }, + { + "input": 120, + "interpolation": "LINEAR", + "output": 121 + }, + { + "input": 122, + "interpolation": "LINEAR", + "output": 123 + }, + { + "input": 124, + "interpolation": "LINEAR", + "output": 125 + }, + { + "input": 126, + "interpolation": "LINEAR", + "output": 127 + }, + { + "input": 128, + "interpolation": "LINEAR", + "output": 129 + }, + { + "input": 130, + "interpolation": "LINEAR", + "output": 131 + }, + { + "input": 132, + "interpolation": "LINEAR", + "output": 133 + }, + { + "input": 134, + "interpolation": "LINEAR", + "output": 135 + }, + { + "input": 136, + "interpolation": "LINEAR", + "output": 137 + }, + { + "input": 138, + "interpolation": "LINEAR", + "output": 139 + }, + { + "input": 140, + "interpolation": "LINEAR", + "output": 141 + }, + { + "input": 142, + "interpolation": "LINEAR", + "output": 143 + }, + { + "input": 144, + "interpolation": "LINEAR", + "output": 145 + }, + { + "input": 146, + "interpolation": "LINEAR", + "output": 147 + }, + { + "input": 148, + "interpolation": "LINEAR", + "output": 149 + }, + { + "input": 150, + "interpolation": "LINEAR", + "output": 151 + }, + { + "input": 152, + "interpolation": "LINEAR", + "output": 153 + }, + { + "input": 154, + "interpolation": "LINEAR", + "output": 155 + }, + { + "input": 156, + "interpolation": "LINEAR", + "output": 157 + }, + { + "input": 158, + "interpolation": "LINEAR", + "output": 159 + }, + { + "input": 160, + "interpolation": "LINEAR", + "output": 161 + }, + { + "input": 162, + "interpolation": "LINEAR", + "output": 163 + }, + { + "input": 164, + "interpolation": "LINEAR", + "output": 165 + }, + { + "input": 166, + "interpolation": "LINEAR", + "output": 167 + }, + { + "input": 168, + "interpolation": "LINEAR", + "output": 169 + }, + { + "input": 170, + "interpolation": "LINEAR", + "output": 171 + }, + { + "input": 172, + "interpolation": "LINEAR", + "output": 173 + }, + { + "input": 174, + "interpolation": "LINEAR", + "output": 175 + }, + { + "input": 176, + "interpolation": "LINEAR", + "output": 177 + }, + { + "input": 178, + "interpolation": "LINEAR", + "output": 179 + }, + { + "input": 180, + "interpolation": "LINEAR", + "output": 181 + }, + { + "input": 182, + "interpolation": "LINEAR", + "output": 183 + }, + { + "input": 184, + "interpolation": "LINEAR", + "output": 185 + }, + { + "input": 186, + "interpolation": "LINEAR", + "output": 187 + }, + { + "input": 188, + "interpolation": "LINEAR", + "output": 189 + }, + { + "input": 190, + "interpolation": "LINEAR", + "output": 191 + }, + { + "input": 192, + "interpolation": "LINEAR", + "output": 193 + }, + { + "input": 194, + "interpolation": "LINEAR", + "output": 195 + }, + { + "input": 196, + "interpolation": "LINEAR", + "output": 197 + }, + { + "input": 198, + "interpolation": "LINEAR", + "output": 199 + }, + { + "input": 200, + "interpolation": "LINEAR", + "output": 201 + }, + { + "input": 202, + "interpolation": "LINEAR", + "output": 203 + } + ] + } + ], + "asset": { + "extras": { + "author": "LaVADraGoN (https://sketchfab.com/lavadragon)", + "license": "CC-BY-NC-4.0 (http://creativecommons.org/licenses/by-nc/4.0/)", + "source": "https://sketchfab.com/3d-models/buster-drone-294e79652f494130ad2ab00a13fdbafd", + "title": "Buster Drone" + }, + "generator": "Sketchfab-7.38.0", + "version": "2.0" + }, + "bufferViews": [ + { + "buffer": 0, + "byteLength": 614976, + "byteOffset": 0, + "byteStride": 12, + "name": "floatBufferViews", + "target": 34962 + }, + { + "buffer": 0, + "byteLength": 175676, + "byteOffset": 614976, + "name": "floatBufferViews" + }, + { + "buffer": 0, + "byteLength": 86916, + "byteOffset": 790652, + "byteStride": 12, + "name": "floatBufferViews" + }, + { + "buffer": 0, + "byteLength": 562384, + "byteOffset": 877568, + "byteStride": 16, + "name": "floatBufferViews" + }, + { + "buffer": 0, + "byteOffset": 1439952, + "byteLength": 354 + }, + { + "buffer": 0, + "byteOffset": 1440308, + "byteLength": 24007 + }, + { + "buffer": 0, + "byteOffset": 1464316, + "byteLength": 1381 + }, + { + "buffer": 0, + "byteOffset": 1465700, + "byteLength": 9138 + }, + { + "buffer": 0, + "byteOffset": 1474840, + "byteLength": 20853 + }, + { + "buffer": 0, + "byteOffset": 1495696, + "byteLength": 9029 + }, + { + "buffer": 0, + "byteOffset": 1504728, + "byteLength": 16918 + }, + { + "buffer": 0, + "byteOffset": 1521648, + "byteLength": 1435 + }, + { + "buffer": 0, + "byteOffset": 1523084, + "byteLength": 9013 + }, + { + "buffer": 0, + "byteOffset": 1532100, + "byteLength": 15509 + }, + { + "buffer": 0, + "byteOffset": 1547612, + "byteLength": 4226 + }, + { + "buffer": 0, + "byteOffset": 1551840, + "byteLength": 3250 + }, + { + "buffer": 0, + "byteOffset": 1555092, + "byteLength": 1382 + }, + { + "buffer": 0, + "byteOffset": 1556476, + "byteLength": 9352 + }, + { + "buffer": 0, + "byteOffset": 1565828, + "byteLength": 21051 + }, + { + "buffer": 0, + "byteOffset": 1586880, + "byteLength": 9282 + }, + { + "buffer": 0, + "byteOffset": 1596164, + "byteLength": 16939 + }, + { + "buffer": 0, + "byteOffset": 1613104, + "byteLength": 1384 + }, + { + "buffer": 0, + "byteOffset": 1614488, + "byteLength": 9284 + }, + { + "buffer": 0, + "byteOffset": 1623772, + "byteLength": 15464 + }, + { + "buffer": 0, + "byteOffset": 1639236, + "byteLength": 4109 + }, + { + "buffer": 0, + "byteOffset": 1643348, + "byteLength": 3147 + }, + { + "buffer": 0, + "byteOffset": 1646496, + "byteLength": 1396 + }, + { + "buffer": 0, + "byteOffset": 1647892, + "byteLength": 9088 + }, + { + "buffer": 0, + "byteOffset": 1656980, + "byteLength": 20226 + }, + { + "buffer": 0, + "byteOffset": 1677208, + "byteLength": 9096 + }, + { + "buffer": 0, + "byteOffset": 1686304, + "byteLength": 16935 + }, + { + "buffer": 0, + "byteOffset": 1703240, + "byteLength": 1378 + }, + { + "buffer": 0, + "byteOffset": 1704620, + "byteLength": 9040 + }, + { + "buffer": 0, + "byteOffset": 1713660, + "byteLength": 15560 + }, + { + "buffer": 0, + "byteOffset": 1729220, + "byteLength": 1310 + }, + { + "buffer": 0, + "byteOffset": 1730532, + "byteLength": 1346 + }, + { + "buffer": 0, + "byteOffset": 1731880, + "byteLength": 1325 + }, + { + "buffer": 0, + "byteOffset": 1733208, + "byteLength": 1847 + }, + { + "buffer": 0, + "byteOffset": 1735056, + "byteLength": 719 + }, + { + "buffer": 0, + "byteOffset": 1735776, + "byteLength": 18693 + }, + { + "buffer": 0, + "byteOffset": 1754472, + "byteLength": 17770 + }, + { + "buffer": 0, + "byteOffset": 1772244, + "byteLength": 20941 + }, + { + "buffer": 0, + "byteOffset": 1793188, + "byteLength": 17590 + } + ], + "buffers": [ + { + "name": "scene", + "byteLength": 1810780, + "uri": "scene.bin" + } + ], + "images": [ + { + "name": "Boden_baseColor", + "uri": "textures/Boden_baseColor.jpg" + }, + { + "name": "Boden_metallicRoughness", + "uri": "textures/Boden_metallicRoughness.jpg" + }, + { + "name": "Boden_normal", + "uri": "textures/Boden_normal.jpg" + }, + { + "name": "body_baseColor", + "uri": "textures/body_baseColor.jpg" + }, + { + "name": "body_metallicRoughness", + "uri": "textures/body_metallicRoughness.jpg" + }, + { + "name": "body_emissive", + "uri": "textures/body_emissive.jpg" + }, + { + "name": "body_normal", + "uri": "textures/body_normal.jpg" + }, + { + "name": "material_baseColor", + "uri": "textures/material_baseColor.jpg" + }, + { + "name": "material_metallicRoughness", + "uri": "textures/material_metallicRoughness.jpg" + }, + { + "name": "material_normal", + "uri": "textures/material_normal.jpg" + } + ], + "materials": [ + { + "doubleSided": false, + "name": "Boden", + "normalTexture": { + "index": 2, + "scale": 1, + "texCoord": 0 + }, + "pbrMetallicRoughness": { + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "baseColorTexture": { + "index": 0, + "texCoord": 0 + }, + "metallicFactor": 1, + "metallicRoughnessTexture": { + "index": 1, + "texCoord": 0 + }, + "roughnessFactor": 1 + }, + "emissiveFactor": [ + 0, + 0, + 0 + ] + }, + { + "doubleSided": false, + "emissiveFactor": [ + 1, + 1, + 1 + ], + "emissiveTexture": { + "index": 5, + "texCoord": 0 + }, + "name": "body", + "normalTexture": { + "index": 6, + "scale": 1, + "texCoord": 0 + }, + "occlusionTexture": { + "index": 4, + "strength": 1, + "texCoord": 0 + }, + "pbrMetallicRoughness": { + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "baseColorTexture": { + "index": 3, + "texCoord": 0 + }, + "metallicFactor": 1, + "metallicRoughnessTexture": { + "index": 4, + "texCoord": 0 + }, + "roughnessFactor": 1 + } + }, + { + "doubleSided": false, + "name": "material", + "normalTexture": { + "index": 9, + "scale": 1, + "texCoord": 0 + }, + "occlusionTexture": { + "index": 8, + "strength": 1, + "texCoord": 0 + }, + "pbrMetallicRoughness": { + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "baseColorTexture": { + "index": 7, + "texCoord": 0 + }, + "metallicFactor": 1, + "metallicRoughnessTexture": { + "index": 8, + "texCoord": 0 + }, + "roughnessFactor": 1 + }, + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE" + } + ], + "meshes": [ + { + "name": "Scheibe_Boden_0", + "primitives": [ + { + "attributes": { + "NORMAL": 205, + "POSITION": 206, + "TANGENT": 207, + "TEXCOORD_0": 208, + "TEXCOORD_1": 209 + }, + "indices": 204, + "material": 0, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 4, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4 + } + } + } + } + ] + }, + { + "name": "Drone_Body_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 211, + "POSITION": 212, + "TANGENT": 213, + "TEXCOORD_0": 214, + "TEXCOORD_1": 215, + "TEXCOORD_2": 216, + "TEXCOORD_3": 217, + "TEXCOORD_4": 218 + }, + "indices": 210, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 5, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_leg_F_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 220, + "POSITION": 221, + "TANGENT": 222, + "TEXCOORD_0": 223, + "TEXCOORD_1": 224, + "TEXCOORD_2": 225, + "TEXCOORD_3": 226 + }, + "indices": 219, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 6, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "F_P1_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 228, + "POSITION": 229, + "TANGENT": 230, + "TEXCOORD_0": 231, + "TEXCOORD_1": 232, + "TEXCOORD_2": 233, + "TEXCOORD_3": 234 + }, + "indices": 227, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 7, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "F_P2_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 236, + "POSITION": 237, + "TANGENT": 238, + "TEXCOORD_0": 239, + "TEXCOORD_1": 240, + "TEXCOORD_2": 241, + "TEXCOORD_3": 242 + }, + "indices": 235, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 8, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "F_P3_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 244, + "POSITION": 245, + "TANGENT": 246, + "TEXCOORD_0": 247, + "TEXCOORD_1": 248, + "TEXCOORD_2": 249, + "TEXCOORD_3": 250 + }, + "indices": 243, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 9, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "F_P4_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 252, + "POSITION": 253, + "TANGENT": 254, + "TEXCOORD_0": 255, + "TEXCOORD_1": 256, + "TEXCOORD_2": 257, + "TEXCOORD_3": 258 + }, + "indices": 251, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 10, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "F_P5_M_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 260, + "POSITION": 261, + "TANGENT": 262, + "TEXCOORD_0": 263, + "TEXCOORD_1": 264, + "TEXCOORD_2": 265, + "TEXCOORD_3": 266 + }, + "indices": 259, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 11, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "F_P6_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 268, + "POSITION": 269, + "TANGENT": 270, + "TEXCOORD_0": 271, + "TEXCOORD_1": 272, + "TEXCOORD_2": 273, + "TEXCOORD_3": 274 + }, + "indices": 267, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 12, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "F_P7_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 276, + "POSITION": 277, + "TANGENT": 278, + "TEXCOORD_0": 279, + "TEXCOORD_1": 280, + "TEXCOORD_2": 281, + "TEXCOORD_3": 282 + }, + "indices": 275, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 13, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "0", + "primitives": [ + { + "attributes": { + "NORMAL": 284, + "POSITION": 285, + "TANGENT": 286, + "TEXCOORD_0": 287, + "TEXCOORD_1": 288, + "TEXCOORD_2": 289, + "TEXCOORD_3": 290, + "TEXCOORD_4": 291 + }, + "indices": 283, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 14, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_Panel_R_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 293, + "POSITION": 294, + "TANGENT": 295, + "TEXCOORD_0": 296, + "TEXCOORD_1": 297, + "TEXCOORD_2": 298, + "TEXCOORD_3": 299, + "TEXCOORD_4": 300 + }, + "indices": 292, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 15, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_leg_R_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 302, + "POSITION": 303, + "TANGENT": 304, + "TEXCOORD_0": 305, + "TEXCOORD_1": 306, + "TEXCOORD_2": 307, + "TEXCOORD_3": 308 + }, + "indices": 301, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 16, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "R_P1_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 310, + "POSITION": 311, + "TANGENT": 312, + "TEXCOORD_0": 313, + "TEXCOORD_1": 314, + "TEXCOORD_2": 315, + "TEXCOORD_3": 316 + }, + "indices": 309, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 17, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "R_P2_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 318, + "POSITION": 319, + "TANGENT": 320, + "TEXCOORD_0": 321, + "TEXCOORD_1": 322, + "TEXCOORD_2": 323, + "TEXCOORD_3": 324 + }, + "indices": 317, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 18, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "R_P3_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 326, + "POSITION": 327, + "TANGENT": 328, + "TEXCOORD_0": 329, + "TEXCOORD_1": 330, + "TEXCOORD_2": 331, + "TEXCOORD_3": 332 + }, + "indices": 325, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 19, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "R_P4_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 334, + "POSITION": 335, + "TANGENT": 336, + "TEXCOORD_0": 337, + "TEXCOORD_1": 338, + "TEXCOORD_2": 339, + "TEXCOORD_3": 340 + }, + "indices": 333, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 20, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "R_P5_M_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 342, + "POSITION": 343, + "TANGENT": 344, + "TEXCOORD_0": 345, + "TEXCOORD_1": 346, + "TEXCOORD_2": 347, + "TEXCOORD_3": 348 + }, + "indices": 341, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 21, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "R_P6_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 350, + "POSITION": 351, + "TANGENT": 352, + "TEXCOORD_0": 353, + "TEXCOORD_1": 354, + "TEXCOORD_2": 355, + "TEXCOORD_3": 356 + }, + "indices": 349, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 22, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "R_P7_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 358, + "POSITION": 359, + "TANGENT": 360, + "TEXCOORD_0": 361, + "TEXCOORD_1": 362, + "TEXCOORD_2": 363, + "TEXCOORD_3": 364 + }, + "indices": 357, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 23, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "Drone_Gen_L_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 366, + "POSITION": 367, + "TANGENT": 368, + "TEXCOORD_0": 369, + "TEXCOORD_1": 370, + "TEXCOORD_2": 371, + "TEXCOORD_3": 372, + "TEXCOORD_4": 373 + }, + "indices": 365, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 24, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_Panel_L_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 375, + "POSITION": 376, + "TANGENT": 377, + "TEXCOORD_0": 378, + "TEXCOORD_1": 379, + "TEXCOORD_2": 380, + "TEXCOORD_3": 381, + "TEXCOORD_4": 382 + }, + "indices": 374, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 25, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_leg_L_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 384, + "POSITION": 385, + "TANGENT": 386, + "TEXCOORD_0": 387, + "TEXCOORD_1": 388, + "TEXCOORD_2": 389, + "TEXCOORD_3": 390 + }, + "indices": 383, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 26, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "L_P1_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 392, + "POSITION": 393, + "TANGENT": 394, + "TEXCOORD_0": 395, + "TEXCOORD_1": 396, + "TEXCOORD_2": 397, + "TEXCOORD_3": 398 + }, + "indices": 391, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 27, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "L_P2_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 400, + "POSITION": 401, + "TANGENT": 402, + "TEXCOORD_0": 403, + "TEXCOORD_1": 404, + "TEXCOORD_2": 405, + "TEXCOORD_3": 406 + }, + "indices": 399, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 28, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "L_P3_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 408, + "POSITION": 409, + "TANGENT": 410, + "TEXCOORD_0": 411, + "TEXCOORD_1": 412, + "TEXCOORD_2": 413, + "TEXCOORD_3": 414 + }, + "indices": 407, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 29, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "L_P4_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 416, + "POSITION": 417, + "TANGENT": 418, + "TEXCOORD_0": 419, + "TEXCOORD_1": 420, + "TEXCOORD_2": 421, + "TEXCOORD_3": 422 + }, + "indices": 415, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 30, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "L_P5_M_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 424, + "POSITION": 425, + "TANGENT": 426, + "TEXCOORD_0": 427, + "TEXCOORD_1": 428, + "TEXCOORD_2": 429, + "TEXCOORD_3": 430 + }, + "indices": 423, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 31, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "L_P6_G_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 432, + "POSITION": 433, + "TANGENT": 434, + "TEXCOORD_0": 435, + "TEXCOORD_1": 436, + "TEXCOORD_2": 437, + "TEXCOORD_3": 438 + }, + "indices": 431, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 32, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "L_P7_leg_0", + "primitives": [ + { + "attributes": { + "NORMAL": 440, + "POSITION": 441, + "TANGENT": 442, + "TEXCOORD_0": 443, + "TEXCOORD_1": 444, + "TEXCOORD_2": 445, + "TEXCOORD_3": 446 + }, + "indices": 439, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 33, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6 + } + } + } + } + ] + }, + { + "name": "Drone_UPanel_R_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 448, + "POSITION": 449, + "TANGENT": 450, + "TEXCOORD_0": 451, + "TEXCOORD_1": 452, + "TEXCOORD_2": 453, + "TEXCOORD_3": 454, + "TEXCOORD_4": 455 + }, + "indices": 447, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 34, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_UPanel_L_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 457, + "POSITION": 458, + "TANGENT": 459, + "TEXCOORD_0": 460, + "TEXCOORD_1": 461, + "TEXCOORD_2": 462, + "TEXCOORD_3": 463, + "TEXCOORD_4": 464 + }, + "indices": 456, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 35, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_UPart_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 466, + "POSITION": 467, + "TANGENT": 468, + "TEXCOORD_0": 469, + "TEXCOORD_1": 470, + "TEXCOORD_2": 471, + "TEXCOORD_3": 472, + "TEXCOORD_4": 473 + }, + "indices": 465, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 36, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_ILens_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 475, + "POSITION": 476, + "TANGENT": 477, + "TEXCOORD_0": 478, + "TEXCOORD_1": 479, + "TEXCOORD_2": 480, + "TEXCOORD_3": 481, + "TEXCOORD_4": 482 + }, + "indices": 474, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 37, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "1", + "primitives": [ + { + "attributes": { + "NORMAL": 484, + "POSITION": 485, + "TANGENT": 486, + "TEXCOORD_0": 487, + "TEXCOORD_1": 488, + "TEXCOORD_2": 489, + "TEXCOORD_3": 490, + "TEXCOORD_4": 491 + }, + "indices": 483, + "material": 1, + "mode": 4, + "targets": [ + { + "NORMAL": 1, + "POSITION": 0 + }, + { + "NORMAL": 3, + "POSITION": 2 + } + ], + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 38, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ], + "weights": [ + 0, + 0 + ] + }, + { + "name": "Drone_Turb_M_L_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 493, + "POSITION": 494, + "TANGENT": 495, + "TEXCOORD_0": 496, + "TEXCOORD_1": 497, + "TEXCOORD_2": 498, + "TEXCOORD_3": 499, + "TEXCOORD_4": 500 + }, + "indices": 492, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 39, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_Turb_Blade_L_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 502, + "POSITION": 503, + "TANGENT": 504, + "TEXCOORD_0": 505, + "TEXCOORD_1": 506, + "TEXCOORD_2": 507, + "TEXCOORD_3": 508, + "TEXCOORD_4": 509 + }, + "indices": 501, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 40, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_Turb_M_R_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 511, + "POSITION": 512, + "TANGENT": 513, + "TEXCOORD_0": 514, + "TEXCOORD_1": 515, + "TEXCOORD_2": 516, + "TEXCOORD_3": 517, + "TEXCOORD_4": 518 + }, + "indices": 510, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 41, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + }, + { + "name": "Drone_Turb_Blade_R_body_0", + "primitives": [ + { + "attributes": { + "NORMAL": 520, + "POSITION": 521, + "TANGENT": 522, + "TEXCOORD_0": 523, + "TEXCOORD_1": 524, + "TEXCOORD_2": 525, + "TEXCOORD_3": 526, + "TEXCOORD_4": 527 + }, + "indices": 519, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 42, + "attributes": { + "NORMAL": 0, + "POSITION": 1, + "TANGENT": 2, + "TEXCOORD_0": 3, + "TEXCOORD_1": 4, + "TEXCOORD_2": 5, + "TEXCOORD_3": 6, + "TEXCOORD_4": 7 + } + } + } + } + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "name": "RootNode (gltf orientation matrix)", + "rotation": [ + -0.7071067811865475, + 0, + 0, + 0.7071067811865476 + ], + "translation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 2 + ], + "name": "RootNode (model correction matrix)" + }, + { + "children": [ + 3 + ], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + -1, + 0, + 0, + 0, + 0, + 0, + 1 + ], + "name": "BusterDrone.fbx" + }, + { + "children": [ + 4 + ], + "name": "" + }, + { + "children": [ + 5, + 9 + ], + "name": "RootNode" + }, + { + "children": [ + 6, + 8 + ], + "name": "Env" + }, + { + "children": [ + 7 + ], + "name": "Scheibe", + "rotation": [ + 0.5, + 0.5, + -0.5, + 0.5 + ], + "translation": [ + 0, + -99, + 6.1232337864698064e-15 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 0, + "name": "Scheibe_Boden_0" + }, + { + "name": "Himmel" + }, + { + "children": [ + 10, + 13 + ], + "name": "Drone_Controller", + "translation": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 11, + 12 + ], + "name": "Turbine_Controller", + "translation": [ + 0, + -100, + -5 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "name": "Turbine_R", + "rotation": [ + 0.7071068286895752, + 0, + 0, + 0.7071068286895752 + ], + "translation": [ + 12.244799613952637, + 0, + -1.0070199966430664 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "name": "Turbine_L", + "rotation": [ + 0.7071068286895752, + 0, + 0, + 0.7071068286895752 + ], + "translation": [ + -12.244799613952637, + 0, + -1.0070199966430664 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 14, + 16 + ], + "name": "U_MassPoint", + "rotation": [ + 0.6133379936218262, + 0, + 0, + 0.789820671081543 + ], + "translation": [ + 0, + 0.11856790632009506, + -12.910046577453613 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 15 + ], + "name": "Eye_Controller", + "rotation": [ + 0.017331130802631378, + 0, + 0, + 0.9998499155044556 + ], + "translation": [ + 0, + 143.0728759765625, + 58.6367301940918 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "name": "Eye_Pupil", + "rotation": [ + -0.7071068286895752, + 0, + 0, + 0.7071068286895752 + ], + "translation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 17 + ], + "name": "D_MassPoint", + "translation": [ + 0, + -1.7763568394002505e-15, + 77.5 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 18, + 19, + 35, + 55, + 75, + 77, + 79, + 81, + 85, + 89 + ], + "name": "Drone_Body", + "rotation": [ + -0.7071068286895752, + 0, + 0, + 0.7071068286895752 + ], + "translation": [ + 0, + 0, + -37.5 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 1, + "name": "Drone_Body_body_0" + }, + { + "children": [ + 20, + 21 + ], + "name": "Drone_leg_F", + "translation": [ + 0, + -38.68080139160156, + 20.01194953918457 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 2, + "name": "Drone_leg_F_leg_0" + }, + { + "children": [ + 22, + 23 + ], + "name": "F_P1_G", + "rotation": [ + -9.472242394202753e-15, + 0.7071065902709961, + 9.472236464972122e-15, + 0.7071070075035095 + ], + "translation": [ + 0.006630018353462219, + -5.510501384735107, + -0.09275053441524506 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 3, + "name": "F_P1_G_leg_0" + }, + { + "children": [ + 24, + 25 + ], + "name": "F_P2", + "rotation": [ + 0.4777144193649292, + 0.5213338136672974, + -0.4777144193649292, + 0.5213338136672974 + ], + "translation": [ + 0, + -0.00004080753933521919, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 4, + "name": "F_P2_leg_0" + }, + { + "children": [ + 26, + 27 + ], + "name": "F_P3_G", + "rotation": [ + -1.5265570559062843e-16, + -4.1108839354819793e-7, + -8.700754859676185e-17, + 1 + ], + "translation": [ + 0.00007688588812015951, + -22.9158935546875, + 0.02676698938012123 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 5, + "name": "F_P3_G_leg_0" + }, + { + "children": [ + 28, + 29 + ], + "name": "F_P4", + "rotation": [ + 4.003213763390976e-16, + -0.5735764503479004, + 0.8191520571708679, + -6.550924359051687e-17 + ], + "translation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 6, + "name": "F_P4_leg_0" + }, + { + "children": [ + 30, + 31 + ], + "name": "F_P5_M", + "rotation": [ + 1.3877787807814457e-17, + -5.293955920339377e-23, + -9.926167350636332e-23, + 1 + ], + "translation": [ + -0.01574668288230896, + -11.282759666442871, + 0.081717349588871 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 7, + "name": "F_P5_M_leg_0" + }, + { + "children": [ + 32, + 33 + ], + "name": "F_P6_G", + "rotation": [ + -2.7755575615628914e-17, + -2.74964495616814e-10, + 7.940170894241536e-23, + 1 + ], + "translation": [ + 0.005422236397862434, + -9.326162338256836, + -0.08217942714691162 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 8, + "name": "F_P6_G_leg_0" + }, + { + "children": [ + 34 + ], + "name": "F_P7", + "rotation": [ + 0.5891698598861694, + -5.057324785588213e-23, + 2.0496480651152692e-23, + 0.8080092072486877 + ], + "translation": [ + 4.336808689942018e-19, + 0.00003388613185961731, + 0.000014036095308256336 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 9, + "name": "F_P7_leg_0" + }, + { + "children": [ + 36, + 37 + ], + "name": "Drone_Gen_R", + "rotation": [ + 0.1889660805463791, + -0.6813896298408508, + 0.1889660656452179, + 0.6813896298408508 + ], + "translation": [ + -26.78019905090332, + -31.10906982421875, + -0.748199999332428 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 10, + "name": "0" + }, + { + "children": [ + 38, + 39 + ], + "name": "Drone_Panel_R", + "rotation": [ + -2.0816678402999235e-17, + 2.62250594573743e-8, + -1.249000902703301e-16, + 1 + ], + "translation": [ + 0.6785002946853638, + -0.37506112456321716, + 4.957866191864014 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 11, + "name": "Drone_Panel_R_body_0" + }, + { + "children": [ + 40, + 41 + ], + "name": "Drone_leg_R", + "rotation": [ + -0.41061899065971375, + 0.575666606426239, + -0.41061899065971375, + 0.575666606426239 + ], + "translation": [ + -12.886950492858887, + -9.610799789428711, + -0.729290246963501 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 12, + "name": "Drone_leg_R_leg_0" + }, + { + "children": [ + 42, + 43 + ], + "name": "R_P1_G", + "rotation": [ + -2.6943811002715914e-16, + 0.7933533787727356, + 4.189390215534042e-17, + 0.6087614297866821 + ], + "translation": [ + 2.4154791831970215, + -4.842290878295898, + -0.006652138661593199 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 13, + "name": "R_P1_G_leg_0" + }, + { + "children": [ + 44, + 45 + ], + "name": "R_P2", + "rotation": [ + 0.6187881827354431, + 7.332807899516821e-17, + 4.8236011717070243e-17, + 0.7855579257011414 + ], + "translation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 14, + "name": "R_P2_leg_0" + }, + { + "children": [ + 46, + 47 + ], + "name": "R_P3_G", + "rotation": [ + 3.5041414214731503e-16, + 2.7755575615628914e-17, + 1.3877787807814457e-16, + 1 + ], + "translation": [ + 0.002689761109650135, + -22.916383743286133, + 0.02693275175988674 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 15, + "name": "R_P3_G_leg_0" + }, + { + "children": [ + 48, + 49 + ], + "name": "R_P4", + "rotation": [ + 4.0562085120848394e-17, + -0.6030816435813904, + 0.7976794838905334, + 1.0742985044475295e-16 + ], + "translation": [ + 0.004904936067759991, + 0.0029711532406508923, + -0.0014322279021143913 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 16, + "name": "R_P4_leg_0" + }, + { + "children": [ + 50, + 51 + ], + "name": "R_P5_M", + "rotation": [ + 0.0000031865668006503256, + -1.3877721633365453e-17, + 2.0816726379474763e-17, + 1 + ], + "translation": [ + 0.010783359408378601, + -11.28590202331543, + 0.08223113417625427 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 17, + "name": "R_P5_M_leg_0" + }, + { + "children": [ + 52, + 53 + ], + "name": "R_P6_G", + "rotation": [ + -7.45931094670027e-17, + 0, + 0, + 1 + ], + "translation": [ + -0.005793713964521885, + -9.326017379760742, + -0.08199705928564072 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 18, + "name": "R_P6_G_leg_0" + }, + { + "children": [ + 54 + ], + "name": "R_P7", + "rotation": [ + 0.6483271718025208, + 3.472374165980341e-9, + -4.330498626359258e-8, + 0.7613618969917297 + ], + "translation": [ + -1.1546319456101628e-13, + -0.000002192010470025707, + -9.079604410544562e-7 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 19, + "name": "R_P7_leg_0" + }, + { + "children": [ + 56, + 57 + ], + "name": "Drone_Gen_L", + "rotation": [ + 0.1889660805463791, + 0.6813896298408508, + -0.1889660656452179, + 0.6813896298408508 + ], + "translation": [ + 26.78019905090332, + -31.10906982421875, + -0.748199999332428 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 20, + "name": "Drone_Gen_L_body_0" + }, + { + "children": [ + 58, + 59 + ], + "name": "Drone_Panel_L", + "rotation": [ + 0.0002122838923241943, + 2.747205307684908e-8, + -5.831957746588179e-12, + 1 + ], + "translation": [ + -0.6784976124763489, + -0.37716609239578247, + 4.957706451416016 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 21, + "name": "Drone_Panel_L_body_0" + }, + { + "children": [ + 60, + 61 + ], + "name": "Drone_leg_L", + "rotation": [ + -0.41061896085739136, + -0.575666606426239, + 0.41061902046203613, + 0.575666606426239 + ], + "translation": [ + 12.88695240020752, + -9.610796928405762, + -0.7292901277542114 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 22, + "name": "Drone_leg_L_leg_0" + }, + { + "children": [ + 62, + 63 + ], + "name": "L_P1_G", + "rotation": [ + 3.7478338591893966e-16, + -0.7613461017608643, + 5.642599445989575e-16, + 0.6483456492424011 + ], + "translation": [ + -2.415479898452759, + -4.84229040145874, + -0.006640426814556122 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 23, + "name": "L_P1_G_leg_0" + }, + { + "children": [ + 64, + 65 + ], + "name": "L_P2", + "rotation": [ + 0.5984764695167542, + -4.839795300149281e-18, + -1.0031977647616155e-16, + 0.8011403679847717 + ], + "translation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 24, + "name": "L_P2_leg_0" + }, + { + "children": [ + 66, + 67 + ], + "name": "L_P3_G", + "rotation": [ + -1.708702623837155e-16, + 1.3877787807814457e-17, + -8.326672684688674e-17, + 1 + ], + "translation": [ + 0.0002644560590852052, + -22.915939331054688, + 0.026753252372145653 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 25, + "name": "L_P3_G_leg_0" + }, + { + "children": [ + 68, + 69 + ], + "name": "L_P4", + "rotation": [ + 3.0627252226114957e-17, + -0.6686968803405762, + 0.7435351014137268, + -5.480842821366953e-17 + ], + "translation": [ + -0.004460121039301157, + 0.000007818744961696211, + 0.00005186478665564209 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 26, + "name": "L_P4_leg_0" + }, + { + "children": [ + 70, + 71 + ], + "name": "L_P5_M", + "rotation": [ + 0.00001270258508156985, + 0.000003925847977370722, + -0.010920973494648933, + 0.9999404549598694 + ], + "translation": [ + 0.05688011273741722, + -11.236658096313477, + 0.08181961625814438 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 27, + "name": "L_P5_M_leg_0" + }, + { + "children": [ + 72, + 73 + ], + "name": "L_P6_G", + "rotation": [ + -7.632783294297951e-17, + -7.632783294297951e-17, + 5.551115123125783e-17, + 1 + ], + "translation": [ + 0.14344365894794464, + -9.371054649353027, + -0.08199699968099594 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 28, + "name": "L_P6_G_leg_0" + }, + { + "children": [ + 74 + ], + "name": "L_P7", + "rotation": [ + 0.7071068286895752, + 5.3971933547419153e-17, + 4.906539263005266e-18, + 0.7071068286895752 + ], + "translation": [ + 0.01226816326379776, + 0.00024394220963586122, + 0.0002562310837674886 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 29, + "name": "L_P7_leg_0" + }, + { + "children": [ + 76 + ], + "name": "Drone_UPanel_R", + "rotation": [ + 0.09390989691019058, + -0.7008430361747742, + 0.09390989691019058, + 0.700843095779419 + ], + "translation": [ + -28.345199584960938, + -10.20475959777832, + 0.14466851949691772 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 30, + "name": "Drone_UPanel_R_body_0" + }, + { + "children": [ + 78 + ], + "name": "Drone_UPanel_L", + "rotation": [ + 0.09390989691019058, + 0.7008430361747742, + -0.09390989691019058, + 0.700843095779419 + ], + "translation": [ + 28.230527877807617, + -11.228233337402344, + -0.07694999873638153 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 31, + "name": "Drone_UPanel_L_body_0" + }, + { + "children": [ + 80 + ], + "name": "Drone_UPart", + "translation": [ + 0, + 38.9765510559082, + -3.073050022125244 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 32, + "name": "Drone_UPart_body_0" + }, + { + "children": [ + 82, + 83 + ], + "name": "Drone_ILens", + "translation": [ + 0, + -14.965813636779785, + 41.50516891479492 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 33, + "name": "Drone_ILens_body_0" + }, + { + "children": [ + 84 + ], + "name": "Drone_IEye", + "rotation": [ + 0.0007836852455511689, + 0.9981203675270081, + -0.013049819506704807, + 0.0598752461373806 + ], + "translation": [ + 0, + -0.018226023763418198, + -8.908537864685059 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 34, + "name": "1" + }, + { + "children": [ + 86, + 87 + ], + "name": "Drone_Turb_M_L", + "rotation": [ + 0.5779998302459717, + -0.4667881727218628, + -0.5311384797096252, + -0.40732908248901367 + ], + "translation": [ + 19.973400115966797, + 24.55685043334961, + -6.007046699523926 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 35, + "name": "Drone_Turb_M_L_body_0" + }, + { + "children": [ + 88 + ], + "name": "Drone_Turb_Blade_L", + "rotation": [ + 0.40862560272216797, + 0.5128536224365234, + 0.6914904713630676, + 0.30306294560432434 + ], + "translation": [ + -0.000021889296476729214, + -36.155147552490234, + -10.966755867004395 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 36, + "name": "Drone_Turb_Blade_L_body_0" + }, + { + "children": [ + 90, + 91 + ], + "name": "Drone_Turb_M_R", + "rotation": [ + 0.5797019600868225, + 0.46958616375923157, + 0.5286666750907898, + -0.40490248799324036 + ], + "translation": [ + -19.973400115966797, + 24.556848526000977, + -6.007049560546875 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 37, + "name": "Drone_Turb_M_R_body_0" + }, + { + "children": [ + 92 + ], + "name": "Drone_Turb_Blade_R", + "rotation": [ + -0.4086257517337799, + 0.512853741645813, + 0.6914904713630676, + -0.30306291580200195 + ], + "translation": [ + 0.000051651491958182305, + -36.1551513671875, + -10.966744422912598 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 38, + "name": "Drone_Turb_Blade_R_body_0" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9987, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "scene": 0, + "scenes": [ + { + "name": "OSG_Scene", + "nodes": [ + 0 + ] + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + }, + { + "sampler": 0, + "source": 1 + }, + { + "sampler": 0, + "source": 2 + }, + { + "sampler": 0, + "source": 3 + }, + { + "sampler": 0, + "source": 4 + }, + { + "sampler": 0, + "source": 5 + }, + { + "sampler": 0, + "source": 6 + }, + { + "sampler": 0, + "source": 7 + }, + { + "sampler": 0, + "source": 8 + }, + { + "sampler": 0, + "source": 9 + } + ], + "extensionsRequired": [ + "KHR_draco_mesh_compression" + ], + "extensionsUsed": [ + "KHR_draco_mesh_compression" + ] +} diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_baseColor.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_baseColor.jpg new file mode 100644 index 00000000..a0b817b7 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_baseColor.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_metallicRoughness.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_metallicRoughness.jpg new file mode 100644 index 00000000..16af5ced Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_metallicRoughness.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_normal.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_normal.jpg new file mode 100644 index 00000000..16ac42fb Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/Boden_normal.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_baseColor.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_baseColor.jpg new file mode 100644 index 00000000..338fa643 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_baseColor.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_emissive.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_emissive.jpg new file mode 100644 index 00000000..db3e51b9 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_emissive.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_metallicRoughness.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_metallicRoughness.jpg new file mode 100644 index 00000000..93b51013 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_metallicRoughness.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_normal.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_normal.jpg new file mode 100644 index 00000000..28e0583b Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/body_normal.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_baseColor.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_baseColor.jpg new file mode 100644 index 00000000..154cb5b1 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_baseColor.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_metallicRoughness.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_metallicRoughness.jpg new file mode 100644 index 00000000..5f539354 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_metallicRoughness.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_normal.jpg b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_normal.jpg new file mode 100644 index 00000000..a1f52c14 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/BusterDrone/textures/material_normal.jpg differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet.bin b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet.bin new file mode 100644 index 00000000..a8b48147 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet.bin differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet.gltf b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet.gltf new file mode 100644 index 00000000..74a92ecd --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet.gltf @@ -0,0 +1,755 @@ +{ + "accessors": [ + { + "componentType": 5123, + "count": 24408, + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 8468, + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 8468, + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 8468, + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 8468, + "type": "VEC3", + "max": [ + 0.131662, + 0.137638986, + 0.10078799 + ], + "min": [ + -0.131333, + -0.028128, + -0.137763992 + ] + }, + { + "componentType": 5123, + "count": 65688, + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 12552, + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 12552, + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 12552, + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 12552, + "type": "VEC3", + "max": [ + 0.11722149, + 0.196387976, + 0.132422984 + ], + "min": [ + -0.11722149, + -0.196387976, + -0.132422984 + ] + }, + { + "componentType": 5123, + "count": 2208, + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 436, + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 436, + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 436, + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 436, + "type": "VEC3", + "max": [ + 0.09527509, + 0.114654, + -0.08429489 + ], + "min": [ + -0.0952748954, + 0.0551489964, + -0.14295499 + ] + }, + { + "componentType": 5123, + "count": 60288, + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 17186, + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 17186, + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 17186, + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 17186, + "type": "VEC3", + "max": [ + 0.1572095, + 0.2716865, + 0.162181988 + ], + "min": [ + -0.1572095, + -0.2716865, + -0.162181988 + ] + }, + { + "componentType": 5123, + "count": 131574, + "type": "SCALAR" + }, + { + "componentType": 5126, + "count": 24148, + "type": "VEC2" + }, + { + "componentType": 5126, + "count": 24148, + "type": "VEC3" + }, + { + "componentType": 5126, + "count": 24148, + "type": "VEC4" + }, + { + "componentType": 5126, + "count": 24148, + "type": "VEC3", + "max": [ + 0.1504075, + 0.328366965, + 0.173673 + ], + "min": [ + -0.1504075, + -0.328366965, + -0.173673 + ] + } + ], + "asset": { + "generator": "glTF Tools for Unity", + "version": "2.0" + }, + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 59806 + }, + { + "buffer": 0, + "byteOffset": 59808, + "byteLength": 99674 + }, + { + "buffer": 0, + "byteOffset": 159484, + "byteLength": 4875 + }, + { + "buffer": 0, + "byteOffset": 164360, + "byteLength": 133545 + }, + { + "buffer": 0, + "byteOffset": 297908, + "byteLength": 203914 + } + ], + "buffers": [ + { + "name": "FlightHelmet", + "byteLength": 501824, + "uri": "FlightHelmet.bin" + } + ], + "images": [ + { + "name": "FlightHelmet_baseColor", + "uri": "FlightHelmet_baseColor.png" + }, + { + "name": "FlightHelmet_occlusionRoughnessMetallic", + "uri": "FlightHelmet_occlusionRoughnessMetallic.png" + }, + { + "name": "FlightHelmet_normal", + "uri": "FlightHelmet_normal.png" + }, + { + "name": "FlightHelmet_baseColor1", + "uri": "FlightHelmet_baseColor1.png" + }, + { + "name": "FlightHelmet_occlusionRoughnessMetallic1", + "uri": "FlightHelmet_occlusionRoughnessMetallic1.png" + }, + { + "name": "FlightHelmet_normal1", + "uri": "FlightHelmet_normal1.png" + }, + { + "name": "FlightHelmet_baseColor2", + "uri": "FlightHelmet_baseColor2.png" + }, + { + "name": "FlightHelmet_occlusionRoughnessMetallic2", + "uri": "FlightHelmet_occlusionRoughnessMetallic2.png" + }, + { + "name": "FlightHelmet_normal2", + "uri": "FlightHelmet_normal2.png" + }, + { + "name": "FlightHelmet_baseColor3", + "uri": "FlightHelmet_baseColor3.png" + }, + { + "name": "FlightHelmet_occlusionRoughnessMetallic3", + "uri": "FlightHelmet_occlusionRoughnessMetallic3.png" + }, + { + "name": "FlightHelmet_normal3", + "uri": "FlightHelmet_normal3.png" + }, + { + "name": "FlightHelmet_baseColor4", + "uri": "FlightHelmet_baseColor4.png" + }, + { + "name": "FlightHelmet_occlusionRoughnessMetallic4", + "uri": "FlightHelmet_occlusionRoughnessMetallic4.png" + }, + { + "name": "FlightHelmet_normal4", + "uri": "FlightHelmet_normal4.png" + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "TEXCOORD_0": 1, + "NORMAL": 2, + "TANGENT": 3, + "POSITION": 4 + }, + "indices": 0, + "material": 0, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 0, + "attributes": { + "TEXCOORD_0": 0, + "NORMAL": 1, + "TANGENT": 2, + "POSITION": 3 + } + } + } + } + ], + "name": "GlassPlastic_low" + }, + { + "primitives": [ + { + "attributes": { + "TEXCOORD_0": 6, + "NORMAL": 7, + "TANGENT": 8, + "POSITION": 9 + }, + "indices": 5, + "material": 1, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 1, + "attributes": { + "TEXCOORD_0": 0, + "NORMAL": 1, + "TANGENT": 2, + "POSITION": 3 + } + } + } + } + ], + "name": "LeatherParts_low" + }, + { + "primitives": [ + { + "attributes": { + "TEXCOORD_0": 11, + "NORMAL": 12, + "TANGENT": 13, + "POSITION": 14 + }, + "indices": 10, + "material": 2, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 2, + "attributes": { + "TEXCOORD_0": 0, + "NORMAL": 1, + "TANGENT": 2, + "POSITION": 3 + } + } + } + } + ], + "name": "Lenses_low" + }, + { + "primitives": [ + { + "attributes": { + "TEXCOORD_0": 16, + "NORMAL": 17, + "TANGENT": 18, + "POSITION": 19 + }, + "indices": 15, + "material": 3, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 3, + "attributes": { + "TEXCOORD_0": 0, + "NORMAL": 1, + "TANGENT": 2, + "POSITION": 3 + } + } + } + } + ], + "name": "MetalParts_low" + }, + { + "primitives": [ + { + "attributes": { + "TEXCOORD_0": 21, + "NORMAL": 22, + "TANGENT": 23, + "POSITION": 24 + }, + "indices": 20, + "material": 4, + "mode": 4, + "extensions": { + "KHR_draco_mesh_compression": { + "bufferView": 4, + "attributes": { + "TEXCOORD_0": 0, + "NORMAL": 1, + "TANGENT": 2, + "POSITION": 3 + } + } + } + } + ], + "name": "RubberWood_low" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "texCoord": 0 + }, + "metallicRoughnessTexture": { + "index": 1, + "texCoord": 0 + }, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "metallicFactor": 1, + "roughnessFactor": 1 + }, + "normalTexture": { + "index": 2, + "texCoord": 0 + }, + "occlusionTexture": { + "index": 1, + "texCoord": 0 + }, + "name": "GlassPlasticMat", + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE", + "doubleSided": false + }, + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 3, + "texCoord": 0 + }, + "metallicRoughnessTexture": { + "index": 4, + "texCoord": 0 + }, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "metallicFactor": 1, + "roughnessFactor": 1 + }, + "normalTexture": { + "index": 5, + "texCoord": 0 + }, + "occlusionTexture": { + "index": 4, + "texCoord": 0 + }, + "name": "LeatherPartsMat", + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE", + "doubleSided": false + }, + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 6, + "texCoord": 0 + }, + "metallicRoughnessTexture": { + "index": 7, + "texCoord": 0 + }, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "metallicFactor": 1, + "roughnessFactor": 1 + }, + "normalTexture": { + "index": 8, + "texCoord": 0 + }, + "occlusionTexture": { + "index": 7, + "texCoord": 0 + }, + "alphaMode": "BLEND", + "name": "LensesMat", + "emissiveFactor": [ + 0, + 0, + 0 + ], + "doubleSided": false + }, + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 9, + "texCoord": 0 + }, + "metallicRoughnessTexture": { + "index": 10, + "texCoord": 0 + }, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "metallicFactor": 1, + "roughnessFactor": 1 + }, + "normalTexture": { + "index": 11, + "texCoord": 0 + }, + "occlusionTexture": { + "index": 10, + "texCoord": 0 + }, + "name": "MetalPartsMat", + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE", + "doubleSided": false + }, + { + "doubleSided": true, + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 12, + "texCoord": 0 + }, + "metallicRoughnessTexture": { + "index": 13, + "texCoord": 0 + }, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "metallicFactor": 1, + "roughnessFactor": 1 + }, + "normalTexture": { + "index": 14, + "texCoord": 0 + }, + "occlusionTexture": { + "index": 13, + "texCoord": 0 + }, + "name": "RubberWoodMat", + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE" + } + ], + "nodes": [ + { + "mesh": 0, + "name": "GlassPlastic_low" + }, + { + "mesh": 1, + "translation": [ + 0.000434499962, + 0.032592997, + 0.011676996 + ], + "name": "LeatherParts_low", + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 2, + "name": "Lenses_low" + }, + { + "mesh": 3, + "translation": [ + 0.0331545, + -0.1488645, + -0.0242879968 + ], + "name": "MetalParts_low", + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "mesh": 4, + "translation": [ + -0.00190849893, + -0.111985, + -0.013313001 + ], + "name": "RubberWood_low", + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 0, + 1, + 2, + 3, + 4 + ], + "rotation": [ + 0, + 1, + 0, + 0 + ], + "name": "FlightHelmet", + "translation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ] + } + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 5 + ] + } + ], + "textures": [ + { + "source": 0 + }, + { + "source": 1 + }, + { + "source": 2 + }, + { + "source": 3 + }, + { + "source": 4 + }, + { + "source": 5 + }, + { + "source": 6 + }, + { + "source": 7 + }, + { + "source": 8 + }, + { + "source": 9 + }, + { + "source": 10 + }, + { + "source": 11 + }, + { + "source": 12 + }, + { + "source": 13 + }, + { + "source": 14 + } + ], + "extensionsRequired": [ + "KHR_draco_mesh_compression" + ], + "extensionsUsed": [ + "KHR_draco_mesh_compression" + ] +} diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor.png new file mode 100644 index 00000000..4116e198 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor1.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor1.png new file mode 100644 index 00000000..d47b33eb Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor1.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor2.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor2.png new file mode 100644 index 00000000..839c5019 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor2.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor3.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor3.png new file mode 100644 index 00000000..6095f68d Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor3.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor4.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor4.png new file mode 100644 index 00000000..fddf46d1 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_baseColor4.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal.png new file mode 100644 index 00000000..058b4e9d Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal1.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal1.png new file mode 100644 index 00000000..a00be5c1 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal1.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal2.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal2.png new file mode 100644 index 00000000..a9ec5618 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal2.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal3.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal3.png new file mode 100644 index 00000000..70f9022b Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal3.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal4.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal4.png new file mode 100644 index 00000000..3c973901 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_normal4.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic.png new file mode 100644 index 00000000..bbde038e Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic1.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic1.png new file mode 100644 index 00000000..067b4f81 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic1.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic2.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic2.png new file mode 100644 index 00000000..2466f5bc Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic2.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic3.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic3.png new file mode 100644 index 00000000..dbe24290 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic3.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic4.png b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic4.png new file mode 100644 index 00000000..2cfc659e Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/FlightHelmet_occlusionRoughnessMetallic4.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/README.md b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/README.md new file mode 100644 index 00000000..75aba073 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/assets/FlightHelmet/README.md @@ -0,0 +1,16 @@ +# Flight Helmet + +## Screenshot + +![screenshot](screenshot/screenshot.jpg) + +## License Information + +Donated by Microsoft for glTF testing + +[![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png)](http://creativecommons.org/publicdomain/zero/1.0/) +To the extent possible under law, Microsoft has waived all copyright and related or neighboring rights to this asset. + +Draco compression was done via Cesium tools on 27-03-2020 as follows. + + gltf-pipeline -i FlightHelmet.gltf -o FlightHelmet.gltf -d -s --keep-unused-elements diff --git a/flutter_filament_federated/flutter_filament/example/assets/background.ktx b/flutter_filament_federated/flutter_filament/example/assets/background.ktx new file mode 100644 index 00000000..af9b04df Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/background.ktx differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/background.png b/flutter_filament_federated/flutter_filament/example/assets/background.png new file mode 100644 index 00000000..4e8e2737 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/background.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/default_env/default_env_ibl.ktx b/flutter_filament_federated/flutter_filament/example/assets/default_env/default_env_ibl.ktx new file mode 100644 index 00000000..0765d521 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/default_env/default_env_ibl.ktx differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/default_env/default_env_skybox.ktx b/flutter_filament_federated/flutter_filament/example/assets/default_env/default_env_skybox.ktx new file mode 100644 index 00000000..9d72e5a0 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/default_env/default_env_skybox.ktx differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_32.uberz b/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_32.uberz new file mode 100644 index 00000000..2be4b0e0 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_32.uberz differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43.uberz b/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43.uberz new file mode 100644 index 00000000..354a6047 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43.uberz differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43_gles.uberz b/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43_gles.uberz new file mode 100644 index 00000000..354a6047 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43_gles.uberz differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43_metal_macos.uberz b/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43_metal_macos.uberz new file mode 100644 index 00000000..35847437 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/lit_opaque_43_metal_macos.uberz differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.bin b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.bin new file mode 100644 index 00000000..b0e7823f Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.bin differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.blend b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.blend new file mode 100644 index 00000000..53907b3f Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.blend differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.blend1 b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.blend1 new file mode 100644 index 00000000..f59ba1a0 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.blend1 differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.glb b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.glb new file mode 100644 index 00000000..92ffaab3 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.glb differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.gltf b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.gltf new file mode 100644 index 00000000..4de0f4f1 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/assets/shapes/shapes.gltf @@ -0,0 +1,1327 @@ +{ + "asset" : { + "generator" : "Khronos glTF Blender I/O v3.4.50", + "version" : "2.0" + }, + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 0, + 1, + 2, + 5 + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "Cone", + "rotation" : [ + -0.5664676427841187, + -0.00448102131485939, + -0.273197203874588, + 0.777468740940094 + ], + "translation" : [ + 4.498239994049072, + -2.412745714187622, + 0 + ] + }, + { + "mesh" : 1, + "name" : "Cube", + "rotation" : [ + -0.047188904136419296, + 0.42376554012298584, + 0.022113962098956108, + 0.9042714834213257 + ], + "scale" : [ + 1.111829400062561, + 1.1118295192718506, + 1.1118295192718506 + ], + "translation" : [ + 0.13781452178955078, + 3.8293533325195312, + -21.286357879638672 + ] + }, + { + "camera" : 0, + "name" : "Camera", + "rotation" : [ + -0.20997299253940582, + 0.3857799470424652, + 0.09062844514846802, + 0.8937962055206299 + ], + "translation" : [ + 7.358891487121582, + 4.958309173583984, + 6.925790786743164 + ] + }, + { + "name" : "Bone" + }, + { + "mesh" : 2, + "name" : "Cylinder", + "skin" : 0 + }, + { + "children" : [ + 4, + 3 + ], + "name" : "Armature" + } + ], + "cameras" : [ + { + "name" : "Camera", + "perspective" : { + "aspectRatio" : 1.7777777777777777, + "yfov" : 0.39959648408210363, + "zfar" : 100, + "znear" : 0.10000000149011612 + }, + "type" : "perspective" + } + ], + "animations" : [ + { + "channels" : [ + { + "sampler" : 0, + "target" : { + "node" : 0, + "path" : "translation" + } + }, + { + "sampler" : 1, + "target" : { + "node" : 0, + "path" : "rotation" + } + } + ], + "name" : "Cone", + "samplers" : [ + { + "input" : 43, + "interpolation" : "LINEAR", + "output" : 44 + }, + { + "input" : 43, + "interpolation" : "LINEAR", + "output" : 45 + } + ] + }, + { + "channels" : [ + { + "sampler" : 0, + "target" : { + "node" : 1, + "path" : "translation" + } + }, + { + "sampler" : 1, + "target" : { + "node" : 1, + "path" : "rotation" + } + }, + { + "sampler" : 2, + "target" : { + "node" : 1, + "path" : "scale" + } + } + ], + "name" : "Cube1", + "samplers" : [ + { + "input" : 46, + "interpolation" : "LINEAR", + "output" : 47 + }, + { + "input" : 46, + "interpolation" : "LINEAR", + "output" : 48 + }, + { + "input" : 46, + "interpolation" : "LINEAR", + "output" : 49 + } + ] + }, + { + "channels" : [ + { + "sampler" : 0, + "target" : { + "node" : 1, + "path" : "translation" + } + }, + { + "sampler" : 1, + "target" : { + "node" : 1, + "path" : "rotation" + } + }, + { + "sampler" : 2, + "target" : { + "node" : 1, + "path" : "scale" + } + } + ], + "name" : "Cube2", + "samplers" : [ + { + "input" : 46, + "interpolation" : "LINEAR", + "output" : 50 + }, + { + "input" : 46, + "interpolation" : "LINEAR", + "output" : 51 + }, + { + "input" : 46, + "interpolation" : "LINEAR", + "output" : 52 + } + ] + }, + { + "channels" : [ + { + "sampler" : 0, + "target" : { + "node" : 4, + "path" : "translation" + } + }, + { + "sampler" : 1, + "target" : { + "node" : 4, + "path" : "rotation" + } + }, + { + "sampler" : 2, + "target" : { + "node" : 4, + "path" : "scale" + } + } + ], + "name" : "Cylinder", + "samplers" : [ + { + "input" : 53, + "interpolation" : "LINEAR", + "output" : 54 + }, + { + "input" : 53, + "interpolation" : "LINEAR", + "output" : 55 + }, + { + "input" : 53, + "interpolation" : "LINEAR", + "output" : 56 + } + ] + } + ], + "materials" : [ + { + "doubleSided" : true, + "name" : "Material.003", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0.008923866786062717, + 0.8000000715255737, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + }, + { + "doubleSided" : true, + "name" : "Material.004", + "pbrMetallicRoughness" : { + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + }, + { + "doubleSided" : true, + "name" : "Material.002", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.8000000715255737, + 0.28562870621681213, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + } + ], + "meshes" : [ + { + "extras" : { + "targetNames" : [ + "Key 1", + "Key 2", + "Key 3", + "Key 4", + "Key 5", + "Key 6", + "Key 7", + "Key 8" + ] + }, + "name" : "Cube.003", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "TEXCOORD_0" : 1, + "NORMAL" : 2 + }, + "indices" : 3, + "material" : 0, + "targets" : [ + { + "POSITION" : 4, + "NORMAL" : 5 + }, + { + "POSITION" : 6, + "NORMAL" : 7 + }, + { + "POSITION" : 8, + "NORMAL" : 9 + }, + { + "POSITION" : 10, + "NORMAL" : 11 + }, + { + "POSITION" : 12, + "NORMAL" : 13 + }, + { + "POSITION" : 14, + "NORMAL" : 15 + }, + { + "POSITION" : 16, + "NORMAL" : 17 + }, + { + "POSITION" : 18, + "NORMAL" : 19 + } + ] + } + ], + "weights" : [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "extras" : { + "targetNames" : [ + "Key 1", + "Key 2" + ] + }, + "name" : "Cube.004", + "primitives" : [ + { + "attributes" : { + "POSITION" : 20, + "TEXCOORD_0" : 21, + "NORMAL" : 22 + }, + "indices" : 23, + "material" : 1, + "targets" : [ + { + "POSITION" : 24, + "NORMAL" : 25 + }, + { + "POSITION" : 26, + "NORMAL" : 27 + } + ] + } + ], + "weights" : [ + 0, + 0 + ] + }, + { + "extras" : { + "targetNames" : [ + "Key 1", + "Key 2", + "Key 3", + "Key 4" + ] + }, + "name" : "Cube.002", + "primitives" : [ + { + "attributes" : { + "POSITION" : 28, + "TEXCOORD_0" : 29, + "NORMAL" : 30, + "JOINTS_0" : 31, + "WEIGHTS_0" : 32 + }, + "indices" : 33, + "material" : 2, + "targets" : [ + { + "POSITION" : 34, + "NORMAL" : 35 + }, + { + "POSITION" : 36, + "NORMAL" : 37 + }, + { + "POSITION" : 38, + "NORMAL" : 39 + }, + { + "POSITION" : 40, + "NORMAL" : 41 + } + ] + } + ], + "weights" : [ + 0, + 0, + 0, + 0 + ] + } + ], + "skins" : [ + { + "inverseBindMatrices" : 42, + "joints" : [ + 3 + ], + "name" : "Armature" + } + ], + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5126, + "count" : 160, + "max" : [ + -1.6020781993865967, + 4.364129543304443, + 0.2525796890258789 + ], + "min" : [ + -3.6020781993865967, + 2.3641295433044434, + -1.747420310974121 + ], + "type" : "VEC3" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 160, + "type" : "VEC2" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 3, + "componentType" : 5123, + "count" : 186, + "type" : "SCALAR" + }, + { + "bufferView" : 4, + "componentType" : 5126, + "count" : 160, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 5, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 6, + "componentType" : 5126, + "count" : 160, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 7, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 8, + "componentType" : 5126, + "count" : 160, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 9, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 10, + "componentType" : 5126, + "count" : 160, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 11, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 12, + "componentType" : 5126, + "count" : 160, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 13, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 14, + "componentType" : 5126, + "count" : 160, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 15, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 16, + "componentType" : 5126, + "count" : 160, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 17, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 18, + "componentType" : 5126, + "count" : 160, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 19, + "componentType" : 5126, + "count" : 160, + "type" : "VEC3" + }, + { + "bufferView" : 20, + "componentType" : 5126, + "count" : 32, + "max" : [ + 1, + 1, + 1 + ], + "min" : [ + -1, + -1, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 21, + "componentType" : 5126, + "count" : 32, + "type" : "VEC2" + }, + { + "bufferView" : 22, + "componentType" : 5126, + "count" : 32, + "type" : "VEC3" + }, + { + "bufferView" : 23, + "componentType" : 5123, + "count" : 36, + "type" : "SCALAR" + }, + { + "bufferView" : 24, + "componentType" : 5126, + "count" : 32, + "max" : [ + 0.9183349609375, + 0, + 0.9183341264724731 + ], + "min" : [ + -0.9183332324028015, + -2.384185791015625e-07, + -0.9183341264724731 + ], + "type" : "VEC3" + }, + { + "bufferView" : 25, + "componentType" : 5126, + "count" : 32, + "type" : "VEC3" + }, + { + "bufferView" : 26, + "componentType" : 5126, + "count" : 32, + "max" : [ + 0, + 0.38660454750061035, + 0 + ], + "min" : [ + -2.0121400356292725, + 0, + -2.008949041366577 + ], + "type" : "VEC3" + }, + { + "bufferView" : 27, + "componentType" : 5126, + "count" : 32, + "type" : "VEC3" + }, + { + "bufferView" : 28, + "componentType" : 5126, + "count" : 350, + "max" : [ + 2.3794736862182617, + 3.644867420196533, + 1.2384302616119385 + ], + "min" : [ + 0.37947380542755127, + 1.6448674201965332, + -0.7615697979927063 + ], + "type" : "VEC3" + }, + { + "bufferView" : 29, + "componentType" : 5126, + "count" : 350, + "type" : "VEC2" + }, + { + "bufferView" : 30, + "componentType" : 5126, + "count" : 350, + "type" : "VEC3" + }, + { + "bufferView" : 31, + "componentType" : 5121, + "count" : 350, + "type" : "VEC4" + }, + { + "bufferView" : 32, + "componentType" : 5126, + "count" : 350, + "type" : "VEC4" + }, + { + "bufferView" : 33, + "componentType" : 5123, + "count" : 372, + "type" : "SCALAR" + }, + { + "bufferView" : 34, + "componentType" : 5126, + "count" : 350, + "max" : [ + 1.076725721359253, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 35, + "componentType" : 5126, + "count" : 350, + "type" : "VEC3" + }, + { + "bufferView" : 36, + "componentType" : 5126, + "count" : 350, + "max" : [ + 0, + 0, + 0.0028746724128723145 + ], + "min" : [ + 0, + -1.207041621208191, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 37, + "componentType" : 5126, + "count" : 350, + "type" : "VEC3" + }, + { + "bufferView" : 38, + "componentType" : 5126, + "count" : 350, + "max" : [ + 0, + 0, + 0 + ], + "min" : [ + -0.9204438924789429, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 39, + "componentType" : 5126, + "count" : 350, + "type" : "VEC3" + }, + { + "bufferView" : 40, + "componentType" : 5126, + "count" : 350, + "max" : [ + 0.60309898853302, + 0, + 0 + ], + "min" : [ + 0, + 0, + 0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 41, + "componentType" : 5126, + "count" : 350, + "type" : "VEC3" + }, + { + "bufferView" : 42, + "componentType" : 5126, + "count" : 1, + "type" : "MAT4" + }, + { + "bufferView" : 43, + "componentType" : 5126, + "count" : 97, + "max" : [ + 4 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 44, + "componentType" : 5126, + "count" : 97, + "type" : "VEC3" + }, + { + "bufferView" : 45, + "componentType" : 5126, + "count" : 97, + "type" : "VEC4" + }, + { + "bufferView" : 46, + "componentType" : 5126, + "count" : 60, + "max" : [ + 2.5 + ], + "min" : [ + 0.041666666666666664 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 47, + "componentType" : 5126, + "count" : 60, + "type" : "VEC3" + }, + { + "bufferView" : 48, + "componentType" : 5126, + "count" : 60, + "type" : "VEC4" + }, + { + "bufferView" : 49, + "componentType" : 5126, + "count" : 60, + "type" : "VEC3" + }, + { + "bufferView" : 50, + "componentType" : 5126, + "count" : 60, + "type" : "VEC3" + }, + { + "bufferView" : 51, + "componentType" : 5126, + "count" : 60, + "type" : "VEC4" + }, + { + "bufferView" : 52, + "componentType" : 5126, + "count" : 60, + "type" : "VEC3" + }, + { + "bufferView" : 53, + "componentType" : 5126, + "count" : 31, + "max" : [ + 1.25 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 54, + "componentType" : 5126, + "count" : 31, + "type" : "VEC3" + }, + { + "bufferView" : 55, + "componentType" : 5126, + "count" : 31, + "type" : "VEC4" + }, + { + "bufferView" : 56, + "componentType" : 5126, + "count" : 31, + "type" : "VEC3" + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 0, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1280, + "byteOffset" : 1920, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 3200, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 372, + "byteOffset" : 5120, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 5492, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 7412, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 9332, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 11252, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 13172, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 15092, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 17012, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 18932, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 20852, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 22772, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 24692, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 26612, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 28532, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 30452, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 32372, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1920, + "byteOffset" : 34292, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 384, + "byteOffset" : 36212, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 256, + "byteOffset" : 36596, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 384, + "byteOffset" : 36852, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 72, + "byteOffset" : 37236, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 384, + "byteOffset" : 37308, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 384, + "byteOffset" : 37692, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 384, + "byteOffset" : 38076, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 384, + "byteOffset" : 38460, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 38844, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 2800, + "byteOffset" : 43044, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 45844, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1400, + "byteOffset" : 50044, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 5600, + "byteOffset" : 51444, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 744, + "byteOffset" : 57044, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 57788, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 61988, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 66188, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 70388, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 74588, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 78788, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 82988, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 4200, + "byteOffset" : 87188, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 91388 + }, + { + "buffer" : 0, + "byteLength" : 388, + "byteOffset" : 91452 + }, + { + "buffer" : 0, + "byteLength" : 1164, + "byteOffset" : 91840 + }, + { + "buffer" : 0, + "byteLength" : 1552, + "byteOffset" : 93004 + }, + { + "buffer" : 0, + "byteLength" : 240, + "byteOffset" : 94556 + }, + { + "buffer" : 0, + "byteLength" : 720, + "byteOffset" : 94796 + }, + { + "buffer" : 0, + "byteLength" : 960, + "byteOffset" : 95516 + }, + { + "buffer" : 0, + "byteLength" : 720, + "byteOffset" : 96476 + }, + { + "buffer" : 0, + "byteLength" : 720, + "byteOffset" : 97196 + }, + { + "buffer" : 0, + "byteLength" : 960, + "byteOffset" : 97916 + }, + { + "buffer" : 0, + "byteLength" : 720, + "byteOffset" : 98876 + }, + { + "buffer" : 0, + "byteLength" : 124, + "byteOffset" : 99596 + }, + { + "buffer" : 0, + "byteLength" : 372, + "byteOffset" : 99720 + }, + { + "buffer" : 0, + "byteLength" : 496, + "byteOffset" : 100092 + }, + { + "buffer" : 0, + "byteLength" : 372, + "byteOffset" : 100588 + } + ], + "buffers" : [ + { + "byteLength" : 100960, + "uri" : "shapes.bin" + } + ] +} diff --git a/flutter_filament_federated/flutter_filament/example/assets/shapes/texture_test.png b/flutter_filament_federated/flutter_filament/example/assets/shapes/texture_test.png new file mode 100644 index 00000000..615a30a1 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/shapes/texture_test.png differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/solidcolor.filamat b/flutter_filament_federated/flutter_filament/example/assets/solidcolor.filamat new file mode 100644 index 00000000..e17086dc Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/assets/solidcolor.filamat differ diff --git a/flutter_filament_federated/flutter_filament/example/assets/solidcolor.mat b/flutter_filament_federated/flutter_filament/example/assets/solidcolor.mat new file mode 100644 index 00000000..d3d46bd0 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/assets/solidcolor.mat @@ -0,0 +1,14 @@ +material { + name : SolidColor, + shadingModel : unlit, + culling : none, + featureLevel : 1, + vertexDomain: object +} + +fragment { + void material(inout MaterialInputs material) { + prepareMaterial(material); + material.baseColor = vec4(0.1f, 0.5f, 0.9f, 1.0f); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/compare_goldens.sh b/flutter_filament_federated/flutter_filament/example/compare_goldens.sh new file mode 100644 index 00000000..952ec892 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/compare_goldens.sh @@ -0,0 +1,9 @@ +#!/bin/bash +device=$1 +if [ -z "$device" ]; then + echo "Usage: $0 " + exit 1; +fi + +rm -f integration_test/goldens/{ios,macos,windows,android}/diffs/*.png +flutter drive --driver=test_driver/integration_test.dart -d $1 --target=integration_test/plugin_integration_test.dart diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/0_fresh.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/0_fresh.png new file mode 100644 index 00000000..e4fcd2be Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/0_fresh.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/10_setshapespositionto.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/10_setshapespositionto.png new file mode 100644 index 00000000..1725f564 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/10_setshapespositionto.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/11_Disablefrustumculling.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/11_Disablefrustumculling.png new file mode 100644 index 00000000..02f6107a Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/11_Disablefrustumculling.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/12_Settonemappingtolinear.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/12_Settonemappingtolinear.png new file mode 100644 index 00000000..fd17520e Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/12_Settonemappingtolinear.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/13_Movecameratoasset.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/13_Movecameratoasset.png new file mode 100644 index 00000000..eb3c28a0 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/13_Movecameratoasset.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/14_movecamerato.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/14_movecamerato.png new file mode 100644 index 00000000..36cb9635 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/14_movecamerato.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/15_setcameratofirstcamerainshapesGLB.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/15_setcameratofirstcamerainshapesGLB.png new file mode 100644 index 00000000..ab7f2111 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/15_setcameratofirstcamerainshapesGLB.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/16_resize.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/16_resize.png new file mode 100644 index 00000000..e5dfd1f3 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/16_resize.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/17_resize.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/17_resize.png new file mode 100644 index 00000000..a5296b61 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/17_resize.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/18_resize.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/18_resize.png new file mode 100644 index 00000000..d7fa1a56 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/18_resize.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/19_resize.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/19_resize.png new file mode 100644 index 00000000..541ad920 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/19_resize.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/1_createviewerdefaultubershader.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/1_createviewerdefaultubershader.png new file mode 100644 index 00000000..c4209f1f Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/1_createviewerdefaultubershader.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/2_Renderingfalse.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/2_Renderingfalse.png new file mode 100644 index 00000000..d6c9c5fc Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/2_Renderingfalse.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/3_loadskybox.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/3_loadskybox.png new file mode 100644 index 00000000..05169daf Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/3_loadskybox.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/4_loadIBL.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/4_loadIBL.png new file mode 100644 index 00000000..a65a452a Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/4_loadIBL.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/5_loadshapesGLB.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/5_loadshapesGLB.png new file mode 100644 index 00000000..162d5bf8 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/5_loadshapesGLB.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/6_zoomin.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/6_zoomin.png new file mode 100644 index 00000000..84f3b216 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/6_zoomin.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/7_rotate.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/7_rotate.png new file mode 100644 index 00000000..5dd18d0b Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/7_rotate.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/8_pan.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/8_pan.png new file mode 100644 index 00000000..6535d5d2 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/8_pan.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/9_transformtounitcube.png b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/9_transformtounitcube.png new file mode 100644 index 00000000..fa7b9684 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/integration_test/goldens/ios/9_transformtounitcube.png differ diff --git a/flutter_filament_federated/flutter_filament/example/integration_test/plugin_integration_test.dart b/flutter_filament_federated/flutter_filament/example/integration_test/plugin_integration_test.dart new file mode 100644 index 00000000..5eaf76f4 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/integration_test/plugin_integration_test.dart @@ -0,0 +1,190 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:ui'; + +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_filament/filament/widgets/filament_widget.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import '../lib/main.dart' as app; + +void main() { + final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized() + as IntegrationTestWidgetsFlutterBinding; + + late String platformIdentifier; + if (Platform.isIOS) { + platformIdentifier = "ios"; + } else if (Platform.isAndroid) { + platformIdentifier = "android"; + } else if (Platform.isMacOS) { + platformIdentifier = "macos"; + } else if (Platform.isWindows) { + platformIdentifier = "windows"; + } else if (Platform.isLinux) { + platformIdentifier = "linux"; + } else { + throw Exception("Unexpected platform"); + } + + int _counter = 0; + + Future _snapshot(WidgetTester tester, String label, [int seconds = 0]) async { + await tester.pumpAndSettle(Duration(milliseconds: 16)); + for (int i = 0; i < seconds; i++) { + await Future.delayed(Duration(seconds: 1)); + await tester.pumpAndSettle(Duration(milliseconds: 16)); + } + await tester.pumpAndSettle(Duration(milliseconds: 16)); + var screenshotPath = '$platformIdentifier/${_counter}_$label'; + if (Platform.isIOS) { + // this is currently hanging on Android + // see https://github.com/flutter/flutter/issues/127306 + // it is also not yet implemented on Windows or MacOS + await binding.convertFlutterSurfaceToImage(); + final bytes = await binding.takeScreenshot(screenshotPath); + } + _counter++; + } + + Future tap(WidgetTester tester, String label, [int seconds = 0]) async { + var target = find.text(label, skipOffstage: false); + + if (!target.hasFound) { + print("Couldn't find target, waiting 100ms"); + await tester.pump(const Duration(milliseconds: 100)); + target = find.text(label); + } + + await tester.tap(target.first); + await _snapshot(tester, label.replaceAll(RegExp("[ -:]"), ""), seconds); + } + + Future pumpUntilFound( + WidgetTester tester, + Finder finder, { + Duration timeout = const Duration(seconds: 30), + }) async { + bool timerDone = false; + final timer = Timer( + timeout, () => throw TimeoutException("Pump until has timed out")); + while (timerDone != true) { + await tester.pump(); + + final found = tester.any(finder); + if (found) { + timerDone = true; + } + } + timer.cancel(); + } + + testWidgets('test', (WidgetTester tester) async { + app.main(); + await pumpUntilFound(tester, find.byType(app.ExampleWidget)); + + await tester.pumpAndSettle(); + + await _snapshot(tester, "fresh"); + + await tap(tester, "Controller / Viewer"); + await tap(tester, "Create FlutterFilamentPlugin (default ubershader)"); + await tap(tester, "Controller / Viewer"); + await tap(tester, "Create FilamentViewer", + 4); // on older devices this may take a while, so let's insert a length delay + + await tap(tester, "Scene"); + await tap(tester, "Rendering"); + await tap(tester, "Set continuous rendering to true"); + + await tap(tester, "Scene"); + await tap(tester, "Assets"); + await tap(tester, "Shapes"); + await tap(tester, "Load GLB"); + + await tester.pump(); + + await tap(tester, "Scene"); + await tap(tester, "Assets"); + await tap(tester, "Load skybox", 1); + + await tap(tester, "Scene"); + await tap(tester, "Assets"); + await tap(tester, "Load IBL", 1); + + final Offset pointerLocation = + tester.getCenter(find.byType(FilamentWidget)); + TestPointer testPointer = TestPointer(1, PointerDeviceKind.mouse); + + // scroll/zoom + testPointer.hover(pointerLocation); + await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 1.0))); + await tester.pumpAndSettle(); + await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 1.0))); + await tester.pumpAndSettle(); + await _snapshot(tester, "zoomin"); + + // rotate + testPointer = + TestPointer(1, PointerDeviceKind.mouse, null, kTertiaryButton); + testPointer.hover(pointerLocation); + await tester.sendEventToBinding(testPointer.down(pointerLocation)); + await tester.pumpAndSettle(); + await tester.sendEventToBinding( + testPointer.move(pointerLocation + Offset(10.0, 10.0))); + await tester.pumpAndSettle(); + await tester.sendEventToBinding( + testPointer.move(pointerLocation + Offset(20.0, 20.0))); + await tester.pumpAndSettle(); + await tester.sendEventToBinding(testPointer.up()); + + await _snapshot(tester, "rotate", 2); + + // pan + testPointer = TestPointer(1, PointerDeviceKind.mouse, null, kPrimaryButton); + testPointer.hover(pointerLocation); + await tester.sendEventToBinding(testPointer.down(pointerLocation)); + await tester + .sendEventToBinding(testPointer.move(pointerLocation + Offset(0, 1.0))); + + for (int i = 0; i < 60; i++) { + await tester.sendEventToBinding(testPointer + .move(pointerLocation + Offset(i.toDouble() * 2, i.toDouble() * 2))); + await tester.pumpAndSettle(); + } + await tester.sendEventToBinding(testPointer.up()); + await tester.pumpAndSettle(); + + await _snapshot(tester, "pan"); + + await tap(tester, "Scene"); + await tap(tester, "Assets"); + await tap(tester, "Shapes"); + await tap(tester, "Transform to unit cube"); + + await tap(tester, "Scene"); + await tap(tester, "Assets"); + await tap(tester, "Shapes"); + await tap(tester, "Set position to 1, 1, -1"); + + await tap(tester, "Scene"); + await tap(tester, "Camera"); + await tap(tester, "Disable frustum culling"); + + await tap(tester, "Scene"); + await tap(tester, "Rendering"); + await tap(tester, "Set tone mapping to linear"); + + await tap(tester, "Scene"); + await tap(tester, "Camera"); + await tap(tester, 'Set to first camera in last added asset'); + + await tap(tester, "Move to last added asset"); + await tap(tester, "Move to 1, 1, -1"); + + await tap(tester, 'Toggle viewport size', 1); + await tap(tester, 'Toggle viewport size', 1); + await tap(tester, 'Toggle viewport size', 1); + }); +} diff --git a/flutter_filament_federated/flutter_filament/example/ios/.gitignore b/flutter_filament_federated/flutter_filament/example/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/flutter_filament_federated/flutter_filament/example/ios/Flutter/AppFrameworkInfo.plist b/flutter_filament_federated/flutter_filament/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..7c569640 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Flutter/Debug.xcconfig b/flutter_filament_federated/flutter_filament/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..ec97fc6f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/flutter_filament_federated/flutter_filament/example/ios/Flutter/Release.xcconfig b/flutter_filament_federated/flutter_filament/example/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..c4855bfe --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/flutter_filament_federated/flutter_filament/example/ios/Podfile b/flutter_filament_federated/flutter_filament/example/ios/Podfile new file mode 100644 index 00000000..18b956ee --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '13.1' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/flutter_filament_federated/flutter_filament/example/ios/Podfile.lock b/flutter_filament_federated/flutter_filament/example/ios/Podfile.lock new file mode 100644 index 00000000..4588f1cd --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Podfile.lock @@ -0,0 +1,41 @@ +PODS: + - Flutter (1.0.0) + - flutter_filament (0.0.1): + - Flutter + - integration_test (0.0.1): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - permission_handler_apple (9.3.0): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - flutter_filament (from `.symlinks/plugins/flutter_filament/ios`) + - integration_test (from `.symlinks/plugins/integration_test/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + flutter_filament: + :path: ".symlinks/plugins/flutter_filament/ios" + integration_test: + :path: ".symlinks/plugins/integration_test/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + +SPEC CHECKSUMS: + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_filament: 931482c60f0020743ef1a87350e0620079c22b61 + integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 + +PODFILE CHECKSUM: a4605dec2dc7bf1ddcfc6f5f4cb7515785c9865e + +COCOAPODS: 1.15.2 diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.pbxproj b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..bfb819a8 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,599 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + EE85ADA13CE47012212956FB /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A258321425FD15835C0E85C8 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0E69A8E4F4FBCA8CA51688D8 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 887CF3E1D8F177CD306AEE91 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A258321425FD15835C0E85C8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E540D86FF0BEABF308A14DBB /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EE85ADA13CE47012212956FB /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 359B21BE5E35E51F8685F431 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A258321425FD15835C0E85C8 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + D3880C741B2115E941EC88CD /* Pods */, + 359B21BE5E35E51F8685F431 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + D3880C741B2115E941EC88CD /* Pods */ = { + isa = PBXGroup; + children = ( + 0E69A8E4F4FBCA8CA51688D8 /* Pods-Runner.debug.xcconfig */, + 887CF3E1D8F177CD306AEE91 /* Pods-Runner.release.xcconfig */, + E540D86FF0BEABF308A14DBB /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 2ED3154DB81A6C5E50B63848 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + F9FAB8A67CF505858CCDA424 /* [CP] Embed Pods Frameworks */, + 55F3237D47F23FE63525E002 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2ED3154DB81A6C5E50B63848 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 55F3237D47F23FE63525E002 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + F9FAB8A67CF505858CCDA424 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEAD_CODE_STRIPPING = NO; + DEVELOPMENT_TEAM = TM2B4SJXNJ; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = "-fvisibility=default"; + PRODUCT_BUNDLE_IDENTIFIER = app.polyvox.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + STRIP_STYLE = "non-global"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEAD_CODE_STRIPPING = NO; + DEVELOPMENT_TEAM = TM2B4SJXNJ; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = "-fvisibility=default"; + PRODUCT_BUNDLE_IDENTIFIER = app.polyvox.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + STRIP_STYLE = "non-global"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEAD_CODE_STRIPPING = NO; + DEVELOPMENT_TEAM = TM2B4SJXNJ; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = "-fvisibility=default"; + PRODUCT_BUNDLE_IDENTIFIER = app.polyvox.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + STRIP_STYLE = "non-global"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..5e31d3d3 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/AppDelegate.swift b/flutter_filament_federated/flutter_filament/example/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..b6363034 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 00000000..dc9ada47 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 00000000..28c6bf03 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 00000000..2ccbfd96 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 00000000..f091b6b0 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 00000000..4cde1211 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 00000000..d0ef06e7 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 00000000..dcdc2306 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 00000000..2ccbfd96 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 00000000..c8f9ed8f Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 00000000..a6d6b860 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 00000000..a6d6b860 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 00000000..75b2d164 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 00000000..c4df70d3 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 00000000..6a84f41e Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 00000000..d0e1f585 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/flutter_filament_federated/flutter_filament/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Base.lproj/Main.storyboard b/flutter_filament_federated/flutter_filament/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Info.plist b/flutter_filament_federated/flutter_filament/example/ios/Runner/Info.plist new file mode 100644 index 00000000..7f553465 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/flutter_filament_federated/flutter_filament/example/ios/Runner/Runner-Bridging-Header.h b/flutter_filament_federated/flutter_filament/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/flutter_filament_federated/flutter_filament/example/ios/RunnerTests/RunnerTests.swift b/flutter_filament_federated/flutter_filament/example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..481885f5 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,26 @@ +import Flutter +import UIKit +import XCTest + +@testable import flutter_filament + +// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. +// +// See https://developer.apple.com/documentation/xctest for more information about using XCTest. + +class RunnerTests: XCTestCase { + + func testGetPlatformVersion() { + let plugin = FlutterFilamentPlugin() + + let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) + + let resultExpectation = expectation(description: "result block must be called.") + plugin.handle(call) { result in + XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) + resultExpectation.fulfill() + } + waitForExpectations(timeout: 1) + } + +} diff --git a/flutter_filament_federated/flutter_filament/example/lib/camera_matrix_overlay.dart b/flutter_filament_federated/flutter_filament/example/lib/camera_matrix_overlay.dart new file mode 100644 index 00000000..3de056c1 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/camera_matrix_overlay.dart @@ -0,0 +1,138 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_filament/flutter_filament.dart'; +import 'package:vector_math/vector_math_64.dart' as v; + +class CameraMatrixOverlay extends StatefulWidget { + final FlutterFilamentPlugin controller; + final bool showProjectionMatrices; + + const CameraMatrixOverlay( + {super.key, + required this.controller, + required this.showProjectionMatrices}); + + @override + State createState() => _CameraMatrixOverlayState(); +} + +class _CameraMatrixOverlayState extends State { + Timer? _cameraTimer; + String? _cameraPosition; + String? _cameraRotation; + + String? _cameraProjectionMatrix; + String? _cameraCullingProjectionMatrix; + + void _tick(Timer timer) async { + var cameraPosition = await widget.controller.getCameraPosition(); + var cameraRotation = await widget.controller.getCameraRotation(); + + _cameraPosition = + "${cameraPosition.storage.map((v) => v.toStringAsFixed(2))}"; + _cameraRotation = + "${cameraRotation.storage.map((v) => v.toStringAsFixed(2))}"; + + if (widget.showProjectionMatrices) { + var projMatrix = await widget.controller.getCameraProjectionMatrix(); + var cullingMatrix = + await widget.controller.getCameraCullingProjectionMatrix(); + + _cameraProjectionMatrix = + projMatrix.storage.map((v) => v.toStringAsFixed(2)).join(","); + _cameraCullingProjectionMatrix = + cullingMatrix.storage.map((v) => v.toStringAsFixed(2)).join(","); + _getFrustum(); + } + + setState(() {}); + } + + void _updateTimer() async { + _cameraTimer?.cancel(); + await widget.controller.initialized; + } + + v.Frustum? _frustum; + + void _getFrustum() async { + _frustum = await widget.controller.getCameraFrustum(); + } + + @override + void initState() { + super.initState(); + _updateTimer(); + } + + @override + void didUpdateWidget(CameraMatrixOverlay oldWidget) { + super.didUpdateWidget(oldWidget); + setState(() {}); + } + + @override + void dispose() { + super.dispose(); + _cameraTimer?.cancel(); + } + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.5), + borderRadius: BorderRadius.circular(29)), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text("Camera : $_cameraPosition $_cameraRotation", + style: + const TextStyle(color: Colors.white, fontSize: 10)), + // widget.showProjectionMatrices + // ? Text("Projection matrix : $_cameraProjectionMatrix", + // style: const TextStyle(color: Colors.white, fontSize: 12)) + // : Container(), + // widget.showProjectionMatrices + // ? Text("Culling matrix : $_cameraCullingProjectionMatrix", + // style: const TextStyle(color: Colors.white, fontSize: 12)) + // : Container(), + widget.showProjectionMatrices + ? const Text("Frustum matrix", + style: TextStyle(color: Colors.white, fontSize: 10)) + : Container() + ] + + (_frustum == null + ? [] + : [ + _frustum!.plane0, + _frustum!.plane1, + _frustum!.plane2, + _frustum!.plane3, + _frustum!.plane4, + _frustum!.plane5 + ] + .map((plane) => Row( + children: [ + plane.normal.x, + plane.normal.y, + plane.normal.z, + plane.constant + ] + .map((v) => Text( + v.toStringAsFixed(2) + " ", + style: const TextStyle( + color: Colors.white, + fontSize: 10), + textAlign: TextAlign.center, + )) + .cast() + .toList())) + .cast() + .toList()))); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/lib/example_viewport.dart b/flutter_filament_federated/flutter_filament/example/lib/example_viewport.dart new file mode 100644 index 00000000..e2141ab5 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/example_viewport.dart @@ -0,0 +1,32 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_filament/flutter_filament.dart'; + +class ExampleViewport extends StatelessWidget { + final FlutterFilamentPlugin? controller; + final EntityTransformController? entityTransformController; + final EdgeInsets padding; + final FocusNode keyboardFocusNode; + + const ExampleViewport( + {super.key, + required this.controller, + required this.padding, + required this.keyboardFocusNode, + this.entityTransformController}); + + @override + Widget build(BuildContext context) { + return controller != null + ? Padding( + padding: padding, + child: EntityTransformMouseControllerWidget( + transformController: entityTransformController, + child: FilamentGestureDetector( + showControlOverlay: true, + controller: controller!, + child: FilamentWidget( + plugin: controller!, + )))) + : Container(); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/lib/main.dart b/flutter_filament_federated/flutter_filament/example/lib/main.dart new file mode 100644 index 00000000..819ad48b --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/main.dart @@ -0,0 +1,214 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/material.dart'; + +import 'package:flutter_filament_example/camera_matrix_overlay.dart'; +import 'package:flutter_filament_example/menus/controller_menu.dart'; +import 'package:flutter_filament_example/example_viewport.dart'; +import 'package:flutter_filament_example/picker_result_widget.dart'; +import 'package:flutter_filament_example/menus/scene_menu.dart'; + +import 'package:flutter_filament/flutter_filament.dart'; + +const loadDefaultScene = bool.hasEnvironment('--load-default-scene'); + +void main() async { + print(loadDefaultScene); + runApp(const MyApp()); +} + +class MyApp extends StatefulWidget { + const MyApp({Key? key}) : super(key: key); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State with SingleTickerProviderStateMixin { + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ThemeData( + useMaterial3: true, + textTheme: const TextTheme( + labelLarge: TextStyle(fontSize: 12), + displayMedium: TextStyle(fontSize: 12), + headlineMedium: const TextStyle(fontSize: 12), + titleMedium: TextStyle(fontSize: 12), + bodyLarge: TextStyle(fontSize: 14), + bodyMedium: TextStyle(fontSize: 12))), + // showPerformanceOverlay: true, + home: const Scaffold(body: ExampleWidget())); + } +} + +class ExampleWidget extends StatefulWidget { + const ExampleWidget({super.key}); + + @override + State createState() { + return ExampleWidgetState(); + } +} + +enum MenuType { controller, assets, camera, misc } + +class ExampleWidgetState extends State { + FlutterFilamentPlugin? _plugin; + + EdgeInsets _viewportMargin = EdgeInsets.zero; + + // these are all the options that can be set via the menu + // we store them here + static bool rendering = false; + static bool recording = false; + static int framerate = 60; + static bool postProcessing = false; + static bool antiAliasingMsaa = false; + static bool antiAliasingTaa = false; + static bool antiAliasingFxaa = false; + static bool frustumCulling = true; + + static double zoomSpeed = 0.01; + static double orbitSpeedX = 0.01; + static double orbitSpeedY = 0.01; + + static bool hasSkybox = false; + static bool coneHidden = false; + + static bool loop = false; + static final showProjectionMatrices = ValueNotifier(false); + + late StreamSubscription _listener; + + @override + void initState() { + super.initState(); + if (loadDefaultScene) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + _plugin = await FlutterFilamentPlugin.create(); + setState(() {}); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + await _plugin!.initialized; + + await _plugin! + .loadSkybox("assets/default_env/default_env_skybox.ktx"); + + await _plugin!.setRendering(true); + + await _plugin!.loadGlb("assets/shapes/shapes.glb"); + + await _plugin!.setCameraManipulatorOptions(zoomSpeed: 1.0); + + hasSkybox = true; + rendering = true; + }); + }); + } + } + + @override + void dispose() { + super.dispose(); + _listener.cancel(); + } + + EntityTransformController? _transformController; + + final _sharedFocusNode = FocusNode(); + + @override + Widget build(BuildContext context) { + return Stack(children: [ + Positioned.fill( + child: ExampleViewport( + controller: _plugin, + entityTransformController: _transformController, + padding: _viewportMargin, + keyboardFocusNode: _sharedFocusNode), + ), + EntityListWidget(controller: _plugin), + Positioned( + bottom: Platform.isIOS ? 30 : 0, + left: 0, + right: 10, + height: 30, + child: Container( + height: 30, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Colors.white.withOpacity(0.25), + ), + padding: const EdgeInsets.symmetric(horizontal: 10), + child: + Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ + ControllerMenu( + sharedFocusNode: _sharedFocusNode, + controller: _plugin, + onToggleViewport: () { + setState(() { + _viewportMargin = (_viewportMargin == EdgeInsets.zero) + ? const EdgeInsets.all(30) + : EdgeInsets.zero; + }); + }, + onControllerDestroyed: () {}, + onControllerCreated: (controller) { + setState(() { + _plugin = controller; + }); + }), + SceneMenu( + sharedFocusNode: _sharedFocusNode, + controller: _plugin, + ), + GestureDetector( + onTap: () async { + await _plugin! + .loadGlb('assets/shapes/shapes.glb', numInstances: 1); + }, + child: Container( + color: Colors.transparent, + child: const Text("shapes.glb"))), + const SizedBox(width: 5), + GestureDetector( + onTap: () async { + await _plugin!.loadGlb('assets/1.glb'); + }, + child: Container( + color: Colors.transparent, child: const Text("1.glb"))), + const SizedBox(width: 5), + GestureDetector( + onTap: () async { + await _plugin!.loadGlb('assets/2.glb'); + }, + child: Container( + color: Colors.transparent, child: const Text("2.glb"))), + const SizedBox(width: 5), + GestureDetector( + onTap: () async { + await _plugin!.loadGlb('assets/3.glb'); + }, + child: Container( + color: Colors.transparent, child: const Text("3.glb"))), + Expanded(child: Container()), + ]))), + _plugin == null + ? Container() + : Padding( + padding: const EdgeInsets.only(top: 10, left: 20, right: 20), + child: ValueListenableBuilder( + valueListenable: showProjectionMatrices, + builder: (ctx, value, child) => CameraMatrixOverlay( + controller: _plugin!, showProjectionMatrices: value)), + ), + _plugin == null + ? Container() + : Align( + alignment: Alignment.topRight, + child: PickerResultWidget(controller: _plugin!), + ) + ]); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/lib/menus/asset_submenu.dart b/flutter_filament_federated/flutter_filament/example/lib/menus/asset_submenu.dart new file mode 100644 index 00000000..b3c488fc --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/menus/asset_submenu.dart @@ -0,0 +1,372 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:flutter_filament/flutter_filament.dart'; +import 'package:flutter_filament_example/main.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:animation_tools_dart/animation_tools_dart.dart'; +import 'package:vector_math/vector_math_64.dart' as v; +import 'package:dart_filament/dart_filament.dart'; + +class AssetSubmenu extends StatefulWidget { + final FlutterFilamentPlugin controller; + const AssetSubmenu({super.key, required this.controller}); + + @override + State createState() => _AssetSubmenuState(); +} + +class _AssetSubmenuState extends State { + @override + void initState() { + super.initState(); + } + + Widget _shapesSubmenu() { + var children = [ + MenuItemButton( + closeOnActivate: false, + onPressed: () async { + var entity = await widget.controller.getChildEntity( + widget.controller.scene.listEntities().last, "Cylinder"); + await showDialog( + context: context, + builder: (BuildContext context) { + return Center( + child: Container( + color: Colors.white, child: Text(entity.toString()))); + }); + }, + child: const Text('Find Cylinder entity by name')), + MenuItemButton( + onPressed: () async { + await widget.controller.addBoneAnimation( + widget.controller.scene.listEntities().last, + BoneAnimationData([ + "Bone" + ], [ + "Cylinder" + ], [ + [v.Quaternion.axisAngle(v.Vector3(1, 1, 1), pi / 2)] + ], [ + [v.Vector3.zero()] + ], 16)); + }, + child: + const Text('Set bone transform for Cylinder (pi/2 rotation X)')), + MenuItemButton( + onPressed: () async { + await widget.controller + .resetBones(widget.controller.scene.listEntities().last); + }, + child: const Text('Reset bones for Cylinder')), + MenuItemButton( + onPressed: () async { + await widget.controller.addBoneAnimation( + widget.controller.scene.listEntities().last, + BoneAnimationData( + ["Bone"], + ["Cylinder"], + List.generate( + 60, + (idx) => [ + v.Quaternion.axisAngle( + v.Vector3(0, 0, 1), pi * 8 * (idx / 60)) + .normalized() + ]), + List.generate(60, (idx) => [v.Vector3.zero()]), + 1000.0 / 60.0)); + }, + child: const Text('Set bone transform animation for Cylinder')), + MenuItemButton( + closeOnActivate: false, + onPressed: () async { + var names = await widget.controller.getMorphTargetNames( + widget.controller.scene.listEntities().last, "Cylinder"); + print("NAMES : $names"); + await showDialog( + context: context, + builder: (ctx) { + return Container( + height: 100, + width: 100, + color: Colors.white, + child: Text(names.join(","))); + }); + }, + child: const Text("Show morph target names for Cylinder")), + MenuItemButton( + onPressed: () async { + var cylinder = await widget.controller.getChildEntity( + widget.controller.scene.listEntities().last, "Cylinder"); + widget.controller + .setMorphTargetWeights(cylinder, List.filled(4, 1.0)); + }, + child: const Text("set Cylinder morph weights to 1")), + MenuItemButton( + onPressed: () async { + var cylinder = await widget.controller.getChildEntity( + widget.controller.scene.listEntities().last, "Cylinder"); + widget.controller + .setMorphTargetWeights(cylinder, List.filled(4, 0.0)); + }, + child: const Text("Set Cylinder morph weights to 0")), + MenuItemButton( + onPressed: () async { + var morphTargets = await widget.controller.getMorphTargetNames( + widget.controller.scene.listEntities().last, "Cylinder"); + + var morphData = MorphAnimationData( + List.generate( + 60, + (frameNum) => + List.generate(4, (morphIndex) => frameNum / 60)), + morphTargets); + await widget.controller.setMorphAnimationData( + widget.controller.scene.listEntities().last, morphData, + targetMeshNames: [ + "Cylinder", + ]); + }, + child: const Text("create manual morph animation for Cylinder")), + MenuItemButton( + onPressed: () async { + widget.controller.setPosition( + widget.controller.scene.listEntities().last, 1.0, 1.0, -1.0); + }, + child: const Text('Set position to 1, 1, -1'), + ), + MenuItemButton( + onPressed: () async { + if (ExampleWidgetState.coneHidden) { + widget.controller + .reveal(widget.controller.scene.listEntities().last, "Cone"); + } else { + widget.controller + .hide(widget.controller.scene.listEntities().last, "Cone"); + } + + ExampleWidgetState.coneHidden = !ExampleWidgetState.coneHidden; + }, + child: + Text(ExampleWidgetState.coneHidden ? 'show cone' : 'hide cone')), + MenuItemButton( + onPressed: () async { + final color = Colors.purple; + widget.controller.setMaterialColor( + widget.controller.scene.listEntities().last, + "Cone", + 0, + color.red / 255.0, + color.green / 255.0, + color.blue / 255.0, + 1.0); + }, + child: const Text("Set cone material color to purple")), + MenuItemButton( + onPressed: () async { + ExampleWidgetState.loop = !ExampleWidgetState.loop; + }, + child: Text( + "Toggle animation looping ${ExampleWidgetState.loop ? "OFF" : "ON"}")) + ]; + + return SubmenuButton(menuChildren: children, child: const Text("Shapes")); + } + + Widget _geometrySubmenu() { + return SubmenuButton( + menuChildren: [ + MenuItemButton( + onPressed: () async { + var verts = [ + -1.0, + 0.0, + -1.0, + -1.0, + 0.0, + 1.0, + 1.0, + 0.0, + 1.0, + 1.0, + 0.0, + -1.0, + ]; + var indices = [0, 1, 2, 2, 3, 0]; + var geom = await widget.controller.createGeometry(verts, indices, + materialPath: "asset://assets/solidcolor.filamat"); + }, + child: const Text("Quad")), + MenuItemButton( + onPressed: () async { + await widget.controller.createGeometry([ + 0, + 0, + 0, + 1, + 0, + 0, + ], [ + 0, + 1 + ], primitiveType: PrimitiveType.LINES); + }, + child: const Text("Line")) + ], + child: const Text("Custom Geometry"), + ); + } + + @override + Widget build(BuildContext context) { + return SubmenuButton( + menuChildren: [ + _shapesSubmenu(), + _geometrySubmenu(), + MenuItemButton( + onPressed: () async { + await widget.controller + .addLight(1, 6500, 150000, 0, 1, 0, 0, -1, 0, true); + }, + child: const Text("Add directional light"), + ), + MenuItemButton( + onPressed: () async { + await widget.controller + .addLight(2, 6500, 150000, 0, 1, 0, 0, -1, 0, true); + }, + child: const Text("Add point light"), + ), + MenuItemButton( + onPressed: () async { + await widget.controller + .addLight(3, 6500, 15000000, 0, 1, 0, 0, -1, 0, true); + }, + child: const Text("Add spot light"), + ), + MenuItemButton( + onPressed: () async { + await widget.controller.clearLights(); + }, + child: const Text("Clear lights"), + ), + MenuItemButton( + onPressed: () { + final color = const Color(0xAA73C9FA); + widget.controller.setBackgroundColor(color.red / 255.0, + color.green / 255.0, color.blue / 255.0, 1.0); + }, + child: const Text("Set background color")), + MenuItemButton( + onPressed: () { + widget.controller.setBackgroundImage('assets/background.ktx'); + }, + child: const Text("Load background image")), + MenuItemButton( + onPressed: () { + widget.controller.setBackgroundImage('assets/background.ktx', + fillHeight: true); + }, + child: const Text("Load background image (fill height)")), + MenuItemButton( + onPressed: () { + if (ExampleWidgetState.hasSkybox) { + widget.controller.removeSkybox(); + } else { + widget.controller + .loadSkybox('assets/default_env/default_env_skybox.ktx'); + } + ExampleWidgetState.hasSkybox = !ExampleWidgetState.hasSkybox; + }, + child: Text(ExampleWidgetState.hasSkybox + ? 'Remove skybox' + : 'Load skybox')), + MenuItemButton( + onPressed: () { + widget.controller + .loadIbl('assets/default_env/default_env_ibl.ktx'); + }, + child: const Text('Load IBL')), + MenuItemButton( + onPressed: () { + widget.controller.removeIbl(); + }, + child: const Text('Remove IBL')), + MenuItemButton( + onPressed: () async { + await Permission.microphone.request(); + }, + child: const Text("Request permissions (tests inactive->resume)")), + MenuItemButton( + onPressed: () async { + await widget.controller.clearEntities(); + }, + child: const Text('Clear assets')), + ], + child: const Text("Assets"), + ); + } +} + + +// _item(() async { +// var frameData = Float32List.fromList( +// List.generate(120, (i) => i / 120).expand((x) { +// var vals = List.filled(7, x); +// vals[3] = 1.0; +// // vals[4] = 0; +// vals[5] = 0; +// vals[6] = 0; +// return vals; +// }).toList()); + +// widget.controller!.setBoneAnimation( +// _shapes!, +// BoneAnimationData( +// "Bone.001", ["Cube.001"], frameData, 1000.0 / 60.0)); +// // , +// // "Bone.001", +// // "Cube.001", +// // BoneTransform([Vec3(x: 0, y: 0.0, z: 0.0)], +// // [Quaternion(x: 1, y: 1, z: 1, w: 1)])); +// }, 'construct bone animation'), + +// _item(() async { +// var morphs = await widget.controller! +// .getMorphTargetNames(_shapes!, "Cylinder"); +// final animation = AnimationBuilder( +// availableMorphs: morphs, +// framerate: 30, +// meshName: "Cylinder") +// .setDuration(4) +// .setMorphTargets(["Key 1", "Key 2"]) +// .interpolateMorphWeights(0, 4, 0, 1) +// .build(); +// widget.controller!.setMorphAnimationData(_shapes!, animation); +// }, "animate cylinder morph weights #1 and #2"), +// _item(() async { +// var morphs = await widget.controller! +// .getMorphTargetNames(_shapes!, "Cylinder"); +// final animation = AnimationBuilder( +// availableMorphs: morphs, +// framerate: 30, +// meshName: "Cylinder") +// .setDuration(4) +// .setMorphTargets(["Key 3", "Key 4"]) +// .interpolateMorphWeights(0, 4, 0, 1) +// .build(); +// widget.controller!.setMorphAnimationData(_shapes!, animation); +// }, "animate cylinder morph weights #3 and #4"), +// _item(() async { +// var morphs = await widget.controller! +// .getMorphTargetNames(_shapes!, "Cube"); +// final animation = AnimationBuilder( +// availableMorphs: morphs, framerate: 30, meshName: "Cube") +// .setDuration(4) +// .setMorphTargets(["Key 1", "Key 2"]) +// .interpolateMorphWeights(0, 4, 0, 1) +// .build(); +// widget.controller!.setMorphAnimationData(_shapes!, animation); +// }, "animate shapes morph weights #1 and #2"), + diff --git a/flutter_filament_federated/flutter_filament/example/lib/menus/camera_submenu.dart b/flutter_filament_federated/flutter_filament/example/lib/menus/camera_submenu.dart new file mode 100644 index 00000000..f32ae082 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/menus/camera_submenu.dart @@ -0,0 +1,225 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:vector_math/vector_math_64.dart' as v; +import 'package:flutter_filament/flutter_filament.dart'; +import 'package:dart_filament/dart_filament.dart'; + +import 'package:flutter_filament_example/main.dart'; + +class CameraSubmenu extends StatefulWidget { + final FlutterFilamentPlugin controller; + const CameraSubmenu({super.key, required this.controller}); + + @override + State createState() => _CameraSubmenuState(); +} + +class _CameraSubmenuState extends State { + double? _near; + double? _far; + + @override + void initState() { + super.initState(); + widget.controller.initialized.then((_) { + widget.controller.getCameraCullingNear().then((v) { + _near = v; + widget.controller.getCameraCullingFar().then((v) { + _far = v; + setState(() {}); + }); + }); + }); + } + + final _menuController = MenuController(); + + List _cameraMenu() { + return [ + MenuItemButton( + closeOnActivate: false, + onPressed: () async { + ExampleWidgetState.showProjectionMatrices.value = + !ExampleWidgetState.showProjectionMatrices.value; + print("Set to ${ExampleWidgetState.showProjectionMatrices}"); + }, + child: Text( + '${ExampleWidgetState.showProjectionMatrices.value ? "Hide" : "Display"} camera frustum', + style: TextStyle( + fontWeight: ExampleWidgetState.showProjectionMatrices.value + ? FontWeight.bold + : FontWeight.normal), + ), + ), + SubmenuButton( + menuChildren: [1.0, 7.0, 14.0, 28.0, 56.0] + .map((v) => MenuItemButton( + onPressed: () { + widget.controller.setCameraFocalLength(v); + }, + child: Text( + v.toStringAsFixed(2), + ), + )) + .toList(), + child: const Text("Set camera focal length")), + SubmenuButton( + menuChildren: [0.05, 0.1, 1.0, 10.0, 100.0] + .map((v) => MenuItemButton( + onPressed: () { + _near = v; + print("Setting camera culling to $_near $_far!"); + + widget.controller.setCameraCulling(_near!, _far!); + }, + child: Text( + v.toStringAsFixed(2), + ), + )) + .toList(), + child: const Text("Set near")), + SubmenuButton( + menuChildren: [5.0, 50.0, 500.0, 1000.0, 100000.0] + .map((v) => MenuItemButton( + onPressed: () { + _far = v; + print("Setting camera culling to $_near! $_far"); + widget.controller.setCameraCulling(_near!, _far!); + }, + child: Text( + v.toStringAsFixed(2), + ), + )) + .toList(), + child: const Text("Set far")), + MenuItemButton( + onPressed: () async { + widget.controller.setCameraPosition(1.0, 1.0, -1.0); + }, + child: const Text('Set position to 1, 1, -1 (leave rotation as-is)'), + ), + MenuItemButton( + onPressed: () async { + widget.controller.setCameraPosition(0.0, 0.0, 0.0); + widget.controller.setCameraRotation( + v.Quaternion.axisAngle(v.Vector3(0, 0.0, 1.0), 0.0)); + }, + child: const Text('Move to 0,0,0, facing towards 0,0,-1'), + ), + MenuItemButton( + onPressed: () { + widget.controller.setCameraRotation( + v.Quaternion.axisAngle(v.Vector3(0, 1, 0), pi / 4)); + }, + child: const Text("Rotate camera 45 degrees around y axis"), + ), + MenuItemButton( + onPressed: () { + ExampleWidgetState.frustumCulling = + !ExampleWidgetState.frustumCulling; + widget.controller + .setViewFrustumCulling(ExampleWidgetState.frustumCulling); + }, + child: Text( + "${ExampleWidgetState.frustumCulling ? "Disable" : "Enable"} frustum culling"), + ), + MenuItemButton( + closeOnActivate: false, + onPressed: () async { + var projMatrix = + await widget.controller.getCameraProjectionMatrix(); + await showDialog( + context: context, + builder: (ctx) { + return Center( + child: Container( + height: 100, + width: 300, + color: Colors.white, + child: Text(projMatrix.storage + .map((v) => v.toStringAsFixed(2)) + .join(",")))); + }); + }, + child: const Text("Get projection matrix")), + SubmenuButton( + menuChildren: ManipulatorMode.values.map((mm) { + return MenuItemButton( + onPressed: () { + widget.controller.setCameraManipulatorOptions( + mode: mm, + orbitSpeedX: ExampleWidgetState.orbitSpeedX, + orbitSpeedY: ExampleWidgetState.orbitSpeedY, + zoomSpeed: ExampleWidgetState.zoomSpeed); + }, + child: Text( + mm.name, + style: TextStyle( + // fontWeight: ExampleWidgetState.cameraManipulatorMode == mm + // ? FontWeight.bold + // : FontWeight.normal + ), + ), + ); + }).toList(), + child: const Text("Manipulator mode")), + SubmenuButton( + menuChildren: [0.01, 0.1, 1.0, 10.0, 100.0].map((speed) { + return MenuItemButton( + onPressed: () { + ExampleWidgetState.zoomSpeed = speed; + widget.controller.setCameraManipulatorOptions( + orbitSpeedX: ExampleWidgetState.orbitSpeedX, + orbitSpeedY: ExampleWidgetState.orbitSpeedY, + zoomSpeed: ExampleWidgetState.zoomSpeed); + }, + child: Text( + speed.toString(), + style: TextStyle( + fontWeight: + (speed - ExampleWidgetState.zoomSpeed).abs() < 0.0001 + ? FontWeight.bold + : FontWeight.normal), + ), + ); + }).toList(), + child: const Text("Zoom speed")), + SubmenuButton( + menuChildren: [0.001, 0.01, 0.1, 1.0].map((speed) { + return MenuItemButton( + onPressed: () { + ExampleWidgetState.orbitSpeedX = speed; + ExampleWidgetState.orbitSpeedY = speed; + widget.controller.setCameraManipulatorOptions( + orbitSpeedX: ExampleWidgetState.orbitSpeedX, + orbitSpeedY: ExampleWidgetState.orbitSpeedY, + zoomSpeed: ExampleWidgetState.zoomSpeed); + }, + child: Text( + speed.toString(), + style: TextStyle( + fontWeight: + (speed - ExampleWidgetState.orbitSpeedX).abs() < 0.0001 + ? FontWeight.bold + : FontWeight.normal), + ), + ); + }).toList(), + child: const Text("Orbit speed (X & Y)")) + ]; + } + + @override + Widget build(BuildContext context) { + if (_near == null || _far == null) { + return Container(); + } + return SubmenuButton( + controller: _menuController, + menuChildren: _cameraMenu(), + child: const Text("Camera"), + ); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/lib/menus/controller_menu.dart b/flutter_filament_federated/flutter_filament/example/lib/menus/controller_menu.dart new file mode 100644 index 00000000..a0599900 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/menus/controller_menu.dart @@ -0,0 +1,117 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +import 'package:flutter_filament/flutter_filament.dart'; + +class ControllerMenu extends StatefulWidget { + final FlutterFilamentPlugin? controller; + final void Function() onToggleViewport; + final void Function(FlutterFilamentPlugin controller) onControllerCreated; + final void Function() onControllerDestroyed; + final FocusNode sharedFocusNode; + + ControllerMenu( + {this.controller, + required this.onControllerCreated, + required this.onControllerDestroyed, + required this.sharedFocusNode, + required this.onToggleViewport}); + + @override + State createState() => _ControllerMenuState(); +} + +class _ControllerMenuState extends State { + FlutterFilamentPlugin? _flutterFilamentPlugin; + + void _createController({String? uberArchivePath}) async { + if (_flutterFilamentPlugin != null) { + throw Exception("Controller already exists"); + } + _flutterFilamentPlugin = + await FlutterFilamentPlugin.create(uberArchivePath: uberArchivePath); + widget.onControllerCreated(_flutterFilamentPlugin!); + } + + @override + void initState() { + super.initState(); + _flutterFilamentPlugin = widget.controller; + } + + @override + void didUpdateWidget(ControllerMenu oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.controller != _flutterFilamentPlugin) { + setState(() { + _flutterFilamentPlugin = widget.controller; + }); + } + } + + @override + Widget build(BuildContext context) { + var items = []; + if (_flutterFilamentPlugin == null) { + items.addAll([ + MenuItemButton( + child: + const Text("Create FlutterFilamentPlugin (default ubershader)"), + onPressed: () { + _createController(); + }, + ), + MenuItemButton( + child: const Text( + "Create FlutterFilamentPlugin (custom ubershader - lit opaque only)"), + onPressed: () { + _createController( + uberArchivePath: Platform.isWindows + ? "assets/lit_opaque_32.uberz" + : Platform.isMacOS + ? "assets/lit_opaque_43.uberz" + : Platform.isIOS + ? "assets/lit_opaque_43.uberz" + : "assets/lit_opaque_43_gles.uberz"); + }, + ) + ]); + } else { + items.addAll([ + MenuItemButton( + child: const Text("Destroy viewer"), + onPressed: () async { + await _flutterFilamentPlugin!.dispose(); + _flutterFilamentPlugin = null; + widget.onControllerDestroyed(); + setState(() {}); + }, + ) + ]); + } + return MenuAnchor( + childFocusNode: widget.sharedFocusNode, + menuChildren: items + + [ + TextButton( + child: const Text("Toggle viewport size"), + onPressed: widget.onToggleViewport, + ) + ], + builder: + (BuildContext context, MenuController controller, Widget? child) { + return TextButton( + onPressed: () { + if (controller.isOpen) { + controller.close(); + } else { + controller.open(); + } + }, + child: const Text("Controller / Viewer"), + ); + }); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/lib/menus/rendering_submenu.dart b/flutter_filament_federated/flutter_filament/example/lib/menus/rendering_submenu.dart new file mode 100644 index 00000000..d7f2502a --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/menus/rendering_submenu.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_filament/flutter_filament.dart'; +import 'package:flutter_filament_example/main.dart'; +import 'package:dart_filament/dart_filament.dart'; + +class RenderingSubmenu extends StatefulWidget { + final FlutterFilamentPlugin controller; + + const RenderingSubmenu({super.key, required this.controller}); + + @override + State createState() => _RenderingSubmenuState(); +} + +class _RenderingSubmenuState extends State { + @override + Widget build(BuildContext context) { + return SubmenuButton( + menuChildren: [ + MenuItemButton( + onPressed: () { + widget.controller.render(); + }, + child: const Text("Render single frame"), + ), + MenuItemButton( + onPressed: () { + ExampleWidgetState.rendering = !ExampleWidgetState.rendering; + widget.controller.setRendering(ExampleWidgetState.rendering); + }, + child: Text( + "Set continuous rendering to ${!ExampleWidgetState.rendering}"), + ), + MenuItemButton( + onPressed: () { + ExampleWidgetState.framerate = + ExampleWidgetState.framerate == 60 ? 30 : 60; + widget.controller.setFrameRate(ExampleWidgetState.framerate); + }, + child: Text( + "Toggle framerate (currently ${ExampleWidgetState.framerate}) "), + ), + MenuItemButton( + onPressed: () { + widget.controller.setToneMapping(ToneMapper.LINEAR); + }, + child: const Text("Set tone mapping to linear"), + ), + MenuItemButton( + onPressed: () { + ExampleWidgetState.postProcessing = + !ExampleWidgetState.postProcessing; + widget.controller + .setPostProcessing(ExampleWidgetState.postProcessing); + }, + child: Text( + "${ExampleWidgetState.postProcessing ? "Disable" : "Enable"} postprocessing"), + ), + MenuItemButton( + onPressed: () { + ExampleWidgetState.antiAliasingMsaa = + !ExampleWidgetState.antiAliasingMsaa; + widget.controller.setAntiAliasing( + ExampleWidgetState.antiAliasingMsaa, + ExampleWidgetState.antiAliasingFxaa, + ExampleWidgetState.antiAliasingTaa); + }, + child: Text( + "${ExampleWidgetState.antiAliasingMsaa ? "Disable" : "Enable"} MSAA antialiasing"), + ), + MenuItemButton( + onPressed: () { + ExampleWidgetState.antiAliasingFxaa = + !ExampleWidgetState.antiAliasingFxaa; + widget.controller.setAntiAliasing( + ExampleWidgetState.antiAliasingMsaa, + ExampleWidgetState.antiAliasingFxaa, + ExampleWidgetState.antiAliasingTaa); + }, + child: Text( + "${ExampleWidgetState.antiAliasingFxaa ? "Disable" : "Enable"} FXAA antialiasing"), + ), + MenuItemButton( + onPressed: () { + ExampleWidgetState.recording = !ExampleWidgetState.recording; + widget.controller.setRecording(ExampleWidgetState.recording); + }, + child: Text( + "Turn recording ${ExampleWidgetState.recording ? "OFF" : "ON"}) "), + ), + MenuItemButton( + onPressed: () async { + await widget.controller + .addLight(2, 6000, 100000, 0, 0, 0, 0, 1, 0, false); + }, + child: Text("Add light"), + ), + ], + child: const Text("Rendering"), + ); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/lib/menus/scene_menu.dart b/flutter_filament_federated/flutter_filament/example/lib/menus/scene_menu.dart new file mode 100644 index 00000000..d8d423da --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/menus/scene_menu.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_filament/flutter_filament.dart'; +import 'package:flutter_filament_example/menus/asset_submenu.dart'; +import 'package:flutter_filament_example/menus/camera_submenu.dart'; +import 'package:flutter_filament_example/menus/rendering_submenu.dart'; + +class SceneMenu extends StatefulWidget { + final FlutterFilamentPlugin? controller; + final FocusNode sharedFocusNode; + + const SceneMenu( + {super.key, required this.controller, required this.sharedFocusNode}); + + @override + State createState() { + return _SceneMenuState(); + } +} + +class _SceneMenuState extends State { + @override + void didUpdateWidget(SceneMenu oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.controller != null && + (widget.controller != oldWidget.controller)) { + setState(() {}); + } + } + + @override + Widget build(BuildContext context) { + return MenuAnchor( + onClose: () {}, + childFocusNode: widget.sharedFocusNode, + menuChildren: widget.controller == null + ? [] + : [ + RenderingSubmenu( + controller: widget.controller!, + ), + AssetSubmenu(controller: widget.controller!), + CameraSubmenu( + controller: widget.controller!, + ), + ], + builder: + (BuildContext context, MenuController controller, Widget? child) { + return TextButton( + onPressed: () { + if (controller.isOpen) { + controller.close(); + } else { + controller.open(); + } + }, + child: const Text("Scene"), + ); + }, + ); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/lib/picker_result_widget.dart b/flutter_filament_federated/flutter_filament/example/lib/picker_result_widget.dart new file mode 100644 index 00000000..424f889f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/lib/picker_result_widget.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_filament/flutter_filament.dart'; +import 'package:dart_filament/dart_filament.dart'; + +class PickerResultWidget extends StatelessWidget { + final FilamentViewer controller; + + const PickerResultWidget({required this.controller, super.key}); + + @override + Widget build(BuildContext context) { + return StreamBuilder( + stream: controller.pickResult.map((result) { + return controller.getNameForEntity(result.entity); + }), + builder: (ctx, snapshot) => snapshot.data == null + ? Container() + : Text(snapshot.data!, + style: const TextStyle(color: Colors.green, fontSize: 24))); + } +} diff --git a/flutter_filament_federated/flutter_filament/example/linux/.gitignore b/flutter_filament_federated/flutter_filament/example/linux/.gitignore new file mode 100644 index 00000000..d3896c98 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/flutter_filament_federated/flutter_filament/example/linux/CMakeLists.txt b/flutter_filament_federated/flutter_filament/example/linux/CMakeLists.txt new file mode 100644 index 00000000..9465b20e --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/CMakeLists.txt @@ -0,0 +1,141 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "flutter_filament_example") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "app.polyvox.flutter_filament") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror -Wno-unused-function -Wno-unused-variable) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + +include_directories(../../ios/include) + + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/flutter_filament_federated/flutter_filament/example/linux/flutter/CMakeLists.txt b/flutter_filament_federated/flutter_filament/example/linux/flutter/CMakeLists.txt new file mode 100644 index 00000000..d5bd0164 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugin_registrant.cc b/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 00000000..98d022b4 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) flutter_filament_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterFilamentPlugin"); + flutter_filament_plugin_register_with_registrar(flutter_filament_registrar); +} diff --git a/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugin_registrant.h b/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 00000000..e0f0a47b --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugins.cmake b/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 00000000..75876d76 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + flutter_filament +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/flutter_filament_federated/flutter_filament/example/linux/main.cc b/flutter_filament_federated/flutter_filament/example/linux/main.cc new file mode 100644 index 00000000..e7c5c543 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/flutter_filament_federated/flutter_filament/example/linux/my_application.cc b/flutter_filament_federated/flutter_filament/example/linux/my_application.cc new file mode 100644 index 00000000..aafe4dd9 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "flutter_filament_example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "flutter_filament_example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/flutter_filament_federated/flutter_filament/example/linux/my_application.h b/flutter_filament_federated/flutter_filament/example/linux/my_application.h new file mode 100644 index 00000000..72271d5e --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/flutter_filament_federated/flutter_filament/example/macos/.gitignore b/flutter_filament_federated/flutter_filament/example/macos/.gitignore new file mode 100644 index 00000000..746adbb6 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/flutter_filament_federated/flutter_filament/example/macos/Flutter/Flutter-Debug.xcconfig b/flutter_filament_federated/flutter_filament/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 00000000..4b81f9b2 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/flutter_filament_federated/flutter_filament/example/macos/Flutter/Flutter-Release.xcconfig b/flutter_filament_federated/flutter_filament/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 00000000..5caa9d15 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/flutter_filament_federated/flutter_filament/example/macos/Flutter/GeneratedPluginRegistrant.swift b/flutter_filament_federated/flutter_filament/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 00000000..bb5362df --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import flutter_filament +import path_provider_foundation + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + SwiftFlutterFilamentPlugin.register(with: registry.registrar(forPlugin: "SwiftFlutterFilamentPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) +} diff --git a/flutter_filament_federated/flutter_filament/example/macos/Podfile b/flutter_filament_federated/flutter_filament/example/macos/Podfile new file mode 100644 index 00000000..90de47d4 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Podfile @@ -0,0 +1,43 @@ +platform :osx, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/flutter_filament_federated/flutter_filament/example/macos/Podfile.lock b/flutter_filament_federated/flutter_filament/example/macos/Podfile.lock new file mode 100644 index 00000000..88ecc417 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - flutter_filament (0.0.1): + - FlutterMacOS + - FlutterMacOS (1.0.0) + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - flutter_filament (from `Flutter/ephemeral/.symlinks/plugins/flutter_filament/macos`) + - FlutterMacOS (from `Flutter/ephemeral`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) + +EXTERNAL SOURCES: + flutter_filament: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_filament/macos + FlutterMacOS: + :path: Flutter/ephemeral + path_provider_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin + +SPEC CHECKSUMS: + flutter_filament: b56021d3cce556b76bbc471803da16f3a866ce64 + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c + +PODFILE CHECKSUM: 1888651be91a8ad58692c1add9ce24279fd4e950 + +COCOAPODS: 1.15.2 diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/project.pbxproj b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..6eba66ee --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,803 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 73983334E7E3D03A0E12661E /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8E0CF9C3C7800C07C9845FC /* Pods_RunnerTests.framework */; }; + C522DC3C60A9E9D8A157D709 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A43AAD1E638EA0D1719DBA3 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 07D325EB165BDBD20CA1B50D /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 5A43AAD1E638EA0D1719DBA3 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 750CFF70D61D26C0BECD5590 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 8A325254C21887E4CBDE8294 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + C29827A08E11D88646BFBE93 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + D8E0CF9C3C7800C07C9845FC /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DEA954DCA916B6FC51B8D22B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + F0328BD31CA3A8DD85456972 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 73983334E7E3D03A0E12661E /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C522DC3C60A9E9D8A157D709 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + A1BEA79574E5550EED38B897 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + A1BEA79574E5550EED38B897 /* Pods */ = { + isa = PBXGroup; + children = ( + C29827A08E11D88646BFBE93 /* Pods-Runner.debug.xcconfig */, + F0328BD31CA3A8DD85456972 /* Pods-Runner.release.xcconfig */, + 8A325254C21887E4CBDE8294 /* Pods-Runner.profile.xcconfig */, + DEA954DCA916B6FC51B8D22B /* Pods-RunnerTests.debug.xcconfig */, + 750CFF70D61D26C0BECD5590 /* Pods-RunnerTests.release.xcconfig */, + 07D325EB165BDBD20CA1B50D /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5A43AAD1E638EA0D1719DBA3 /* Pods_Runner.framework */, + D8E0CF9C3C7800C07C9845FC /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 210FEE2628F42B7BDFED20C4 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + B67C6085C13299F59758F7CC /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + D8E4D2DE64C21B53086793F8 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 210FEE2628F42B7BDFED20C4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + B67C6085C13299F59758F7CC /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + D8E4D2DE64C21B53086793F8 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DEA954DCA916B6FC51B8D22B /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = app.polyvox.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 750CFF70D61D26C0BECD5590 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = app.polyvox.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 07D325EB165BDBD20CA1B50D /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = app.polyvox.example.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..15368ecc --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/AppDelegate.swift b/flutter_filament_federated/flutter_filament/example/macos/Runner/AppDelegate.swift new file mode 100644 index 00000000..8e02df28 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..a2ec33f1 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 00000000..82b6f9d9 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 00000000..13b35eba Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 00000000..0a3f5fa4 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 00000000..bdb57226 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 00000000..f083318e Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 00000000..326c0e72 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 00000000..2f1632cf Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Base.lproj/MainMenu.xib b/flutter_filament_federated/flutter_filament/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 00000000..80e867a4 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/AppInfo.xcconfig b/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 00000000..322ba235 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = app.polyvox.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2024 app.polyvox. All rights reserved. diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Debug.xcconfig b/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 00000000..36b0fd94 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Release.xcconfig b/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 00000000..dff4f495 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Warnings.xcconfig b/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 00000000..42bcbf47 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/DebugProfile.entitlements b/flutter_filament_federated/flutter_filament/example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 00000000..dddb8a30 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Info.plist b/flutter_filament_federated/flutter_filament/example/macos/Runner/Info.plist new file mode 100644 index 00000000..4789daa6 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/MainFlutterWindow.swift b/flutter_filament_federated/flutter_filament/example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 00000000..3cc05eb2 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/flutter_filament_federated/flutter_filament/example/macos/Runner/Release.entitlements b/flutter_filament_federated/flutter_filament/example/macos/Runner/Release.entitlements new file mode 100644 index 00000000..852fa1a4 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/flutter_filament_federated/flutter_filament/example/macos/RunnerTests/RunnerTests.swift b/flutter_filament_federated/flutter_filament/example/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..61f3bd1f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/flutter_filament_federated/flutter_filament/example/pubspec.lock b/flutter_filament_federated/flutter_filament/example/pubspec.lock new file mode 100644 index 00000000..746dafe7 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/pubspec.lock @@ -0,0 +1,566 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + animation_tools_dart: + dependency: transitive + description: + name: animation_tools_dart + sha256: c4bc4096d43227b573345a3ea3cb26c3af47a70af31cd7d7d3a5b7c99e33d615 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + archive: + dependency: transitive + description: + name: archive + sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265 + url: "https://pub.dev" + source: hosted + version: "3.5.1" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + crypto: + dependency: "direct dev" + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + dart_filament: + dependency: transitive + description: + path: "../../../dart_filament" + relative: true + source: path + version: "0.5.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_filament: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "0.6.0" + flutter_filament_platform_interface: + dependency: transitive + description: + path: "../../flutter_filament_platform_interface" + relative: true + source: path + version: "2.0.5" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + image: + dependency: transitive + description: + name: image + sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + url: "https://pub.dev" + source: hosted + version: "3.3.0" + image_compare: + dependency: "direct dev" + description: + name: image_compare + sha256: "774e9ef1558ca328191fe9690e8e024159a3a2db6ea4ef6b65bea0faa3631b74" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" + source: hosted + version: "1.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "25dfcaf170a0190f47ca6355bdd4552cb8924b430512ff0cafb8db9bd41fe33b" + url: "https://pub.dev" + source: hosted + version: "1.14.0" + native_assets_cli: + dependency: "direct dev" + description: + name: native_assets_cli + sha256: "9c1b67ccf85ec9282f34e5348ae78dcb7da2c7dc965c0265306477d977853a0d" + url: "https://pub.dev" + source: hosted + version: "0.5.4" + native_toolchain_c: + dependency: "direct dev" + description: + name: native_toolchain_c + sha256: "1b1b86f47570378d0003f0d949fbb03b637ec9d2dcbcf698a16f7cbffb3a945c" + url: "https://pub.dev" + source: hosted + version: "0.4.1" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + url: "https://pub.dev" + source: hosted + version: "2.1.3" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d + url: "https://pub.dev" + source: hosted + version: "2.2.4" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" + url: "https://pub.dev" + source: hosted + version: "11.3.1" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5" + url: "https://pub.dev" + source: hosted + version: "12.0.6" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662 + url: "https://pub.dev" + source: hosted + version: "9.4.4" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d" + url: "https://pub.dev" + source: hosted + version: "0.1.1" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20" + url: "https://pub.dev" + source: hosted + version: "4.2.1" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + url: "https://pub.dev" + source: hosted + version: "3.1.4" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + process: + dependency: transitive + description: + name: process + sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + url: "https://pub.dev" + source: hosted + version: "5.0.2" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "2419f20b0c8677b2d67c8ac4d1ac7372d862dc6c460cdbb052b40155408cd794" + url: "https://pub.dev" + source: hosted + version: "0.7.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "7475cb4dd713d57b6f7464c0e13f06da0d535d8b2067e188962a59bac2cf280b" + url: "https://pub.dev" + source: hosted + version: "14.2.2" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + win32: + dependency: transitive + description: + name: win32 + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + url: "https://pub.dev" + source: hosted + version: "5.5.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/flutter_filament_federated/flutter_filament/example/pubspec.yaml b/flutter_filament_federated/flutter_filament/example/pubspec.yaml new file mode 100644 index 00000000..a1586338 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/pubspec.yaml @@ -0,0 +1,51 @@ +name: flutter_filament_example +description: Demonstrates how to use the flutter_filament plugin. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +environment: + sdk: ">=3.0.0 <4.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + path_provider: + flutter_filament: + path: ../ + permission_handler: + cupertino_icons: ^1.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + flutter_lints: ^1.0.0 + crypto: + image_compare: ^1.1.2 + native_assets_cli: ^0.5.0 + native_toolchain_c: ^0.4.0 + + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + uses-material-design: true + assets: + - assets/ + - assets/shapes/ + - assets/default_env/ + - assets/BusterDrone/ + - assets/BusterDrone/textures/ + - assets/FlightHelmet/ + \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/example/regenerate_goldens.sh b/flutter_filament_federated/flutter_filament/example/regenerate_goldens.sh new file mode 100644 index 00000000..b1f06b4f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/regenerate_goldens.sh @@ -0,0 +1,8 @@ +#!/bin/bash +device=$1 +if [ -z "$device" ]; then + echo "Usage: $0 " + exit 1; +fi +rm -f integration_test/goldens/{ios,macos,windows,android}/*.png +flutter drive --driver=test_driver/integration_test_update_goldens.dart -d $1 --target=integration_test/plugin_integration_test.dart diff --git a/flutter_filament_federated/flutter_filament/example/test/widget_test.dart b/flutter_filament_federated/flutter_filament/example/test/widget_test.dart new file mode 100644 index 00000000..78b385b9 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:flutter_filament_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/flutter_filament_federated/flutter_filament/example/test_driver/integration_test.dart b/flutter_filament_federated/flutter_filament/example/test_driver/integration_test.dart new file mode 100644 index 00000000..752a3842 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/test_driver/integration_test.dart @@ -0,0 +1,58 @@ +import 'dart:io'; + +import 'package:integration_test/integration_test_driver_extended.dart'; +import 'package:image_compare/image_compare.dart'; + +Future main() async { + await integrationDriver( + onScreenshot: ( + String screenshotName, + List screenshotBytes, [ + Map? args, + ]) async { + final dir = screenshotName.split("/")[0]; + final name = screenshotName.split("/")[1]; + final File golden = await File('integration_test/goldens/$dir/$name.png'); + + if (!golden.existsSync()) { + throw Exception( + "Golden image ${golden.path} doesn't exist yet. Make sure you have run integraton_test_update_goldens.dart first"); + } + + var result = await compareImages( + src1: screenshotBytes, + src2: golden.readAsBytesSync(), + algorithm: ChiSquareDistanceHistogram()); + + print(result); + + // TODO - it would be preferable to use Flutter's GoldenFileComparator here, e.g. + // + // ```var comparator = LocalFileComparator(testImage.uri); + // comparator.compare(imageBytes, golden) + // comparator.getFailureFile(failure, golden, basedir) + // var result = await comparator.compare( + // Uint8List.fromList(screenshotBytes), golden.uri); + // if (!result.passed) { + // for (var key in result.diffs!.keys) { + // var byteData = await result.diffs![key]!.toByteData(); + // File('integration_test/goldens/$dir/diffs/$name.png') + // .writeAsBytesSync( + // byteData!.buffer.asUint8List(byteData!.offsetInBytes)); + // } + // return false; + // }``` + // but this is only available via a Flutter shell which is currently unavailable (this script is run as a plain Dart file I guess). + // let's revisit if/when this changes + // see https://github.com/flutter/flutter/issues/51890 and https://github.com/flutter/flutter/issues/103222 + + if (result > 0.005) { + File('integration_test/goldens/$dir/diffs/$name.png') + .writeAsBytesSync(screenshotBytes); + return false; + } + + return true; + }, + ); +} diff --git a/flutter_filament_federated/flutter_filament/example/test_driver/integration_test_update_goldens.dart b/flutter_filament_federated/flutter_filament/example/test_driver/integration_test_update_goldens.dart new file mode 100644 index 00000000..e32febe2 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/test_driver/integration_test_update_goldens.dart @@ -0,0 +1,22 @@ +import 'dart:io'; +import 'package:crypto/crypto.dart'; +import 'package:integration_test/integration_test_driver_extended.dart'; + +Future main() async { + await integrationDriver( + onScreenshot: ( + String screenshotName, + List screenshotBytes, [ + Map? args, + ]) async { + final dir = screenshotName.split("/")[0]; + final name = screenshotName.split("/")[1]; + final File image = await File('integration_test/goldens/$dir/$name.png') + .create(recursive: true); + + image.writeAsBytesSync(screenshotBytes); + + return true; + }, + ); +} diff --git a/flutter_filament_federated/flutter_filament/example/web/favicon.png b/flutter_filament_federated/flutter_filament/example/web/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/web/favicon.png differ diff --git a/flutter_filament_federated/flutter_filament/example/web/icons/Icon-192.png b/flutter_filament_federated/flutter_filament/example/web/icons/Icon-192.png new file mode 100644 index 00000000..b749bfef Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/web/icons/Icon-192.png differ diff --git a/flutter_filament_federated/flutter_filament/example/web/icons/Icon-512.png b/flutter_filament_federated/flutter_filament/example/web/icons/Icon-512.png new file mode 100644 index 00000000..88cfd48d Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/web/icons/Icon-512.png differ diff --git a/flutter_filament_federated/flutter_filament/example/web/icons/Icon-maskable-192.png b/flutter_filament_federated/flutter_filament/example/web/icons/Icon-maskable-192.png new file mode 100644 index 00000000..eb9b4d76 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/web/icons/Icon-maskable-192.png differ diff --git a/flutter_filament_federated/flutter_filament/example/web/icons/Icon-maskable-512.png b/flutter_filament_federated/flutter_filament/example/web/icons/Icon-maskable-512.png new file mode 100644 index 00000000..d69c5669 Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/web/icons/Icon-maskable-512.png differ diff --git a/flutter_filament_federated/flutter_filament/example/web/index.html b/flutter_filament_federated/flutter_filament/example/web/index.html new file mode 100644 index 00000000..bd7bcbe9 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/web/index.html @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + flutter_filament_example + + + + + + + +
+
+ + + + diff --git a/flutter_filament_federated/flutter_filament/example/web/manifest.json b/flutter_filament_federated/flutter_filament/example/web/manifest.json new file mode 100644 index 00000000..48eb01be --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "flutter_filament_example", + "short_name": "flutter_filament_example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "Demonstrates how to use the flutter_filament plugin.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/flutter_filament_federated/flutter_filament/example/windows/.gitignore b/flutter_filament_federated/flutter_filament/example/windows/.gitignore new file mode 100644 index 00000000..d492d0d9 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/flutter_filament_federated/flutter_filament/example/windows/CMakeLists.txt b/flutter_filament_federated/flutter_filament/example/windows/CMakeLists.txt new file mode 100644 index 00000000..99c90863 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.14) +project(flutter_filament_example LANGUAGES CXX) + +set(BINARY_NAME "flutter_filament_example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W0 /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/flutter_filament_federated/flutter_filament/example/windows/flutter/CMakeLists.txt b/flutter_filament_federated/flutter_filament/example/windows/flutter/CMakeLists.txt new file mode 100644 index 00000000..4f2af69b --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,108 @@ +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugin_registrant.cc b/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 00000000..754e1cb7 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,17 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + FlutterFilamentPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterFilamentPluginCApi")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); +} diff --git a/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugin_registrant.h b/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 00000000..dc139d85 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugins.cmake b/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugins.cmake new file mode 100644 index 00000000..e1dea286 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,25 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + flutter_filament + permission_handler_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/CMakeLists.txt b/flutter_filament_federated/flutter_filament/example/windows/runner/CMakeLists.txt new file mode 100644 index 00000000..de2d8916 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/Runner.rc b/flutter_filament_federated/flutter_filament/example/windows/runner/Runner.rc new file mode 100644 index 00000000..b85a561d --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "app.polyvox" "\0" + VALUE "FileDescription", "flutter_filament_example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "flutter_filament_example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 app.polyvox. All rights reserved." "\0" + VALUE "OriginalFilename", "flutter_filament_example.exe" "\0" + VALUE "ProductName", "flutter_filament_example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/flutter_window.cpp b/flutter_filament_federated/flutter_filament/example/windows/runner/flutter_window.cpp new file mode 100644 index 00000000..b43b9095 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/flutter_window.h b/flutter_filament_federated/flutter_filament/example/windows/runner/flutter_window.h new file mode 100644 index 00000000..6da0652f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/main.cpp b/flutter_filament_federated/flutter_filament/example/windows/runner/main.cpp new file mode 100644 index 00000000..9a6e00b8 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"flutter_filament_example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/resource.h b/flutter_filament_federated/flutter_filament/example/windows/runner/resource.h new file mode 100644 index 00000000..66a65d1e --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/resources/app_icon.ico b/flutter_filament_federated/flutter_filament/example/windows/runner/resources/app_icon.ico new file mode 100644 index 00000000..c04e20ca Binary files /dev/null and b/flutter_filament_federated/flutter_filament/example/windows/runner/resources/app_icon.ico differ diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/runner.exe.manifest b/flutter_filament_federated/flutter_filament/example/windows/runner/runner.exe.manifest new file mode 100644 index 00000000..c977c4a4 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/utils.cpp b/flutter_filament_federated/flutter_filament/example/windows/runner/utils.cpp new file mode 100644 index 00000000..d19bdbbc --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/utils.h b/flutter_filament_federated/flutter_filament/example/windows/runner/utils.h new file mode 100644 index 00000000..3879d547 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/win32_window.cpp b/flutter_filament_federated/flutter_filament/example/windows/runner/win32_window.cpp new file mode 100644 index 00000000..c10f08dc --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/flutter_filament_federated/flutter_filament/example/windows/runner/win32_window.h b/flutter_filament_federated/flutter_filament/example/windows/runner/win32_window.h new file mode 100644 index 00000000..17ba4311 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/example/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/flutter_filament_federated/flutter_filament/ios/.gitignore b/flutter_filament_federated/flutter_filament/ios/.gitignore new file mode 100644 index 00000000..0c885071 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/ios/.gitignore @@ -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 \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/ios/Assets/.gitkeep b/flutter_filament_federated/flutter_filament/ios/Assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/flutter_filament_federated/flutter_filament/ios/Classes/FlutterFilamentTexture.swift b/flutter_filament_federated/flutter_filament/ios/Classes/FlutterFilamentTexture.swift new file mode 100644 index 00000000..637b8ace --- /dev/null +++ b/flutter_filament_federated/flutter_filament/ios/Classes/FlutterFilamentTexture.swift @@ -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? { + 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 + } + +} diff --git a/flutter_filament_federated/flutter_filament/ios/Classes/ResourceBuffer.c b/flutter_filament_federated/flutter_filament/ios/Classes/ResourceBuffer.c new file mode 100644 index 00000000..f2ec5e00 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/ios/Classes/ResourceBuffer.c @@ -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; +} diff --git a/flutter_filament_federated/flutter_filament/ios/Classes/SwiftFlutterFilamentPlugin.swift b/flutter_filament_federated/flutter_filament/ios/Classes/SwiftFlutterFilamentPlugin.swift new file mode 100644 index 00000000..495bc76f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/ios/Classes/SwiftFlutterFilamentPlugin.swift @@ -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?, UnsafeMutableRawPointer?) -> ResourceBuffer = { uri, resourcesPtr in + + let instance:SwiftFlutterFilamentPlugin = Unmanaged.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.fromOpaque(resourcesPtr!).takeUnretainedValue() + instance.resources.removeObject(forKey:rbuf.id) + } + + var markTextureFrameAvailable : @convention(c) (UnsafeMutableRawPointer?) -> () = { instancePtr in + let instance:SwiftFlutterFilamentPlugin = Unmanaged.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) + } + } +} + diff --git a/flutter_filament_federated/flutter_filament/ios/flutter_filament.podspec b/flutter_filament_federated/flutter_filament/ios/flutter_filament.podspec new file mode 100644 index 00000000..b2d2b2b8 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/ios/flutter_filament.podspec @@ -0,0 +1,34 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint flutter_filament.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'flutter_filament' + 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/SwiftFlutterFilamentPlugin-Bridging-Header.h', 'include/ResourceBuffer.h' + s.public_header_files = 'include/SwiftFlutterFilamentPlugin-Bridging-Header.h', 'include/ResourceBuffer.h' + 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 diff --git a/flutter_filament_federated/flutter_filament/ios/include/ResourceBuffer.h b/flutter_filament_federated/flutter_filament/ios/include/ResourceBuffer.h new file mode 120000 index 00000000..5375d4ad --- /dev/null +++ b/flutter_filament_federated/flutter_filament/ios/include/ResourceBuffer.h @@ -0,0 +1 @@ +../../../dart_filament/native/include/ResourceBuffer.h \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/ios/include/SwiftFlutterFilamentPlugin-Bridging-Header.h b/flutter_filament_federated/flutter_filament/ios/include/SwiftFlutterFilamentPlugin-Bridging-Header.h new file mode 100644 index 00000000..c3548735 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/ios/include/SwiftFlutterFilamentPlugin-Bridging-Header.h @@ -0,0 +1,6 @@ +#ifndef SwiftFlutterFilamentPlugin_Bridging_Header_h +#define SwiftFlutterFilamentPlugin_Bridging_Header_h + +#include "ResourceBuffer.h" + +#endif diff --git a/flutter_filament_federated/flutter_filament/lib/filament/flutter_filament.g.dart b/flutter_filament_federated/flutter_filament/lib/filament/flutter_filament.g.dart new file mode 100644 index 00000000..61d60308 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/flutter_filament.g.dart @@ -0,0 +1,1711 @@ +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +// ignore_for_file: type=lint +import 'dart:ffi' as ffi; + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>( + symbol: 'create_filament_viewer', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer create_filament_viewer( + ffi.Pointer context, + ffi.Pointer loader, + ffi.Pointer platform, + ffi.Pointer uberArchivePath, +); + +@ffi.Native)>( + symbol: 'destroy_filament_viewer', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void destroy_filament_viewer( + ffi.Pointer viewer, +); + +@ffi.Native Function(ffi.Pointer)>( + symbol: 'get_scene_manager', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer get_scene_manager( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.IntPtr, ffi.Uint32, ffi.Uint32)>( + symbol: 'create_render_target', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void create_render_target( + ffi.Pointer viewer, + int texture, + int width, + int height, +); + +@ffi.Native)>( + symbol: 'clear_background_image', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void clear_background_image( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer, ffi.Bool)>( + symbol: 'set_background_image', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_background_image( + ffi.Pointer viewer, + ffi.Pointer path, + bool fillHeight, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>( + symbol: 'set_background_image_position', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_background_image_position( + ffi.Pointer viewer, + double x, + double y, + bool clamp, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, ffi.Float)>( + symbol: 'set_background_color', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_background_color( + ffi.Pointer viewer, + double r, + double g, + double b, + double a, +); + +@ffi.Native, ffi.Int)>( + symbol: 'set_tone_mapping', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_tone_mapping( + ffi.Pointer viewer, + int toneMapping, +); + +@ffi.Native, ffi.Float)>( + symbol: 'set_bloom', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_bloom( + ffi.Pointer viewer, + double strength, +); + +@ffi.Native, ffi.Pointer)>( + symbol: 'load_skybox', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void load_skybox( + ffi.Pointer viewer, + ffi.Pointer skyboxPath, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer, ffi.Float)>( + symbol: 'load_ibl', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void load_ibl( + ffi.Pointer viewer, + ffi.Pointer iblPath, + double intensity, +); + +@ffi.Native, ffi.Pointer)>( + symbol: 'rotate_ibl', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void rotate_ibl( + ffi.Pointer viewer, + ffi.Pointer rotationMatrix, +); + +@ffi.Native)>( + symbol: 'remove_skybox', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_skybox( + ffi.Pointer viewer, +); + +@ffi.Native)>( + symbol: 'remove_ibl', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_ibl( + ffi.Pointer viewer, +); + +@ffi.Native< + EntityId Function( + ffi.Pointer, + ffi.Uint8, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Bool)>( + symbol: 'add_light', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int add_light( + ffi.Pointer viewer, + int type, + double colour, + double intensity, + double posX, + double posY, + double posZ, + double dirX, + double dirY, + double dirZ, + bool shadows, +); + +@ffi.Native, EntityId)>( + symbol: 'remove_light', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_light( + ffi.Pointer viewer, + int entityId, +); + +@ffi.Native)>( + symbol: 'clear_lights', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void clear_lights( + ffi.Pointer viewer, +); + +@ffi.Native< + EntityId Function( + ffi.Pointer, ffi.Pointer, ffi.Int)>( + symbol: 'load_glb', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int load_glb( + ffi.Pointer sceneManager, + ffi.Pointer assetPath, + int numInstances, +); + +@ffi.Native< + EntityId Function( + ffi.Pointer, ffi.Pointer, ffi.Size)>( + symbol: 'load_glb_from_buffer', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int load_glb_from_buffer( + ffi.Pointer sceneManager, + ffi.Pointer data, + int length, +); + +@ffi.Native< + EntityId Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>( + symbol: 'load_gltf', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int load_gltf( + ffi.Pointer sceneManager, + ffi.Pointer assetPath, + ffi.Pointer relativePath, +); + +@ffi.Native, EntityId)>( + symbol: 'create_instance', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int create_instance( + ffi.Pointer sceneManager, + int id, +); + +@ffi.Native, EntityId)>( + symbol: 'get_instance_count', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int get_instance_count( + ffi.Pointer sceneManager, + int entityId, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, EntityId, ffi.Pointer)>( + symbol: 'get_instances', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_instances( + ffi.Pointer sceneManager, + int entityId, + ffi.Pointer out, +); + +@ffi.Native)>( + symbol: 'set_main_camera', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_main_camera( + ffi.Pointer viewer, +); + +@ffi.Native)>( + symbol: 'get_main_camera', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int get_main_camera( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Bool Function( + ffi.Pointer, EntityId, ffi.Pointer)>( + symbol: 'set_camera', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external bool set_camera( + ffi.Pointer viewer, + int asset, + ffi.Pointer nodeName, +); + +@ffi.Native, ffi.Bool)>( + symbol: 'set_view_frustum_culling', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_view_frustum_culling( + ffi.Pointer viewer, + bool enabled, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Uint64, + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer buf, ffi.Size size, + ffi.Pointer data)>>, + ffi.Pointer)>( + symbol: 'render', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void render( + ffi.Pointer viewer, + int frameTimeInNanos, + ffi.Pointer pixelBuffer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer buf, ffi.Size size, + ffi.Pointer data)>> + callback, + ffi.Pointer data, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Uint32, ffi.Uint32)>( + symbol: 'create_swap_chain', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void create_swap_chain( + ffi.Pointer viewer, + ffi.Pointer window, + int width, + int height, +); + +@ffi.Native)>( + symbol: 'destroy_swap_chain', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void destroy_swap_chain( + ffi.Pointer viewer, +); + +@ffi.Native, ffi.Float)>( + symbol: 'set_frame_interval', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_frame_interval( + ffi.Pointer viewer, + double interval, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Uint32, ffi.Uint32, ffi.Float)>( + symbol: 'update_viewport_and_camera_projection', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void update_viewport_and_camera_projection( + ffi.Pointer viewer, + int width, + int height, + double scaleFactor, +); + +@ffi.Native)>( + symbol: 'scroll_begin', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void scroll_begin( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Float)>( + symbol: 'scroll_update', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void scroll_update( + ffi.Pointer viewer, + double x, + double y, + double z, +); + +@ffi.Native)>( + symbol: 'scroll_end', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void scroll_end( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>( + symbol: 'grab_begin', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void grab_begin( + ffi.Pointer viewer, + double x, + double y, + bool pan, +); + +@ffi.Native, ffi.Float, ffi.Float)>( + symbol: 'grab_update', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void grab_update( + ffi.Pointer viewer, + double x, + double y, +); + +@ffi.Native)>( + symbol: 'grab_end', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void grab_end( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer, ffi.Pointer, ffi.Int)>( + symbol: 'apply_weights', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void apply_weights( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer entityName, + ffi.Pointer weights, + int count, +); + +@ffi.Native< + ffi.Bool Function( + ffi.Pointer, EntityId, ffi.Pointer, ffi.Int)>( + symbol: 'set_morph_target_weights', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external bool set_morph_target_weights( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer morphData, + int numWeights, +); + +@ffi.Native< + ffi.Bool Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer, + ffi.Int, + ffi.Int, + ffi.Float)>( + symbol: 'set_morph_animation', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external bool set_morph_animation( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer morphData, + ffi.Pointer morphIndices, + int numMorphTargets, + int numFrames, + double frameLengthInMs, +); + +@ffi.Native, EntityId)>( + symbol: 'reset_to_rest_pose', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void reset_to_rest_pose( + ffi.Pointer sceneManager, + int asset, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Int, + ffi.Pointer, + ffi.Pointer>, + ffi.Int, + ffi.Float, + ffi.Bool)>( + symbol: 'add_bone_animation', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void add_bone_animation( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer frameData, + int numFrames, + ffi.Pointer boneName, + ffi.Pointer> meshNames, + int numMeshTargets, + double frameLengthInMs, + bool isModelSpace, +); + +@ffi.Native< + ffi.Bool Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>( + symbol: 'set_bone_transform', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external bool set_bone_transform( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer entityName, + ffi.Pointer transform, + ffi.Pointer boneName, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Int, ffi.Bool, + ffi.Bool, ffi.Bool, ffi.Float)>( + symbol: 'play_animation', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void play_animation( + ffi.Pointer sceneManager, + int asset, + int index, + bool loop, + bool reverse, + bool replaceActive, + double crossfade, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Int, ffi.Int)>( + symbol: 'set_animation_frame', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_animation_frame( + ffi.Pointer sceneManager, + int asset, + int animationIndex, + int animationFrame, +); + +@ffi.Native, EntityId, ffi.Int)>( + symbol: 'stop_animation', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void stop_animation( + ffi.Pointer sceneManager, + int asset, + int index, +); + +@ffi.Native, EntityId)>( + symbol: 'get_animation_count', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int get_animation_count( + ffi.Pointer sceneManager, + int asset, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, EntityId, ffi.Pointer, ffi.Int)>( + symbol: 'get_animation_name', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_animation_name( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer outPtr, + int index, +); + +@ffi.Native, EntityId, ffi.Int)>( + symbol: 'get_animation_duration', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external double get_animation_duration( + ffi.Pointer sceneManager, + int asset, + int index, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer, ffi.Pointer, ffi.Int)>( + symbol: 'get_morph_target_name', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_morph_target_name( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer meshName, + ffi.Pointer outPtr, + int index, +); + +@ffi.Native< + ffi.Int Function( + ffi.Pointer, EntityId, ffi.Pointer)>( + symbol: 'get_morph_target_name_count', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int get_morph_target_name_count( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer meshName, +); + +@ffi.Native, EntityId)>( + symbol: 'remove_entity', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_entity( + ffi.Pointer viewer, + int asset, +); + +@ffi.Native)>( + symbol: 'clear_entities', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void clear_entities( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Bool Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Int, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float)>( + symbol: 'set_material_color', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external bool set_material_color( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer meshName, + int materialIndex, + double r, + double g, + double b, + double a, +); + +@ffi.Native, EntityId)>( + symbol: 'transform_to_unit_cube', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void transform_to_unit_cube( + ffi.Pointer sceneManager, + int asset, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, ffi.Float, + ffi.Float, ffi.Bool)>( + symbol: 'queue_position_update', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void queue_position_update( + ffi.Pointer sceneManager, + int asset, + double x, + double y, + double z, + bool relative, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, ffi.Float, + ffi.Float, ffi.Float, ffi.Float, ffi.Bool)>( + symbol: 'queue_rotation_update', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void queue_rotation_update( + ffi.Pointer sceneManager, + int asset, + double rads, + double x, + double y, + double z, + double w, + bool relative, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, EntityId, ffi.Float, ffi.Float, ffi.Float)>( + symbol: 'set_position', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_position( + ffi.Pointer sceneManager, + int asset, + double x, + double y, + double z, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, ffi.Float, + ffi.Float, ffi.Float, ffi.Float)>( + symbol: 'set_rotation', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_rotation( + ffi.Pointer sceneManager, + int asset, + double rads, + double x, + double y, + double z, + double w, +); + +@ffi.Native, EntityId, ffi.Float)>( + symbol: 'set_scale', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_scale( + ffi.Pointer sceneManager, + int asset, + double scale, +); + +@ffi.Native, EntityId)>( + symbol: 'move_camera_to_asset', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void move_camera_to_asset( + ffi.Pointer viewer, + int asset, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Float)>( + symbol: 'set_camera_exposure', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_exposure( + ffi.Pointer viewer, + double aperture, + double shutterSpeed, + double sensitivity, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Float)>( + symbol: 'set_camera_position', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_position( + ffi.Pointer viewer, + double x, + double y, + double z, +); + +@ffi.Native)>( + symbol: 'get_camera_position', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_camera_position( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, ffi.Float)>( + symbol: 'set_camera_rotation', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_rotation( + ffi.Pointer viewer, + double w, + double x, + double y, + double z, +); + +@ffi.Native, ffi.Pointer)>( + symbol: 'set_camera_model_matrix', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_model_matrix( + ffi.Pointer viewer, + ffi.Pointer matrix, +); + +@ffi.Native Function(ffi.Pointer)>( + symbol: 'get_camera_model_matrix', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer get_camera_model_matrix( + ffi.Pointer viewer, +); + +@ffi.Native Function(ffi.Pointer)>( + symbol: 'get_camera_view_matrix', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer get_camera_view_matrix( + ffi.Pointer viewer, +); + +@ffi.Native Function(ffi.Pointer)>( + symbol: 'get_camera_projection_matrix', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer get_camera_projection_matrix( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Double, ffi.Double)>( + symbol: 'set_camera_projection_matrix', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_projection_matrix( + ffi.Pointer viewer, + ffi.Pointer matrix, + double near, + double far, +); + +@ffi.Native, ffi.Double, ffi.Double)>( + symbol: 'set_camera_culling', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_culling( + ffi.Pointer viewer, + double near, + double far, +); + +@ffi.Native)>( + symbol: 'get_camera_culling_near', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external double get_camera_culling_near( + ffi.Pointer viewer, +); + +@ffi.Native)>( + symbol: 'get_camera_culling_far', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external double get_camera_culling_far( + ffi.Pointer viewer, +); + +@ffi.Native Function(ffi.Pointer)>( + symbol: 'get_camera_culling_projection_matrix', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer get_camera_culling_projection_matrix( + ffi.Pointer viewer, +); + +@ffi.Native Function(ffi.Pointer)>( + symbol: 'get_camera_frustum', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer get_camera_frustum( + ffi.Pointer viewer, +); + +@ffi.Native, ffi.Float, ffi.Float)>( + symbol: 'set_camera_fov', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_fov( + ffi.Pointer viewer, + double fovInDegrees, + double aspect, +); + +@ffi.Native, ffi.Float)>( + symbol: 'set_camera_focal_length', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_focal_length( + ffi.Pointer viewer, + double focalLength, +); + +@ffi.Native, ffi.Float)>( + symbol: 'set_camera_focus_distance', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_focus_distance( + ffi.Pointer viewer, + double focusDistance, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, _ManipulatorMode, ffi.Double, + ffi.Double, ffi.Double)>( + symbol: 'set_camera_manipulator_options', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_manipulator_options( + ffi.Pointer viewer, + int mode, + double orbitSpeedX, + double orbitSpeedY, + double zoomSpeed, +); + +@ffi.Native< + ffi.Int Function( + ffi.Pointer, EntityId, ffi.Pointer)>( + symbol: 'hide_mesh', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int hide_mesh( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer meshName, +); + +@ffi.Native< + ffi.Int Function( + ffi.Pointer, EntityId, ffi.Pointer)>( + symbol: 'reveal_mesh', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int reveal_mesh( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer meshName, +); + +@ffi.Native, ffi.Bool)>( + symbol: 'set_post_processing', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_post_processing( + ffi.Pointer viewer, + bool enabled, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>( + symbol: 'set_antialiasing', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_antialiasing( + ffi.Pointer viewer, + bool msaa, + bool fxaa, + bool taa, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Int, + ffi.Int, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + EntityId entityId, ffi.Int x, ffi.Int y)>>)>( + symbol: 'pick', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void pick( + ffi.Pointer viewer, + int x, + int y, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y)>> + callback, +); + +@ffi.Native Function(ffi.Pointer, EntityId)>( + symbol: 'get_name_for_entity', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer get_name_for_entity( + ffi.Pointer sceneManager, + int entityId, +); + +@ffi.Native< + EntityId Function( + ffi.Pointer, EntityId, ffi.Pointer)>( + symbol: 'find_child_entity_by_name', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int find_child_entity_by_name( + ffi.Pointer sceneManager, + int parent, + ffi.Pointer name, +); + +@ffi.Native, EntityId, ffi.Bool)>( + symbol: 'get_entity_count', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int get_entity_count( + ffi.Pointer sceneManager, + int target, + bool renderableOnly, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, EntityId, ffi.Bool, ffi.Pointer)>( + symbol: 'get_entities', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_entities( + ffi.Pointer sceneManager, + int target, + bool renderableOnly, + ffi.Pointer out, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, EntityId, ffi.Int, ffi.Bool)>( + symbol: 'get_entity_name_at', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external ffi.Pointer get_entity_name_at( + ffi.Pointer sceneManager, + int target, + int index, + bool renderableOnly, +); + +@ffi.Native, ffi.Bool)>( + symbol: 'set_recording', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_recording( + ffi.Pointer viewer, + bool recording, +); + +@ffi.Native, ffi.Pointer)>( + symbol: 'set_recording_output_directory', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_recording_output_directory( + ffi.Pointer viewer, + ffi.Pointer outputDirectory, +); + +@ffi.Native( + symbol: 'ios_dummy', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void ios_dummy(); + +@ffi.Native)>( + symbol: 'flutter_filament_free', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void flutter_filament_free( + ffi.Pointer ptr, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(EntityId entityId1, EntityId entityId2)>>, + ffi.Bool)>( + symbol: 'add_collision_component', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void add_collision_component( + ffi.Pointer sceneManager, + int entityId, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(EntityId entityId1, EntityId entityId2)>> + callback, + bool affectsCollidingTransform, +); + +@ffi.Native, EntityId)>( + symbol: 'remove_collision_component', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_collision_component( + ffi.Pointer sceneManager, + int entityId, +); + +@ffi.Native, EntityId)>( + symbol: 'add_animation_component', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external bool add_animation_component( + ffi.Pointer sceneManager, + int entityId, +); + +@ffi.Native< + EntityId Function( + ffi.Pointer, + ffi.Pointer, + ffi.Int, + ffi.Pointer, + ffi.Int, + ffi.Int, + ffi.Pointer)>( + symbol: 'create_geometry', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external int create_geometry( + ffi.Pointer viewer, + ffi.Pointer vertices, + int numVertices, + ffi.Pointer indices, + int numIndices, + int primitiveType, + ffi.Pointer materialPath, +); + +@ffi.Native, EntityId, EntityId)>( + symbol: 'set_parent', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_parent( + ffi.Pointer sceneManager, + int child, + int parent, +); + +@ffi.Native, EntityId)>( + symbol: 'test_collisions', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void test_collisions( + ffi.Pointer sceneManager, + int entity, +); + +@ffi.Native, EntityId, ffi.Int)>( + symbol: 'set_priority', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_priority( + ffi.Pointer sceneManager, + int entityId, + int priority, +); + +@ffi.Native, ffi.Pointer)>( + symbol: 'get_gizmo', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_gizmo( + ffi.Pointer sceneManager, + ffi.Pointer out, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi + .Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer renderCallbackOwner)>>, + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer viewer)>>)>( + symbol: 'create_filament_viewer_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void create_filament_viewer_ffi( + ffi.Pointer context, + ffi.Pointer platform, + ffi.Pointer uberArchivePath, + ffi.Pointer loader, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer renderCallbackOwner)>> + renderCallback, + ffi.Pointer renderCallbackOwner, + ffi.Pointer< + ffi.NativeFunction viewer)>> + callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Uint32, + ffi.Pointer>)>( + symbol: 'create_swap_chain_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void create_swap_chain_ffi( + ffi.Pointer viewer, + ffi.Pointer surface, + int width, + int height, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>( + symbol: 'destroy_swap_chain_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void destroy_swap_chain_ffi( + ffi.Pointer viewer, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.IntPtr, ffi.Uint32, + ffi.Uint32, ffi.Pointer>)>( + symbol: 'create_render_target_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void create_render_target_ffi( + ffi.Pointer viewer, + int nativeTextureId, + int width, + int height, + ffi.Pointer> onComplete, +); + +@ffi.Native)>( + symbol: 'destroy_filament_viewer_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void destroy_filament_viewer_ffi( + ffi.Pointer viewer, +); + +@ffi.Native)>( + symbol: 'render_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void render_ffi( + ffi.Pointer viewer, +); + +@ffi.Native( + symbol: 'make_render_callback_fn_pointer', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external FilamentRenderCallback make_render_callback_fn_pointer( + FilamentRenderCallback arg0, +); + +@ffi.Native, ffi.Bool)>( + symbol: 'set_rendering_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_rendering_ffi( + ffi.Pointer viewer, + bool rendering, +); + +@ffi.Native( + symbol: 'set_frame_interval_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_frame_interval_ffi( + double frameInterval, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, + ffi.Float, ffi.Pointer>)>( + symbol: 'update_viewport_and_camera_projection_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void update_viewport_and_camera_projection_ffi( + ffi.Pointer viewer, + int width, + int height, + double scaleFactor, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, ffi.Float)>( + symbol: 'set_background_color_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_background_color_ffi( + ffi.Pointer viewer, + double r, + double g, + double b, + double a, +); + +@ffi.Native)>( + symbol: 'clear_background_image_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void clear_background_image_ffi( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Bool, ffi.Pointer>)>( + symbol: 'set_background_image_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_background_image_ffi( + ffi.Pointer viewer, + ffi.Pointer path, + bool fillHeight, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>( + symbol: 'set_background_image_position_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_background_image_position_ffi( + ffi.Pointer viewer, + double x, + double y, + bool clamp, +); + +@ffi.Native, ffi.Int)>( + symbol: 'set_tone_mapping_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_tone_mapping_ffi( + ffi.Pointer viewer, + int toneMapping, +); + +@ffi.Native, ffi.Float)>( + symbol: 'set_bloom_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_bloom_ffi( + ffi.Pointer viewer, + double strength, +); + +@ffi.Native, ffi.Pointer)>( + symbol: 'load_skybox_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void load_skybox_ffi( + ffi.Pointer viewer, + ffi.Pointer skyboxPath, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer, ffi.Float)>( + symbol: 'load_ibl_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void load_ibl_ffi( + ffi.Pointer viewer, + ffi.Pointer iblPath, + double intensity, +); + +@ffi.Native)>( + symbol: 'remove_skybox_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_skybox_ffi( + ffi.Pointer viewer, +); + +@ffi.Native)>( + symbol: 'remove_ibl_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_ibl_ffi( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Uint8, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Bool, + ffi.Pointer>)>( + symbol: 'add_light_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void add_light_ffi( + ffi.Pointer viewer, + int type, + double colour, + double intensity, + double posX, + double posY, + double posZ, + double dirX, + double dirY, + double dirZ, + bool shadows, + ffi.Pointer> callback, +); + +@ffi.Native, EntityId)>( + symbol: 'remove_light_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_light_ffi( + ffi.Pointer viewer, + int entityId, +); + +@ffi.Native)>( + symbol: 'clear_lights_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void clear_lights_ffi( + ffi.Pointer viewer, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int, + ffi.Pointer>)>( + symbol: 'load_glb_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void load_glb_ffi( + ffi.Pointer sceneManager, + ffi.Pointer assetPath, + int numInstances, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Int, + ffi.Pointer>)>( + symbol: 'load_glb_from_buffer_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void load_glb_from_buffer_ffi( + ffi.Pointer sceneManager, + ffi.Pointer data, + int length, + int numInstances, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>)>( + symbol: 'load_gltf_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void load_gltf_ffi( + ffi.Pointer sceneManager, + ffi.Pointer assetPath, + ffi.Pointer relativePath, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer>)>( + symbol: 'create_instance_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void create_instance_ffi( + ffi.Pointer sceneManager, + int entityId, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer>)>( + symbol: 'remove_entity_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void remove_entity_ffi( + ffi.Pointer viewer, + int asset, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>( + symbol: 'clear_entities_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void clear_entities_ffi( + ffi.Pointer viewer, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer>)>( + symbol: 'set_camera_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_camera_ffi( + ffi.Pointer viewer, + int asset, + ffi.Pointer nodeName, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer, ffi.Pointer, ffi.Int)>( + symbol: 'apply_weights_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void apply_weights_ffi( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer entityName, + ffi.Pointer weights, + int count, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Int, ffi.Bool, + ffi.Bool, ffi.Bool, ffi.Float)>( + symbol: 'play_animation_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void play_animation_ffi( + ffi.Pointer sceneManager, + int asset, + int index, + bool loop, + bool reverse, + bool replaceActive, + double crossfade, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, ffi.Int, ffi.Int)>( + symbol: 'set_animation_frame_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_animation_frame_ffi( + ffi.Pointer sceneManager, + int asset, + int animationIndex, + int animationFrame, +); + +@ffi.Native, EntityId, ffi.Int)>( + symbol: 'stop_animation_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void stop_animation_ffi( + ffi.Pointer sceneManager, + int asset, + int index, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer>)>( + symbol: 'get_animation_count_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_animation_count_ffi( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Int, + ffi.Pointer>)>( + symbol: 'get_animation_name_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_animation_name_ffi( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer outPtr, + int index, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer, + ffi.Int, + ffi.Pointer>)>( + symbol: 'get_morph_target_name_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_morph_target_name_ffi( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer meshName, + ffi.Pointer outPtr, + int index, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer>)>( + symbol: 'get_morph_target_name_count_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void get_morph_target_name_count_ffi( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer meshName, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Int, + ffi.Pointer>)>( + symbol: 'set_morph_target_weights_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_morph_target_weights_ffi( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer morphData, + int numWeights, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>)>( + symbol: 'set_bone_transform_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_bone_transform_ffi( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer entityName, + ffi.Pointer transform, + ffi.Pointer boneName, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Int, + ffi.Pointer, + ffi.Pointer>, + ffi.Int, + ffi.Float, + ffi.Bool)>( + symbol: 'add_bone_animation_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void add_bone_animation_ffi( + ffi.Pointer sceneManager, + int asset, + ffi.Pointer frameData, + int numFrames, + ffi.Pointer boneName, + ffi.Pointer> meshNames, + int numMeshTargets, + double frameLengthInMs, + bool isModelSpace, +); + +@ffi.Native, ffi.Bool)>( + symbol: 'set_post_processing_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void set_post_processing_ffi( + ffi.Pointer viewer, + bool enabled, +); + +@ffi.Native, EntityId)>( + symbol: 'reset_to_rest_pose_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void reset_to_rest_pose_ffi( + ffi.Pointer sceneManager, + int entityId, +); + +@ffi.Native( + symbol: 'ios_dummy_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void ios_dummy_ffi(); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Int, + ffi.Pointer, + ffi.Int, + ffi.Int, + ffi.Pointer, + ffi.Pointer>)>( + symbol: 'create_geometry_ffi', + assetId: 'package:flutter_filament/flutter_filament_bindings.dart') +external void create_geometry_ffi( + ffi.Pointer viewer, + ffi.Pointer vertices, + int numVertices, + ffi.Pointer indices, + int numIndices, + int primitiveType, + ffi.Pointer materialPath, + ffi.Pointer> callback, +); + +final class ResourceLoaderWrapper extends ffi.Struct { + external LoadFilamentResource loadResource; + + external FreeFilamentResource freeResource; + + external LoadFilamentResourceFromOwner loadFromOwner; + + external FreeFilamentResourceFromOwner freeFromOwner; + + external ffi.Pointer owner; +} + +typedef LoadFilamentResource = ffi.Pointer< + ffi.NativeFunction uri)>>; + +final class ResourceBuffer extends ffi.Struct { + external ffi.Pointer data; + + @ffi.Int32() + external int size; + + @ffi.Int32() + external int id; +} + +typedef FreeFilamentResource + = ffi.Pointer>; +typedef LoadFilamentResourceFromOwner = ffi.Pointer< + ffi.NativeFunction< + ResourceBuffer Function(ffi.Pointer, ffi.Pointer)>>; +typedef FreeFilamentResourceFromOwner = ffi.Pointer< + ffi + .NativeFunction)>>; + +/// This header replicates most of the methods in FlutterFilamentApi.h, and is only intended to be used to generate client FFI bindings. +/// The intention is that calling one of these methods will call its respective method in FlutterFilamentApi.h, but wrapped in some kind of thread runner to ensure thread safety. +typedef EntityId = ffi.Int32; +typedef _ManipulatorMode = ffi.Int32; +typedef FilamentRenderCallback = ffi.Pointer< + ffi.NativeFunction owner)>>; + +const int __bool_true_false_are_defined = 1; + +const int true1 = 1; + +const int false1 = 0; diff --git a/flutter_filament_federated/flutter_filament/lib/filament/flutter_filament_plugin.dart b/flutter_filament_federated/flutter_filament/lib/filament/flutter_filament_plugin.dart new file mode 100644 index 00000000..8a8bab1f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/flutter_filament_plugin.dart @@ -0,0 +1,45 @@ +import 'dart:async'; +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:flutter_filament_platform_interface/flutter_filament_platform_interface.dart'; +import 'package:flutter_filament_platform_interface/flutter_filament_texture.dart'; + +/// +/// A Flutter-only interface for creating an [AbstractFilamentViewer] . +/// +class FlutterFilamentPlugin { + AbstractFilamentViewer get viewer => FlutterFilamentPlatform.instance.viewer; + + final _initialized = Completer(); + Future get initialized => _initialized.future; + + Future initialize({String? uberArchivePath}) async { + if (_initialized.isCompleted) { + throw Exception("Instance already initialized"); + } + await FlutterFilamentPlatform.instance + .initialize(uberArchivePath: uberArchivePath); + _initialized.complete(true); + await viewer.initialized; + } + + Future createTexture( + int width, int height, int offsetLeft, int offsetRight) async { + return FlutterFilamentPlatform.instance + .createTexture(width, height, offsetLeft, offsetRight); + } + + Future destroyTexture(FlutterFilamentTexture texture) async { + return FlutterFilamentPlatform.instance.destroyTexture(texture); + } + + @override + Future resizeTexture(FlutterFilamentTexture texture, + int width, int height, int offsetLeft, int offsetRight) async { + return FlutterFilamentPlatform.instance + .resizeTexture(texture, width, height, offsetLeft, offsetRight); + } + + void dispose() { + FlutterFilamentPlatform.instance.dispose(); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/utils/camera_orientation.dart b/flutter_filament_federated/flutter_filament/lib/filament/utils/camera_orientation.dart new file mode 100644 index 00000000..3e800836 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/utils/camera_orientation.dart @@ -0,0 +1,15 @@ +import 'package:vector_math/vector_math_64.dart' as v; + +class CameraOrientation { + v.Vector3 position = v.Vector3(0, 0, 0); + + var rotationX = 0.0; + var rotationY = 0.0; + var rotationZ = 0.0; + + v.Quaternion compose() { + return v.Quaternion.axisAngle(v.Vector3(0, 0, 1), rotationZ) * + v.Quaternion.axisAngle(v.Vector3(0, 1, 0), rotationY) * + v.Quaternion.axisAngle(v.Vector3(1, 0, 0), rotationX); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/utils/hardware_keyboard_listener.dart b/flutter_filament_federated/flutter_filament/lib/filament/utils/hardware_keyboard_listener.dart new file mode 100644 index 00000000..2bda1eef --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/utils/hardware_keyboard_listener.dart @@ -0,0 +1,60 @@ +import 'package:dart_filament/dart_filament/entities/entity_transform_controller.dart'; +import 'package:flutter/services.dart'; + +class HardwareKeyboardListener { + final EntityTransformController _controller; + var _listening = true; + HardwareKeyboardListener(this._controller) { + // Get the global handler. + final KeyMessageHandler? existing = + ServicesBinding.instance.keyEventManager.keyMessageHandler; + // The handler is guaranteed non-null since + // `FallbackKeyEventRegistrar.instance` is only called during + // `Focus.onFocusChange`, at which time `ServicesBinding.instance` must + // have been called somewhere. + assert(existing != null); + // Assign the global handler with a patched handler. + ServicesBinding.instance.keyEventManager.keyMessageHandler = (keyMessage) { + if (keyMessage.rawEvent == null) { + return false; + } + if (!_listening) { + return false; + } + var event = keyMessage.rawEvent!; + switch (event.logicalKey) { + case LogicalKeyboardKey.escape: + _listening = false; + break; + case LogicalKeyboardKey.keyW: + (event is RawKeyDownEvent) + ? _controller.forwardPressed() + : _controller.forwardReleased(); + break; + case LogicalKeyboardKey.keyA: + event is RawKeyDownEvent + ? _controller.strafeLeftPressed() + : _controller.strafeLeftReleased(); + break; + case LogicalKeyboardKey.keyS: + event is RawKeyDownEvent + ? _controller.backPressed() + : _controller.backReleased(); + break; + case LogicalKeyboardKey.keyD: + event is RawKeyDownEvent + ? _controller.strafeRightPressed() + : _controller.strafeRightReleased(); + break; + default: + break; + } + return true; + }; + } + + void dispose() { + ServicesBinding.instance.keyEventManager.keyMessageHandler = null; + _controller.dispose(); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/utils/hardware_keyboard_poll.dart b/flutter_filament_federated/flutter_filament/lib/filament/utils/hardware_keyboard_poll.dart new file mode 100644 index 00000000..990c183c --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/utils/hardware_keyboard_poll.dart @@ -0,0 +1,39 @@ +import 'dart:async'; +import 'package:dart_filament/dart_filament/entities/entity_transform_controller.dart'; +import 'package:flutter/services.dart'; + +class HardwareKeyboardPoll { + final EntityTransformController _controller; + late Timer _timer; + HardwareKeyboardPoll(this._controller) { + _timer = Timer.periodic(const Duration(milliseconds: 16), (_) { + if (RawKeyboard.instance.keysPressed.contains(LogicalKeyboardKey.keyW)) { + _controller.forwardPressed(); + } else { + _controller.forwardReleased(); + } + + if (RawKeyboard.instance.keysPressed.contains(LogicalKeyboardKey.keyS)) { + _controller.backPressed(); + } else { + _controller.backReleased(); + } + + if (RawKeyboard.instance.keysPressed.contains(LogicalKeyboardKey.keyA)) { + _controller.strafeLeftPressed(); + } else { + _controller.strafeLeftReleased(); + } + + if (RawKeyboard.instance.keysPressed.contains(LogicalKeyboardKey.keyD)) { + _controller.strafeRightPressed(); + } else { + _controller.strafeRightReleased(); + } + }); + } + + void dispose() { + _timer.cancel(); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/camera_options_widget.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/camera_options_widget.dart new file mode 100644 index 00000000..7fba317d --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/camera_options_widget.dart @@ -0,0 +1,234 @@ +import 'package:dart_filament/dart_filament/entities/filament_entity.dart'; +import 'package:dart_filament/dart_filament/filament_viewer_impl.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import '../../utils/camera_orientation.dart'; + +import 'dart:math'; +import 'package:vector_math/vector_math_64.dart' as v64; + +class CameraOptionsWidget extends StatefulWidget { + final FilamentViewer controller; + final CameraOrientation cameraOrientation; + final List<({FilamentEntity entity, String name})> cameras; + + CameraOptionsWidget( + {super.key, + required this.controller, + required this.cameras, + required this.cameraOrientation}) {} + + @override + State createState() => _CameraOptionsWidgetState(); +} + +class _CameraOptionsWidgetState extends State { + final _apertureController = TextEditingController(); + final _speedController = TextEditingController(); + final _sensitivityController = TextEditingController(); + + @override + void initState() { + _apertureController.text = "0"; + _speedController.text = "0"; + _sensitivityController.text = "0"; + + _apertureController.addListener(() { + _set(); + setState(() {}); + }); + _speedController.addListener(() { + _set(); + setState(() {}); + }); + _sensitivityController.addListener(() { + _set(); + setState(() {}); + }); + + super.initState(); + } + + @override + void didUpdateWidget(CameraOptionsWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.cameras.length != widget.cameras.length) { + setState(() {}); + } + } + + Future _set() async { + await widget.controller.setCameraExposure( + double.parse(_apertureController.text), + double.parse(_speedController.text), + double.parse(_sensitivityController.text)); + await widget.controller.setCameraPosition( + widget.cameraOrientation.position.x, + widget.cameraOrientation.position.y, + widget.cameraOrientation.position.z); + var rotation = widget.cameraOrientation.compose(); + await widget.controller.setCameraRotation(rotation); + print( + "Camera : ${widget.cameraOrientation.position} ${widget.cameraOrientation.rotationX} ${widget.cameraOrientation.rotationY} ${widget.cameraOrientation.rotationZ}"); + setState(() {}); + } + + double _bloom = 0.0; + + double _focalLength = 26.0; + @override + Widget build(BuildContext context) { + return Theme( + data: ThemeData(platform: TargetPlatform.android), + child: Container( + decoration: BoxDecoration(color: Colors.white.withOpacity(0.5)), + child: SliderTheme( + data: SliderThemeData( + showValueIndicator: ShowValueIndicator.always, + valueIndicatorTextStyle: TextStyle(color: Colors.black)), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Row(children: [ + Text("Aperture"), + Expanded( + child: TextField( + controller: _apertureController, + )), + Text("Speed"), + Expanded(child: TextField(controller: _speedController)), + Text("Sensitivity"), + Expanded( + child: TextField(controller: _sensitivityController)), + ]), + Row(children: [ + Text("Bloom: ${_bloom.toStringAsFixed(2)}"), + Slider( + value: _bloom, + min: 0.0, + max: 1.0, + onChanged: (v) async { + setState(() { + _bloom = v; + }); + await widget.controller.setBloom(_bloom); + }) + ]), + Row(children: [ + Text("Focal length"), + Slider( + label: _focalLength.toString(), + value: _focalLength, + min: 1.0, + max: 100.0, + onChanged: (v) async { + setState(() { + _focalLength = v; + }); + await widget.controller + .setCameraFocalLength(_focalLength); + }) + ]), + Row(children: [ + Text("X"), + Slider( + label: widget.cameraOrientation.position.x.toString(), + value: widget.cameraOrientation.position.x, + min: -100.0, + max: 100.0, + onChanged: (v) async { + setState(() { + widget.cameraOrientation.position.x = v; + }); + _set(); + }) + ]), + Row(children: [ + Text("Y"), + Slider( + label: widget.cameraOrientation.position.y.toString(), + value: widget.cameraOrientation.position.y, + min: -100.0, + max: 100.0, + onChanged: (v) async { + setState(() { + widget.cameraOrientation.position.y = v; + }); + _set(); + }) + ]), + Row(children: [ + Text("Z"), + Slider( + label: widget.cameraOrientation.position.z.toString(), + value: widget.cameraOrientation.position.z, + min: -100.0, + max: 100.0, + onChanged: (v) async { + setState(() { + widget.cameraOrientation.position.z = v; + }); + _set(); + }) + ]), + Row(children: [ + Text("ROTX"), + Slider( + label: widget.cameraOrientation.rotationX.toString(), + value: widget.cameraOrientation.rotationX, + min: -pi, + max: pi, + onChanged: (value) async { + setState(() { + widget.cameraOrientation.rotationX = value; + }); + _set(); + }) + ]), + Row(children: [ + Text("ROTY"), + Slider( + label: widget.cameraOrientation.rotationY.toString(), + value: widget.cameraOrientation.rotationY, + min: -pi, + max: pi, + onChanged: (v) async { + setState(() { + widget.cameraOrientation.rotationY = v; + }); + _set(); + }), + ]), + Row(children: [ + Text("ROTZ"), + Slider( + label: widget.cameraOrientation.rotationZ.toString(), + value: widget.cameraOrientation.rotationZ, + min: -pi, + max: pi, + onChanged: (v) async { + setState(() { + widget.cameraOrientation.rotationZ = v; + }); + _set(); + }) + ]), + Wrap( + children: [ + GestureDetector( + child: Text("Main "), + onTap: () { + widget.controller.setMainCamera(); + }, + ), + ...widget.cameras + .map((camera) => GestureDetector( + onTap: () { + widget.controller + .setCamera(camera.entity, camera.name); + }, + child: Text(camera.name))) + .toList() + ], + ) + ])))); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/entity_controller_mouse_widget.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/entity_controller_mouse_widget.dart new file mode 100644 index 00000000..cd97d6eb --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/entity_controller_mouse_widget.dart @@ -0,0 +1,52 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +import 'dart:async'; + +import 'package:dart_filament/dart_filament.dart'; + +/// +/// A widget that translates mouse gestures to zoom/pan/rotate actions. +/// +class EntityTransformMouseControllerWidget extends StatelessWidget { + final EntityTransformController? transformController; + final Widget? child; + + EntityTransformMouseControllerWidget( + {Key? key, required this.transformController, this.child}) + : super(key: key); + + Timer? _timer; + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return Listener( + onPointerDown: (event) { + if (kPrimaryMouseButton & event.buttons != 0) { + transformController?.mouse1Down(); + } + }, + onPointerUp: (event) { + if (kPrimaryMouseButton & event.buttons != 0) { + transformController?.mouse1Up(); + } + }, + onPointerHover: (event) { + _timer?.cancel(); + if (event.position.dx < 10) { + _timer = Timer.periodic(const Duration(milliseconds: 17), (_) { + transformController?.look(-30); + }); + } else if (event.position.dx > constraints.maxWidth - 10) { + _timer = Timer.periodic(const Duration(milliseconds: 17), (_) { + transformController?.look(30); + }); + } else { + transformController?.look(event.delta.dx); + } + }, + child: child); + }); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector.dart new file mode 100644 index 00000000..97d319dc --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector.dart @@ -0,0 +1,93 @@ +import 'dart:io'; + +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'filament_gesture_detector_desktop.dart'; +import 'filament_gesture_detector_mobile.dart'; + +enum GestureType { rotateCamera, panCamera, panBackground } + +/// +/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions. +/// +class FilamentGestureDetector extends StatelessWidget { + /// + /// The content to display below the gesture detector/listener widget. + /// This will usually be a FilamentWidget (so you can navigate by directly interacting with the viewport), but this is not necessary. + /// It is equally possible to render the viewport/gesture controls elsewhere in the widget hierarchy. The only requirement is that they share the same [FilamentController]. + /// + final Widget? child; + + /// + /// The [controller] attached to the [FilamentWidget] you wish to control. + /// + final AbstractFilamentViewer controller; + + /// + /// If true, an overlay will be shown with buttons to toggle whether pointer movements are interpreted as: + /// 1) rotate or a pan (mobile only), + /// 2) moving the camera or the background image (TODO). + /// + final bool showControlOverlay; + + /// + /// If false, gestures will not manipulate the active camera. + /// + final bool enableCamera; + + /// + /// If false, pointer down events will not trigger hit-testing (picking). + /// + final bool enablePicking; + + final void Function(ScaleStartDetails)? onScaleStart; + final void Function(ScaleUpdateDetails)? onScaleUpdate; + final void Function(ScaleEndDetails)? onScaleEnd; + + const FilamentGestureDetector( + {Key? key, + required this.controller, + this.child, + this.showControlOverlay = false, + this.enableCamera = true, + this.enablePicking = true, + this.onScaleStart, + this.onScaleUpdate, + this.onScaleEnd}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: controller.initialized, + builder: (_, initialized) { + if (initialized.data != true) { + return Container(); + } + if (kIsWeb) { + throw Exception("TODO"); + } else if (Platform.isLinux || + Platform.isWindows || + Platform.isMacOS) { + return FilamentGestureDetectorDesktop( + controller: controller, + child: child, + showControlOverlay: showControlOverlay, + enableCamera: enableCamera, + enablePicking: enablePicking, + ); + } else { + return FilamentGestureDetectorMobile( + controller: controller, + child: child, + showControlOverlay: showControlOverlay, + enableCamera: enableCamera, + enablePicking: enablePicking, + onScaleStart: onScaleStart, + onScaleUpdate: onScaleUpdate, + onScaleEnd: onScaleEnd); + } + }); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector_desktop.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector_desktop.dart new file mode 100644 index 00000000..8110dc1e --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector_desktop.dart @@ -0,0 +1,192 @@ +import 'dart:async'; + +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:dart_filament/dart_filament/entities/gizmo.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +/// +/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions. +/// +class FilamentGestureDetectorDesktop extends StatefulWidget { + /// + /// The content to display below the gesture detector/listener widget. + /// This will usually be a FilamentWidget (so you can navigate by directly interacting with the viewport), but this is not necessary. + /// It is equally possible to render the viewport/gesture controls elsewhere in the widget hierarchy. The only requirement is that they share the same [FilamentController]. + /// + final Widget? child; + + /// + /// The [controller] attached to the [FilamentWidget] you wish to control. + /// + final AbstractFilamentViewer controller; + + /// + /// If true, an overlay will be shown with buttons to toggle whether pointer movements are interpreted as: + /// 1) rotate or a pan (mobile only), + /// 2) moving the camera or the background image (TODO). + /// + final bool showControlOverlay; + + /// + /// If false, gestures will not manipulate the active camera. + /// + final bool enableCamera; + + /// + /// If false, pointer down events will not trigger hit-testing (picking). + /// + final bool enablePicking; + + const FilamentGestureDetectorDesktop( + {Key? key, + required this.controller, + this.child, + this.showControlOverlay = false, + this.enableCamera = true, + this.enablePicking = true}) + : super(key: key); + + @override + State createState() => _FilamentGestureDetectorDesktopState(); +} + +class _FilamentGestureDetectorDesktopState + extends State { + /// + /// + /// + // ignore: unused_field + final bool _scaling = false; + + bool _pointerMoving = false; + + AbstractGizmo? _gizmo; + + @override + void initState() { + super.initState(); + widget.controller.scene.gizmo.then((g) { + _gizmo = g; + setState(() {}); + }); + } + + @override + void didUpdateWidget(FilamentGestureDetectorDesktop oldWidget) { + if (widget.showControlOverlay != oldWidget.showControlOverlay || + widget.enableCamera != oldWidget.enableCamera || + widget.enablePicking != oldWidget.enablePicking) { + setState(() {}); + } + + super.didUpdateWidget(oldWidget); + } + + Timer? _scrollTimer; + + /// + /// Scroll-wheel on desktop, interpreted as zoom + /// + void _zoom(PointerScrollEvent pointerSignal) async { + _scrollTimer?.cancel(); + await widget.controller.zoomBegin(); + await widget.controller.zoomUpdate( + pointerSignal.localPosition.dx, + pointerSignal.localPosition.dy, + pointerSignal.scrollDelta.dy > 0 ? 1 : -1); + + // we don't want to end the zoom in the same frame, because this will destroy the camera manipulator (and cancel the zoom update). + // here, we just defer calling [zoomEnd] for 100ms to ensure the update is propagated through. + _scrollTimer = Timer(const Duration(milliseconds: 100), () async { + await widget.controller.zoomEnd(); + }); + } + + Timer? _pickTimer; + + @override + Widget build(BuildContext context) { + if (_gizmo == null) { + return Container(); + } + return Listener( + // onPointerHover: (event) async { + // if (_gizmo.isActive) { + // return; + // } + // _pickTimer?.cancel(); + // _pickTimer = Timer(const Duration(milliseconds: 100), () async { + // widget.controller + // .pick(event.position.dx.toInt(), event.position.dy.toInt()); + // }); + // }, + onPointerSignal: (PointerSignalEvent pointerSignal) async { + if (pointerSignal is PointerScrollEvent) { + if (widget.enableCamera) { + _zoom(pointerSignal); + } + } else { + throw Exception("TODO"); + } + }, + onPointerPanZoomStart: (pzs) { + throw Exception("TODO - is this a pinch zoom on laptop trackpad?"); + }, + onPointerDown: (d) async { + if (_gizmo!.isActive) { + return; + } + if (d.buttons != kTertiaryButton && widget.enablePicking) { + widget.controller + .pick(d.localPosition.dx.toInt(), d.localPosition.dy.toInt()); + } + _pointerMoving = false; + }, + // holding/moving the left mouse button is interpreted as a pan, middle mouse button as a rotate + onPointerMove: (PointerMoveEvent d) async { + if (_gizmo!.isActive) { + _gizmo!.translate(d.delta.dx, d.delta.dy); + return; + } + // if this is the first move event, we need to call rotateStart/panStart to set the first coordinates + if (!_pointerMoving) { + if (d.buttons == kTertiaryButton && widget.enableCamera) { + widget.controller + .rotateStart(d.localPosition.dx, d.localPosition.dy); + } else if (widget.enableCamera) { + widget.controller + .panStart(d.localPosition.dx, d.localPosition.dy); + } + } + // set the _pointerMoving flag so we don't call rotateStart/panStart on future move events + _pointerMoving = true; + if (d.buttons == kTertiaryButton && widget.enableCamera) { + widget.controller + .rotateUpdate(d.localPosition.dx, d.localPosition.dy); + } else if (widget.enableCamera) { + widget.controller.panUpdate(d.localPosition.dx, d.localPosition.dy); + } + }, + // when the left mouse button is released: + // 1) if _pointerMoving is true, this completes the pan + // 2) if _pointerMoving is false, this is interpreted as a pick + // same applies to middle mouse button, but this is ignored as a pick + onPointerUp: (PointerUpEvent d) async { + if (_gizmo!.isActive) { + _gizmo!.reset(); + return; + } + + if (d.buttons == kTertiaryButton && widget.enableCamera) { + widget.controller.rotateEnd(); + } else { + if (_pointerMoving && widget.enableCamera) { + widget.controller.panEnd(); + } + } + _pointerMoving = false; + }, + child: widget.child); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector_mobile.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector_mobile.dart new file mode 100644 index 00000000..c152e3d8 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/camera/gestures/filament_gesture_detector_mobile.dart @@ -0,0 +1,234 @@ +import 'dart:async'; +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:flutter/material.dart'; + +enum GestureType { rotateCamera, panCamera, panBackground } + +/// +/// A widget that translates finger/mouse gestures to zoom/pan/rotate actions. +/// +class FilamentGestureDetectorMobile extends StatefulWidget { + /// + /// The content to display below the gesture detector/listener widget. + /// This will usually be a FilamentWidget (so you can navigate by directly interacting with the viewport), but this is not necessary. + /// It is equally possible to render the viewport/gesture controls elsewhere in the widget hierarchy. The only requirement is that they share the same [FilamentController]. + /// + final Widget? child; + + /// + /// The [controller] attached to the [FilamentWidget] you wish to control. + /// + final AbstractFilamentViewer controller; + + /// + /// If true, an overlay will be shown with buttons to toggle whether pointer movements are interpreted as: + /// 1) rotate or a pan (mobile only), + /// 2) moving the camera or the background image (TODO). + /// + final bool showControlOverlay; + + /// + /// If false, gestures will not manipulate the active camera. + /// + final bool enableCamera; + + /// + /// If false, pointer down events will not trigger hit-testing (picking). + /// + final bool enablePicking; + + final double zoomDelta; + + final void Function(ScaleStartDetails)? onScaleStart; + final void Function(ScaleUpdateDetails)? onScaleUpdate; + final void Function(ScaleEndDetails)? onScaleEnd; + + const FilamentGestureDetectorMobile( + {Key? key, + required this.controller, + this.child, + this.showControlOverlay = false, + this.enableCamera = true, + this.enablePicking = true, + this.onScaleStart, + this.onScaleUpdate, + this.onScaleEnd, + this.zoomDelta = 1}) + : super(key: key); + + @override + State createState() => _FilamentGestureDetectorMobileState(); +} + +class _FilamentGestureDetectorMobileState + extends State { + GestureType gestureType = GestureType.panCamera; + + final _icons = { + GestureType.panBackground: Icons.image, + GestureType.panCamera: Icons.pan_tool, + GestureType.rotateCamera: Icons.rotate_90_degrees_ccw + }; + + // on mobile, we can't differentiate between pointer down events like we do on desktop with primary/secondary/tertiary buttons + // we allow the user to toggle between panning and rotating by double-tapping the widget + bool _rotateOnPointerMove = false; + + // + // + // + bool _scaling = false; + + // to avoid duplicating code for pan/rotate (panStart, panUpdate, panEnd, rotateStart, rotateUpdate etc) + // we have only a single function for start/update/end. + // when the gesture type is changed, these properties are updated to point to the correct function. + // ignore: unused_field + late Function(double x, double y) _functionStart; + // ignore: unused_field + late Function(double x, double y) _functionUpdate; + // ignore: unused_field + late Function() _functionEnd; + + @override + void initState() { + _setFunction(); + super.initState(); + } + + void _setFunction() { + switch (gestureType) { + case GestureType.rotateCamera: + _functionStart = widget.controller.rotateStart; + _functionUpdate = widget.controller.rotateUpdate; + _functionEnd = widget.controller.rotateEnd; + break; + case GestureType.panCamera: + _functionStart = widget.controller.panStart; + _functionUpdate = widget.controller.panUpdate; + _functionEnd = widget.controller.panEnd; + break; + // TODO + case GestureType.panBackground: + _functionStart = (x, y) async {}; + _functionUpdate = (x, y) async {}; + _functionEnd = () async {}; + } + } + + @override + void didUpdateWidget(FilamentGestureDetectorMobile oldWidget) { + if (widget.showControlOverlay != oldWidget.showControlOverlay || + widget.enableCamera != oldWidget.enableCamera || + widget.enablePicking != oldWidget.enablePicking) { + setState(() {}); + } + + super.didUpdateWidget(oldWidget); + } + + // ignore: unused_field + Timer? _scrollTimer; + double _lastScale = 0; + + // pinch zoom on mobile + // couldn't find any equivalent for pointerCount in Listener (?) so we use a GestureDetector + @override + Widget build(BuildContext context) { + return Stack(children: [ + Positioned.fill( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTapDown: (d) { + if (!widget.enablePicking) { + return; + } + + widget.controller.pick( + d.globalPosition.dx.toInt(), d.globalPosition.dy.toInt()); + }, + onDoubleTap: () { + setState(() { + _rotateOnPointerMove = !_rotateOnPointerMove; + }); + }, + onScaleStart: (d) async { + if (widget.onScaleStart != null) { + widget.onScaleStart!.call(d); + return; + } + if (d.pointerCount == 2 && widget.enableCamera) { + _scaling = true; + await widget.controller.zoomBegin(); + } else if (!_scaling && widget.enableCamera) { + if (_rotateOnPointerMove) { + widget.controller.rotateStart( + d.localFocalPoint.dx, d.localFocalPoint.dy); + } else { + widget.controller + .panStart(d.localFocalPoint.dx, d.localFocalPoint.dy); + } + } + }, + onScaleUpdate: (ScaleUpdateDetails d) async { + if (widget.onScaleUpdate != null) { + widget.onScaleUpdate!.call(d); + return; + } + if (d.pointerCount == 2 && widget.enableCamera) { + if (d.horizontalScale != _lastScale) { + widget.controller.zoomUpdate( + d.localFocalPoint.dx, + d.localFocalPoint.dy, + d.horizontalScale > _lastScale ? 0.1 : -0.1); + _lastScale = d.horizontalScale; + } + } else if (!_scaling && widget.enableCamera) { + if (_rotateOnPointerMove) { + widget.controller + .rotateUpdate(d.focalPoint.dx, d.focalPoint.dy); + } else { + widget.controller + .panUpdate(d.focalPoint.dx, d.focalPoint.dy); + } + } + }, + onScaleEnd: (d) async { + if (widget.onScaleEnd != null) { + widget.onScaleEnd!.call(d); + return; + } + + if (d.pointerCount == 2 && widget.enableCamera) { + widget.controller.zoomEnd(); + } else if (!_scaling && widget.enableCamera) { + if (_rotateOnPointerMove) { + widget.controller.rotateEnd(); + } else { + widget.controller.panEnd(); + } + } + _scaling = false; + }, + child: widget.child)), + widget.showControlOverlay + ? Align( + alignment: Alignment.bottomRight, + child: GestureDetector( + onTap: () { + setState(() { + var curIdx = GestureType.values.indexOf(gestureType); + var nextIdx = curIdx == GestureType.values.length - 1 + ? 0 + : curIdx + 1; + gestureType = GestureType.values[nextIdx]; + _setFunction(); + }); + }, + child: Container( + padding: const EdgeInsets.all(50), + child: Icon(_icons[gestureType], color: Colors.green)), + )) + : Container() + ]); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/debug/entity_list_widget.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/debug/entity_list_widget.dart new file mode 100644 index 00000000..5df02401 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/debug/entity_list_widget.dart @@ -0,0 +1,144 @@ +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:dart_filament/dart_filament/entities/filament_entity.dart'; +import 'package:flutter_filament/flutter_filament.dart'; +import 'package:flutter/material.dart'; + +class EntityListWidget extends StatefulWidget { + final AbstractFilamentViewer? controller; + + const EntityListWidget({super.key, required this.controller}); + + @override + State createState() => _EntityListWidget(); +} + +class _EntityListWidget extends State { + @override + void didUpdateWidget(EntityListWidget oldWidget) { + super.didUpdateWidget(oldWidget); + } + + Widget _entity(FilamentEntity entity) { + return FutureBuilder( + future: widget.controller!.getAnimationNames(entity), + builder: (_, animations) { + if (animations.data == null) { + return Container(); + } + final menuController = MenuController(); + return Row(children: [ + Expanded( + child: GestureDetector( + onTap: () { + widget.controller!.scene.select(entity); + }, + child: Text(entity.toString(), + style: TextStyle( + fontWeight: + entity == widget.controller!.scene.selected + ? FontWeight.bold + : FontWeight.normal)))), + MenuAnchor( + controller: menuController, + child: Container( + color: Colors.transparent, + child: IconButton( + icon: const Icon( + Icons.arrow_drop_down, + color: Colors.black, + ), + onPressed: () { + menuController.open(); + }, + )), + menuChildren: [ + MenuItemButton( + child: const Text("Remove"), + onPressed: () async { + await widget.controller!.removeEntity(entity); + }), + MenuItemButton( + child: const Text("Transform to unit cube"), + onPressed: () async { + await widget.controller!.transformToUnitCube(entity); + }), + SubmenuButton( + child: const Text("Animations"), + menuChildren: animations.data! + .map((a) => MenuItemButton( + child: Text(a), + onPressed: () { + widget.controller!.playAnimation( + entity, animations.data!.indexOf(a)); + }, + )) + .toList()) + ]) + ]); + }); + } + + Widget _light(FilamentEntity entity) { + final controller = MenuController(); + return Row(children: [ + GestureDetector( + onTap: () { + widget.controller!.scene.select(entity); + }, + child: Container( + color: Colors.transparent, + child: Text("Light $entity", + style: TextStyle( + fontWeight: entity == widget.controller!.scene.selected + ? FontWeight.bold + : FontWeight.normal)))), + MenuAnchor( + controller: controller, + child: Container( + color: Colors.transparent, + child: IconButton( + icon: const Icon( + Icons.arrow_drop_down, + color: Colors.black, + ), + onPressed: () { + controller.open(); + }, + )), + menuChildren: [ + MenuItemButton( + child: const Text("Remove"), + onPressed: () async { + await widget.controller!.removeLight(entity); + }) + ]) + ]); + } + + @override + Widget build(BuildContext context) { + if (widget.controller == null) { + return Container(); + } + return StreamBuilder( + stream: widget.controller!.scene.onUpdated, + builder: (_, __) => Container( + padding: const EdgeInsets.symmetric( + horizontal: 30, vertical: 10), + height: 100, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Colors.white.withOpacity(0.25), + ), + child: ListView( + reverse: true, + children: widget.controller!.scene + .listLights() + .map(_light) + .followedBy(widget.controller!.scene + .listEntities() + .map(_entity)) + .cast() + .toList()))); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/filament_widget.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/filament_widget.dart new file mode 100644 index 00000000..dd2553fb --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/filament_widget.dart @@ -0,0 +1,155 @@ +import 'dart:io'; +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter_filament_platform_interface/flutter_filament_platform_interface.dart'; +import 'package:flutter_filament_platform_interface/flutter_filament_texture.dart'; +import 'package:flutter_filament/flutter_filament.dart'; +import 'resize_observer.dart'; + +class FilamentWidget extends StatefulWidget { + final FlutterFilamentPlugin plugin; + + /// + /// The content to render before the texture widget is available. + /// The default is a solid red Container, intentionally chosen to make it clear that there will be at least one frame where the Texture widget is not being rendered. + /// + final Widget? initial; + + const FilamentWidget({Key? key, this.initial, required this.plugin}) + : super(key: key); + + @override + _FilamentWidgetState createState() => _FilamentWidgetState(); +} + +class _FilamentWidgetState extends State { + FlutterFilamentTexture? _texture; + + late final AppLifecycleListener _appLifecycleListener; + + Rect get _rect { + final renderBox = (context.findRenderObject()) as RenderBox; + final size = renderBox.size; + final translation = renderBox.getTransformTo(null).getTranslation(); + return Rect.fromLTWH(translation.x, translation.y, size.width, size.height); + } + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + var dpr = MediaQuery.of(context).devicePixelRatio; + var size = ((context.findRenderObject()) as RenderBox).size; + var width = (dpr * size.width).ceil(); + var height = (dpr * size.height).ceil(); + _texture = await widget.plugin.createTexture(width, height, 0, 0); + _appLifecycleListener = AppLifecycleListener( + onStateChange: _handleStateChange, + ); + setState(() {}); + }); + super.initState(); + } + + @override + void dispose() { + if (_texture != null) { + widget.plugin.destroyTexture(_texture!); + } + + _appLifecycleListener.dispose(); + super.dispose(); + } + + bool _wasRenderingOnInactive = false; + + void _handleStateChange(AppLifecycleState state) async { + await widget.plugin.viewer.initialized; + switch (state) { + case AppLifecycleState.detached: + print("Detached"); + if (!_wasRenderingOnInactive) { + _wasRenderingOnInactive = widget.plugin.viewer.rendering; + } + await widget.plugin.viewer.setRendering(false); + break; + case AppLifecycleState.hidden: + print("Hidden"); + if (!_wasRenderingOnInactive) { + _wasRenderingOnInactive = widget.plugin.viewer.rendering; + } + await widget.plugin.viewer.setRendering(false); + break; + case AppLifecycleState.inactive: + print("Inactive"); + if (!_wasRenderingOnInactive) { + _wasRenderingOnInactive = widget.plugin.viewer.rendering; + } + // on Windows in particular, restoring a window after minimizing stalls the renderer (and the whole application) for a considerable length of time. + // disabling rendering on minimize seems to fix the issue (so I wonder if there's some kind of command buffer that's filling up while the window is minimized). + await widget.plugin.viewer.setRendering(false); + break; + case AppLifecycleState.paused: + print("Paused"); + if (!_wasRenderingOnInactive) { + _wasRenderingOnInactive = widget.plugin.viewer.rendering; + } + await widget.plugin.viewer.setRendering(false); + break; + case AppLifecycleState.resumed: + print("Resumed"); + await widget.plugin.viewer.setRendering(_wasRenderingOnInactive); + break; + } + } + + bool _resizing = false; + + Future _resizeTexture(Size newSize) async { + if (_resizing) { + return; + } + await Future.delayed(Duration.zero); + if (_resizing) { + return; + } + _resizing = true; + + var dpr = MediaQuery.of(context).devicePixelRatio; + + _texture = await widget.plugin.resizeTexture(_texture!, + (dpr * newSize.width).ceil(), (dpr * newSize.height).ceil(), 0, 0); + print( + "Resized texture, new flutter ID is ${_texture!.flutterTextureId} (hardware ID ${_texture!.hardwareTextureId})"); + setState(() {}); + _resizing = false; + } + + @override + Widget build(BuildContext context) { + if (_texture == null) { + return widget.initial ?? Container(color: Colors.red); + } + + var textureWidget = Texture( + key: ObjectKey("texture_${_texture!.flutterTextureId}"), + textureId: _texture!.flutterTextureId, + filterQuality: FilterQuality.none, + freeze: false, + ); + + return ResizeObserver( + onResized: _resizeTexture, + child: Stack(children: [ + Positioned.fill( + child: Platform.isLinux || Platform.isWindows + ? Transform( + alignment: Alignment.center, + transform: Matrix4.rotationX( + pi), // TODO - this rotation is due to OpenGL texture coordinate working in a different space from Flutter, can we move this to the C++ side somewhere? + child: textureWidget) + : textureWidget) + ])); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/lights/ibl_rotation_slider.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/lights/ibl_rotation_slider.dart new file mode 100644 index 00000000..87968328 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/lights/ibl_rotation_slider.dart @@ -0,0 +1,29 @@ +import 'dart:math'; +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:flutter/material.dart'; +import 'package:vector_math/vector_math_64.dart' as v; + +class IblRotationSliderWidget extends StatefulWidget { + final AbstractFilamentViewer controller; + + const IblRotationSliderWidget({super.key, required this.controller}); + @override + State createState() => _IblRotationSliderWidgetState(); +} + +class _IblRotationSliderWidgetState extends State { + double _iblRotation = 0; + @override + Widget build(BuildContext context) { + return Slider( + value: _iblRotation, + onChanged: (value) { + _iblRotation = value; + setState(() {}); + print(value); + var rotation = v.Matrix3.identity(); + Matrix4.rotationY(value * 2 * pi).copyRotation(rotation); + widget.controller.rotateIbl(rotation); + }); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/lights/light_slider.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/lights/light_slider.dart new file mode 100644 index 00000000..5cfdf158 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/lights/light_slider.dart @@ -0,0 +1,195 @@ +import 'dart:math'; + +import 'package:dart_filament/dart_filament/entities/filament_entity.dart'; +import 'package:dart_filament/dart_filament/filament_viewer_impl.dart'; +import 'package:dart_filament/dart_filament/utils/light_options.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +import 'package:vector_math/vector_math_64.dart' as v; + +class LightSliderWidget extends StatefulWidget { + final FilamentViewer controller; + + final LightOptions options; + final bool showControls; + + LightSliderWidget( + {super.key, + required this.controller, + this.showControls = false, + required this.options}); + @override + State createState() => _LightSliderWidgetState(); +} + +class _LightSliderWidgetState extends State { + FilamentEntity? _light; + + @override + void initState() { + _set(); + super.initState(); + } + + Future _set() async { + await widget.controller.clearLights(); + + if (widget.options.iblPath != null) { + _light = await widget.controller.loadIbl(widget.options.iblPath!, + intensity: widget.options.iblIntensity); + } + + _light = await widget.controller.addLight( + widget.options.directionalType, + widget.options.directionalColor, + widget.options.directionalIntensity, + widget.options.directionalPosition.x, + widget.options.directionalPosition.y, + widget.options.directionalPosition.z, + widget.options.directionalDirection.x, + widget.options.directionalDirection.y, + widget.options.directionalDirection.z, + widget.options.directionalCastShadows); + + setState(() {}); + } + + @override + Widget build(BuildContext context) { + if (_light == null || !widget.showControls) { + return Container(); + } + return Theme( + data: ThemeData(platform: TargetPlatform.android), + child: Container( + decoration: BoxDecoration(color: Colors.white.withOpacity(0.5)), + child: SliderTheme( + data: const SliderThemeData( + showValueIndicator: ShowValueIndicator.always, + valueIndicatorTextStyle: TextStyle(color: Colors.black)), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Text("Directional"), + Row(children: [ + Expanded( + child: Slider( + label: + "POSX ${widget.options.directionalPosition.x}", + value: widget.options.directionalPosition.x, + min: -10.0, + max: 10.0, + onChanged: (value) { + widget.options.directionalPosition.x = value; + _set(); + })), + Expanded( + child: Slider( + label: + "POSY ${widget.options.directionalPosition.y}", + value: widget.options.directionalPosition.y, + min: -100.0, + max: 100.0, + onChanged: (value) { + widget.options.directionalPosition.y = value; + _set(); + })), + Expanded( + child: Slider( + label: + "POSZ ${widget.options.directionalPosition.z}", + value: widget.options.directionalPosition.z, + min: -100.0, + max: 100.0, + onChanged: (value) { + widget.options.directionalPosition.z = value; + _set(); + })) + ]), + Row(children: [ + Expanded( + child: Slider( + label: "DIRX", + value: widget.options.directionalDirection.x, + min: -1.0, + max: 1.0, + onChanged: (value) { + widget.options.directionalDirection.x = value; + _set(); + })), + Expanded( + child: Slider( + label: "DIRY", + value: widget.options.directionalDirection.y, + min: -1.0, + max: 1.0, + onChanged: (value) { + widget.options.directionalDirection.y = value; + _set(); + })), + Expanded( + child: Slider( + label: "DIRZ", + value: widget.options.directionalDirection.z, + min: -1.0, + max: 1.0, + onChanged: (value) { + widget.options.directionalDirection.z = value; + _set(); + })) + ]), + Slider( + label: "Color", + value: widget.options.directionalColor, + min: 0, + max: 16000, + onChanged: (value) { + widget.options.directionalColor = value; + _set(); + }), + Slider( + label: "Intensity ${widget.options.directionalIntensity}", + value: widget.options.directionalIntensity, + min: 0, + max: 1000000, + onChanged: (value) { + widget.options.directionalIntensity = value; + _set(); + }), + DropdownButton( + onChanged: (v) { + this.widget.options.directionalType = v; + _set(); + }, + value: this.widget.options.directionalType, + items: List.generate( + 5, + (idx) => DropdownMenuItem( + value: idx, + child: Text("$idx"), + ))), + Row(children: [ + Text( + "Shadows: ${this.widget.options.directionalCastShadows}"), + Checkbox( + value: widget.options.directionalCastShadows, + onChanged: (v) { + this.widget.options.directionalCastShadows = v!; + _set(); + }) + ]), + Text("Indirect"), + Row(children: [ + Expanded( + child: Slider( + label: "Intensity ${widget.options.iblIntensity}", + value: widget.options.iblIntensity, + min: 0.0, + max: 200000, + onChanged: (value) { + widget.options.iblIntensity = value; + _set(); + })), + ]) + ])))); + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/resize_observer.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/resize_observer.dart new file mode 100644 index 00000000..218f84f1 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/resize_observer.dart @@ -0,0 +1,41 @@ +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +typedef ResizeCallback = void Function(Size newSize); + +class ResizeObserver extends SingleChildRenderObjectWidget { + final ResizeCallback onResized; + + const ResizeObserver({ + Key? key, + required this.onResized, + Widget? child, + }) : super( + key: key, + child: child, + ); + + @override + RenderObject createRenderObject(BuildContext context) => + _RenderResizeObserver(onLayoutChangedCallback: onResized); +} + +class _RenderResizeObserver extends RenderProxyBox { + final ResizeCallback onLayoutChangedCallback; + + _RenderResizeObserver({ + RenderBox? child, + required this.onLayoutChangedCallback, + }) : super(child); + + Size _oldSize = Size.zero; + + @override + void performLayout() async { + super.performLayout(); + if (size.width != _oldSize.width || size.height != _oldSize.height) { + onLayoutChangedCallback(size); + _oldSize = Size(size.width, size.height); + } + } +} diff --git a/flutter_filament_federated/flutter_filament/lib/filament/widgets/transparent_filament_widget.dart b/flutter_filament_federated/flutter_filament/lib/filament/widgets/transparent_filament_widget.dart new file mode 100644 index 00000000..c4037a17 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/filament/widgets/transparent_filament_widget.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +class TransparencyPainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + canvas.drawRect( + Rect.fromLTWH(0, 0, size.width, size.height), + Paint() + ..blendMode = BlendMode.clear + ..color = const Color(0x00000000), + ); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} diff --git a/flutter_filament_federated/flutter_filament/lib/flutter_filament.dart b/flutter_filament_federated/flutter_filament/lib/flutter_filament.dart new file mode 100644 index 00000000..be36dc47 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/lib/flutter_filament.dart @@ -0,0 +1,5 @@ +library flutter_filament; + +export 'filament/flutter_filament_plugin.dart'; +export 'package:dart_filament/dart_filament.dart'; + diff --git a/flutter_filament_federated/flutter_filament/linux/CMakeLists.txt b/flutter_filament_federated/flutter_filament/linux/CMakeLists.txt new file mode 100644 index 00000000..210e4b86 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/CMakeLists.txt @@ -0,0 +1,168 @@ +# The Flutter tooling requires that developers have CMake 3.10 or later +# installed. You should not increase this version, as doing so will cause +# the plugin to fail to compile for some customers of the plugin. +cmake_minimum_required(VERSION 3.10) + +# Project-level configuration. +set(PROJECT_NAME "flutter_filament") +project(${PROJECT_NAME}) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fPIC -Wno-unused-variable -Wno-unused-function") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -Wno-unused-variable -Wno-unused-function") + +# This value is used when generating builds using this plugin, so it must +# not be changed. +set(PLUGIN_NAME "flutter_filament_plugin") + +link_directories("${CMAKE_CURRENT_SOURCE_DIR}/lib") + +add_library(FILAMENT_SHADERS SHARED + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/include/material/image.c" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/include/material/unlit_opaque.c" +) + +# Define the plugin library target. Its name must not be changed (see comment +# on PLUGIN_NAME above). +# +# Any new source files that you add to the plugin should be added here. +add_library(${PLUGIN_NAME} SHARED + "flutter_filament_plugin.cc" + "filament_texture.cc" + "filament_pb_texture.cc" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/SceneManager.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FilamentViewer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FlutterFilamentApi.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/StreamBufferAdapter.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/TimeIt.cpp" +) + +# Apply a standard set of build settings that are configured in the +# application-level CMakeLists.txt. This can be removed for plugins that want +# full control over build settings. +apply_standard_settings(${PLUGIN_NAME}) + +# Symbols are hidden by default to reduce the chance of accidental conflicts +# between plugins. This should not be removed; any symbols that should be +# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) + +target_compile_features(${PLUGIN_NAME} PRIVATE cxx_std_17) + +add_compile_definitions(IS_DLL) + + +# Source include directories and library dependencies. Add any plugin-specific +# dependencies here. +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") + +include_directories(../ios/src) +include_directories(../ios/include) +include_directories(../example/linux) + +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) + +add_library(geometry STATIC IMPORTED) +set_property(TARGET geometry PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libgeometry.a") +add_library(filament STATIC IMPORTED) +set_property(TARGET filament PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libfilament.a") +add_library(backend STATIC IMPORTED) +set_property(TARGET backend PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libbackend.a") +add_library(filameshio STATIC IMPORTED) +set_property(TARGET filameshio PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libfilameshio.a") +add_library(filament_viewer STATIC IMPORTED) +set_property(TARGET filament_viewer PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libviewer.a") +add_library(filamat STATIC IMPORTED) +set_property(TARGET filamat PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libfilamat.a") +add_library(utils STATIC IMPORTED) +set_property(TARGET utils PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libutils.a") +add_library(filabridge STATIC IMPORTED) +set_property(TARGET filabridge PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libfilabridge.a") +add_library(gltfio_core STATIC IMPORTED) +set_property(TARGET gltfio_core PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libgltfio_core.a") +add_library(filament-iblprefilter STATIC IMPORTED) +set_property(TARGET filament-iblprefilter PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libfilament-iblprefilter.a") +add_library(image STATIC IMPORTED) +set_property(TARGET image PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimage.a") +add_library(camutils STATIC IMPORTED) +set_property(TARGET camutils PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libcamutils.a") +add_library(filaflat STATIC IMPORTED) +set_property(TARGET filaflat PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libfilaflat.a") +add_library(dracodec STATIC IMPORTED) +set_property(TARGET dracodec PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libdracodec.a") +add_library(ibl STATIC IMPORTED) +set_property(TARGET ibl PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libibl.a") +add_library(ktxreader STATIC IMPORTED) +set_property(TARGET ktxreader PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libktxreader.a") +add_library(imageio STATIC IMPORTED) +set_property(TARGET imageio PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimageio.a") +add_library(tinyexr STATIC IMPORTED) +set_property(TARGET tinyexr PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libtinyexr.a") +add_library(stb STATIC IMPORTED) +set_property(TARGET stb PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libstb.a") +add_library(bluevk STATIC IMPORTED) +set_property(TARGET bluevk PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libbluevk.a") +add_library(vkshaders STATIC IMPORTED) +set_property(TARGET vkshaders PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libvkshaders.a") +add_library(bluegl STATIC IMPORTED) +set_property(TARGET bluegl PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libbluegl.a") +add_library(uberzlib STATIC IMPORTED) +set_property(TARGET uberzlib PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libuberzlib.a") +add_library(smol-v STATIC IMPORTED) +set_property(TARGET smol-v PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libsmol-v.a") +add_library(uberarchive STATIC IMPORTED) +set_property(TARGET uberarchive PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libuberarchive.a") +add_library(meshoptimizer STATIC IMPORTED) +set_property(TARGET meshoptimizer PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libmeshoptimizer.a") +add_library(mathio STATIC IMPORTED) +set_property(TARGET mathio PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libmathio.a") +add_library(math STATIC IMPORTED) +set_property(TARGET math PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libmath.a") +add_library(basis_transcoder STATIC IMPORTED) +set_property(TARGET basis_transcoder PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libbasis_transcoder.a") + +target_link_libraries(${PLUGIN_NAME} PRIVATE + FILAMENT_SHADERS + gltfio_core + filament + backend + geometry + filameshio + filament_viewer + filamat + filabridge + filament-iblprefilter + camutils + filaflat + dracodec + ibl + ktxreader + imageio + image + utils + tinyexr + stb + bluevk + vkshaders + bluegl + uberzlib + smol-v + uberarchive + meshoptimizer + mathio + math + geometry + basis_transcoder +) + +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(flutter_filament_bundled_libraries + "" + PARENT_SCOPE + lib/libgeometry.a +) diff --git a/flutter_filament_federated/flutter_filament/linux/filament_pb_texture.cc b/flutter_filament_federated/flutter_filament/linux/filament_pb_texture.cc new file mode 100644 index 00000000..8a931ba8 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/filament_pb_texture.cc @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include "include/flutter_filament/filament_pb_texture.h" + +#include +#include + +// This was just an experiment for copying pixel buffers to Flutter. This won't actually render anything from Filament. +G_DEFINE_TYPE(FilamentPBTexture, + filament_pb_texture, + fl_pixel_buffer_texture_get_type()) + + +static gboolean video_texture_copy_pixels (FlPixelBufferTexture* texture, + const uint8_t** out_buffer, + uint32_t* width, + uint32_t* height, + GError** error) { + + auto buffer = new std::vector(width*height*4); + for (int i = 0; i < width*height*4; i++) + { + if(i%4 == 1 || i % 4 == 3) { + buffer->at(i) = (uint8_t)255; + } else { + buffer->at(i) = (uint8_t)0; + } + } + *width = width; + *height = height; + *out_buffer = buffer->data(); + std::cout << "COPYING PIXEL BUFFER" << std::endl; + return TRUE; +} + +void filament_pb_texture_dispose(GObject* object) { + G_OBJECT_CLASS(filament_pb_texture_parent_class)->dispose(object); +} + +void filament_pb_texture_class_init(FilamentPBTextureClass* klass) { + G_OBJECT_CLASS(klass)->dispose = filament_pb_texture_dispose; + FL_PIXEL_BUFFER_TEXTURE_CLASS(klass)->copy_pixels = video_texture_copy_pixels; +} + +void filament_pb_texture_init(FilamentPBTexture* self) { } + +FLUTTER_PLUGIN_EXPORT FlTexture* create_filament_pb_texture(uint32_t width, uint32_t height, FlTextureRegistrar* registrar) { + + auto pbTexture = FILAMENT_PB_TEXTURE(g_object_new(filament_pb_texture_get_type(), nullptr)); + + g_autoptr(FlTexture) texture = FL_TEXTURE(pbTexture); + + if(fl_texture_registrar_register_texture(registrar, texture) == TRUE) { + if(fl_texture_registrar_mark_texture_frame_available(registrar, + texture) != TRUE) { + std::cout << "FAILED" << std::endl; + } + } + return texture; +} \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/linux/filament_texture.cc b/flutter_filament_federated/flutter_filament/linux/filament_texture.cc new file mode 100644 index 00000000..8184b7e1 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/filament_texture.cc @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include + +#include +#include "include/flutter_filament/filament_texture.h" + +#include +#include + + +G_DEFINE_TYPE(FilamentTextureGL, + filament_texture_gl, + fl_texture_gl_get_type()) + +static gboolean +filament_texture_populate (FlTextureGL *texture, + uint32_t *target, + uint32_t *name, + uint32_t *width, + uint32_t *height, + GError **error) { + FilamentTextureGL *self = FILAMENT_TEXTURE_GL (texture); + *target = GL_TEXTURE_2D; + *name = self->texture_id; + *width = self->width; + *height = self->height; + return TRUE; +} + +void filament_texture_gl_dispose(GObject* object) { + auto filamentTextureGL = FILAMENT_TEXTURE_GL(object); + glDeleteTextures(1, &(filamentTextureGL->texture_id)); + filamentTextureGL->texture_id = 0; +} + +void filament_texture_gl_class_init(FilamentTextureGLClass* klass) { + G_OBJECT_CLASS(klass)->dispose = filament_texture_gl_dispose; + FL_TEXTURE_GL_CLASS(klass)->populate = filament_texture_populate; +} + +void filament_texture_gl_init(FilamentTextureGL* self) { } + +void destroy_filament_texture(FlTexture* texture, FlTextureRegistrar* registrar) { + fl_texture_registrar_unregister_texture(registrar, texture); +} + +FlTexture* create_filament_texture(uint32_t width, uint32_t height, FlTextureRegistrar* registrar) { + auto textureGL = FILAMENT_TEXTURE_GL(g_object_new(filament_texture_gl_get_type(), nullptr)); + textureGL->width = width; + textureGL->height = height; + textureGL->registrar = registrar; + + g_autoptr(FlTexture) texture = FL_TEXTURE(textureGL); + + glGenTextures(1, &textureGL->texture_id); + + glBindTexture(GL_TEXTURE_2D, textureGL->texture_id); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, textureGL->width, textureGL->height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, 0); + + if(fl_texture_registrar_register_texture(registrar, texture) == TRUE) { + + if(fl_texture_registrar_mark_texture_frame_available(registrar, + texture) != TRUE) { + std::cout << "FAILED" << std::endl; + return nullptr; + } + } + return texture; +} \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/linux/flutter_filament_plugin.cc b/flutter_filament_federated/flutter_filament/linux/flutter_filament_plugin.cc new file mode 100644 index 00000000..69055014 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/flutter_filament_plugin.cc @@ -0,0 +1,889 @@ +#include "include/flutter_filament/flutter_filament_plugin.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "include/flutter_filament/filament_texture.h" +#include "include/flutter_filament/filament_pb_texture.h" +#include "include/flutter_filament/resource_loader.hpp" + +#include "FilamentViewer.hpp" +#include "Log.hpp" + +extern "C" { +#include "FlutterFilamentApi.h" +} + +#include +#include + +#define FLUTTER_FILAMENT_PLUGIN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), flutter_filament_plugin_get_type(), \ + FlutterFilamentPlugin)) + + +struct _FlutterFilamentPlugin { + GObject parent_instance; + FlTextureRegistrar* texture_registrar; + FlView* fl_view; + FlTexture* texture; + double width = 0; + double height = 0; + bool rendering = false; + flutter_filament::FilamentViewer* viewer; +}; + +G_DEFINE_TYPE(FlutterFilamentPlugin, flutter_filament_plugin, g_object_get_type()) + +static gboolean on_frame_tick(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer self) { + FlutterFilamentPlugin* plugin = (FlutterFilamentPlugin*)self; + + if(plugin->rendering) { + render(plugin->viewer, 0); + fl_texture_registrar_mark_texture_frame_available(plugin->texture_registrar, + plugin->texture); + } + return TRUE; +} + +static FlMethodResponse* _create_filament_viewer(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + auto callback = new ResourceLoaderWrapper(loadResource, freeResource); + + FlValue* args = fl_method_call_get_args(method_call); + + const double width = fl_value_get_float(fl_value_get_list_value(args, 0)); + const double height = fl_value_get_float(fl_value_get_list_value(args, 1)); + + self->width = width; + self->height = height; + + auto context = glXGetCurrentContext(); + self->viewer = (flutter_filament::FilamentViewer*)create_filament_viewer( + (void*)context, + callback + ); + + GtkWidget *w = gtk_widget_get_toplevel (GTK_WIDGET(self->fl_view)); + gtk_widget_add_tick_callback(w, on_frame_tick, self,NULL); + + // don't pass a surface to the SwapChain as we are effectively creating a headless SwapChain that will render into a RenderTarget associated with a texture + create_swap_chain(self->viewer, nullptr, width, height); + create_render_target(self->viewer, ((FilamentTextureGL*)self->texture)->texture_id,width,height); + update_viewport_and_camera_projection(self->viewer, width, height, 1.0f); + + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(self->viewer)); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _create_texture(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + if(self->texture) { + Log("Error - create_texture called when texture exists."); + } + + FlValue* args = fl_method_call_get_args(method_call); + + const double width = fl_value_get_float(fl_value_get_list_value(args, 0)); + const double height = fl_value_get_float(fl_value_get_list_value(args, 1)); + + self->width = width; + self->height = height; + + auto texture = create_filament_texture(uint32_t(width), uint32_t(height), self->texture_registrar); + //auto texture = create_filament_pb_texture(uint32_t(width), uint32_t(height), self->texture_registrar); + self->texture = texture; + + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(texture)); + + Log("Successfully created texture."); + + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + + +static FlMethodResponse* _update_viewport_and_camera_projection(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + + auto width = fl_value_get_int(fl_value_get_list_value(args, 0)); + auto height = fl_value_get_int(fl_value_get_list_value(args, 1)); + auto scaleFactor = fl_value_get_float(fl_value_get_list_value(args, 2)); + + update_viewport_and_camera_projection(self->viewer, width, height, scaleFactor); + + return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_bool(true))); +} + + +static FlMethodResponse* _get_asset_manager(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + auto assetManager = get_asset_manager(self->viewer); + return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_int(reinterpret_cast(assetManager)))); +} + +static FlMethodResponse* _resize(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + + const double width = fl_value_get_float(fl_value_get_list_value(args, 0)); + const double height = fl_value_get_float(fl_value_get_list_value(args, 1)); + + destroy_filament_texture(self->texture, self->texture_registrar); + + self->texture = create_filament_texture(uint32_t(width), uint32_t(height), self->texture_registrar); + + create_swap_chain(self->viewer, nullptr, width, height); + create_render_target(self->viewer, ((FilamentTextureGL*)self->texture)->texture_id,width,height); + + update_viewport_and_camera_projection(self->viewer, width, height, 1.0f); + + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(self->texture)); + + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _loadSkybox(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + + const gchar* path = fl_value_get_string(args); + + load_skybox(self->viewer, path); + + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _remove_ibl(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + remove_ibl(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _loadIbl(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + + auto path = fl_value_get_string(fl_value_get_list_value(args, 0)); + auto intensity = fl_value_get_float(fl_value_get_list_value(args, 1)); + + load_ibl(self->viewer, path, intensity); + + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _removeSkybox(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + std::cout << "Removing skybox" << std::endl; + remove_skybox(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_background_image(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + + FlValue* args = fl_method_call_get_args(method_call); + + const gchar* path = fl_value_get_string(args); + + set_background_image(self->viewer, path); + + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_background_color(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + const float r = fl_value_get_float(fl_value_get_list_value(args, 0)); + const float g = fl_value_get_float(fl_value_get_list_value(args, 1)); + const float b = fl_value_get_float(fl_value_get_list_value(args, 2)); + const float a = fl_value_get_float(fl_value_get_list_value(args, 3)); + set_background_color(self->viewer, r,g,b,a); + + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _add_light(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + + FlValue* args = fl_method_call_get_args(method_call); + + auto type = (uint8_t)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto color = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + auto intensity = float(fl_value_get_float(fl_value_get_list_value(args, 2))); + auto posX = (float)fl_value_get_float(fl_value_get_list_value(args, 3)); + auto posY = (float)fl_value_get_float(fl_value_get_list_value(args, 4)); + auto posZ = (float)fl_value_get_float(fl_value_get_list_value(args, 5)); + auto dirX = (float)fl_value_get_float(fl_value_get_list_value(args, 6)); + auto dirY = (float)fl_value_get_float(fl_value_get_list_value(args, 7)); + auto dirZ = (float)fl_value_get_float(fl_value_get_list_value(args, 8)); + auto shadows = fl_value_get_bool(fl_value_get_list_value(args, 9)); + + auto entityId = add_light(self->viewer, type, color, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows); + g_autoptr(FlValue) result = fl_value_new_int(entityId); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + +} + +static FlMethodResponse* _load_glb(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto path = fl_value_get_string(fl_value_get_list_value(args, 1)); + auto unlit = fl_value_get_bool(fl_value_get_list_value(args, 2)); + auto entityId = load_glb(assetManager, path, unlit); + g_autoptr(FlValue) result = fl_value_new_int((int64_t)entityId); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _get_animation_names(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + g_autoptr(FlValue) result = fl_value_new_list(); + + auto numNames = get_animation_count(assetManager, asset); + + for(int i = 0; i < numNames; i++) { + gchar out[255]; + get_animation_name(assetManager, asset, out, i); + fl_value_append_take (result, fl_value_new_string (out)); + } + + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _remove_asset(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + remove_asset(self->viewer, asset); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _transform_to_unit_cube(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + transform_to_unit_cube(assetManager, asset); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _rotate_start(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + + grab_begin(self->viewer, x,y, false); + + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _rotate_end(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + grab_end(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _rotate_update(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + + grab_update(self->viewer, x,y); + + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _pan_start(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + + FlValue* args = fl_method_call_get_args(method_call); + + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + + grab_begin(self->viewer, x,y, true); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _pan_update(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + + grab_update(self->viewer, x,y); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _pan_end(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + grab_end(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_position(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + + set_position( + assetManager, + asset, + (float)fl_value_get_float(fl_value_get_list_value(args, 2)), // x + (float)fl_value_get_float(fl_value_get_list_value(args, 3)), // y + (float)fl_value_get_float(fl_value_get_list_value(args, 4)) // z + ); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_rotation(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + + set_rotation( + assetManager, + asset, + (float)fl_value_get_float(fl_value_get_list_value(args, 2)), // rads + (float)fl_value_get_float(fl_value_get_list_value(args, 3)), // x + (float)fl_value_get_float(fl_value_get_list_value(args, 4)), // y + (float)fl_value_get_float(fl_value_get_list_value(args, 5 )) // z + ); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + + + +static FlMethodResponse* _set_bone_transform(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + throw std::invalid_argument( "received negative value" ); + // FlValue* args = fl_method_call_get_args(method_call); + // auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + // auto boneName = fl_value_get_string(fl_value_get_list_value(args, 1)); + // auto meshName = fl_value_get_string(fl_value_get_list_value(args, 2)); + + // set_bone_transform( + // assetPtr, + // boneName, + // meshName, + // (float)fl_value_get_float(fl_value_get_list_value(args, 3)), // transX + // (float)fl_value_get_float(fl_value_get_list_value(args, 4)), // transY + // (float)fl_value_get_float(fl_value_get_list_value(args, 5)), // transZ + // (float)fl_value_get_float(fl_value_get_list_value(args, 6)), // quatX + // (float)fl_value_get_float(fl_value_get_list_value(args, 7)), // quatY + // (float)fl_value_get_float(fl_value_get_list_value(args, 8)), // quatZ + // (float)fl_value_get_float(fl_value_get_list_value(args, 9)) // quatW + // ); + // g_autoptr(FlValue) result = fl_value_new_string("OK"); + // return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_camera(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto cameraName = fl_value_get_string(fl_value_get_list_value(args, 1)) ; + + set_camera(self->viewer, asset, cameraName); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_camera_model_matrix(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + set_camera_model_matrix(self->viewer, fl_value_get_float32_list(args)); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_camera_exposure(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto aperture = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto shutter_speed = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + auto sensitivity = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); + set_camera_exposure(self->viewer, aperture, shutter_speed, sensitivity); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_camera_position(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); + set_camera_position(self->viewer, x,y, z); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_camera_rotation(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto rads = (float)fl_value_get_float(fl_value_get_list_value(args,0 )); + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); + auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 3)); + + set_camera_rotation(self->viewer, rads, x,y, z); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_rendering(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + self->rendering = (bool)fl_value_get_bool(args); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_frame_interval(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto val = (float) fl_value_get_float(args); + set_frame_interval(self->viewer, val); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _grab_begin(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + auto pan = (bool)fl_value_get_bool(fl_value_get_list_value(args, 2)); + grab_begin(self->viewer, x, y, pan); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _grab_end(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + grab_end(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _grab_update(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + + grab_update(self->viewer, x,y); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _scroll_begin(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + scroll_begin(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _scroll_end(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + scroll_end(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _scroll_update(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); + auto y = (float)fl_value_get_float(fl_value_get_list_value(args, 1)); + auto z = (float)fl_value_get_float(fl_value_get_list_value(args, 2)); + + scroll_update(self->viewer, x,y, z); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _play_animation(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + auto animationId = (int)fl_value_get_int(fl_value_get_list_value(args, 2)); + auto loop = (bool)fl_value_get_bool(fl_value_get_list_value(args, 3)); + auto reverse = (bool)fl_value_get_bool(fl_value_get_list_value(args, 4)); + auto replaceActive = (bool)fl_value_get_bool(fl_value_get_list_value(args, 5)); + auto crossfade = (bool)fl_value_get_float(fl_value_get_list_value(args, 6)); + play_animation(assetManager, asset, animationId, loop, reverse, replaceActive, crossfade); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + + +static FlMethodResponse* _stop_animation(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + auto animationId = (int)fl_value_get_int(fl_value_get_list_value(args, 2)); + stop_animation(assetManager, asset, animationId); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + + +static FlMethodResponse* _set_morph_target_weights(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + auto entityName = fl_value_get_string(fl_value_get_list_value(args, 2)); + auto flWeights = fl_value_get_list_value(args, 3); + size_t numWeights = fl_value_get_length(flWeights); + + std::vector weights(numWeights); + for(int i =0; i < numWeights; i++) { + float val = fl_value_get_float(fl_value_get_list_value(flWeights, i)); + weights[i] = val; + } + + set_morph_target_weights(assetManager, asset, entityName, weights.data(), (int)numWeights); + + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +template class std::vector; + +static FlMethodResponse* _set_morph_animation(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + auto entityName = fl_value_get_string(fl_value_get_list_value(args, 2)); + + auto morphDataList = fl_value_get_list_value(args, 3); + auto morphDataListLength = fl_value_get_length(morphDataList); + auto morphData = std::vector(morphDataListLength); + + for(int i =0; i < morphDataListLength; i++) { + morphData[i] = fl_value_get_float(fl_value_get_list_value(morphDataList, i)); + } + + auto morphIndicesList = fl_value_get_list_value(args, 4); + auto morphIndicesListLength = fl_value_get_length(morphIndicesList); + auto indices = std::vector(morphIndicesListLength); + + for(int i =0; i < morphIndicesListLength; i++) { + FlValue* flMorphIndex = fl_value_get_list_value(morphIndicesList, i); + indices[i] = static_cast(fl_value_get_int(flMorphIndex)); + } + + int64_t numMorphTargets = fl_value_get_int(fl_value_get_list_value(args, 5)); + int64_t numFrames = fl_value_get_int(fl_value_get_list_value(args, 6)); + float frameLengthInMs = fl_value_get_float(fl_value_get_list_value(args, 7)); + + bool success = set_morph_animation( + assetManager, + asset, + (const char *const)entityName, + (const float *const)morphData.data(), + (const int* const)indices.data(), + static_cast(numMorphTargets), + static_cast(numFrames), + frameLengthInMs + ); + g_autoptr(FlValue) result = fl_value_new_bool(success); + + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_animation(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + throw std::invalid_argument( "received negative value" ); + // FlValue* args = fl_method_call_get_args(method_call); + // auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + + // const char* entityName = fl_value_get_string(fl_value_get_list_value(args, 1)); + + // float* const morphData = (float* const) fl_value_get_float32_list(fl_value_get_list_value(args, 2)); + + // int64_t numMorphWeights = fl_value_get_int(fl_value_get_list_value(args, 3)); + + // FlValue* flBoneAnimations = fl_value_get_list_value(args, 4); + + // size_t numBoneAnimations = fl_value_get_length(flBoneAnimations); + + // vector boneAnimations; + + // for(int i = 0; i < numBoneAnimations; i++) { + + // FlValue* flBoneAnimation = fl_value_get_list_value(flBoneAnimations, i); + + // FlValue* flBoneNames = fl_value_get_list_value(flBoneAnimation, 0); + // FlValue* flMeshNames = fl_value_get_list_value(flBoneAnimation, 1); + // float* const frameData = (float* const) fl_value_get_float32_list(fl_value_get_list_value(flBoneAnimation, 2)); + + // Log("Framedata %f", frameData); + + // vector boneNames; + // boneNames.resize(fl_value_get_length(flBoneNames)); + + // for(int i=0; i < boneNames.size(); i++) { + // boneNames[i] = fl_value_get_string(fl_value_get_list_value(flBoneNames, i)) ; + // } + + // vector meshNames; + // meshNames.resize(fl_value_get_length(flMeshNames)); + // for(int i=0; i < meshNames.size(); i++) { + // meshNames[i] = fl_value_get_string(fl_value_get_list_value(flMeshNames, i)); + // } + + // const char** boneNamesPtr = (const char**)malloc(boneNames.size() * sizeof(char*)); + // memcpy((void*)boneNamesPtr, (void*)boneNames.data(), boneNames.size() * sizeof(char*)); + // auto meshNamesPtr = (const char**)malloc(meshNames.size() * sizeof(char*)); + // memcpy((void*)meshNamesPtr, (void*)meshNames.data(), meshNames.size() * sizeof(char*)); + + // BoneAnimation animation { + // .boneNames = boneNamesPtr, + // .meshNames = meshNamesPtr, + // .data = frameData, + // .numBones = boneNames.size(), + // .numMeshTargets = meshNames.size() + // }; + + // boneAnimations.push_back(animation); + + // } + + // int64_t numFrames = fl_value_get_int(fl_value_get_list_value(args, 5)); + + // float frameLengthInMs = fl_value_get_float(fl_value_get_list_value(args, 6)); + + // auto boneAnimationsPointer = boneAnimations.data(); + // auto boneAnimationsSize = boneAnimations.size(); + + // set_animation( + // assetPtr, + // entityName, + // morphData, + // numMorphWeights, + // boneAnimationsPointer, + // boneAnimationsSize, + // numFrames, + // frameLengthInMs); + + // g_autoptr(FlValue) result = fl_value_new_string("OK"); + // return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _get_morph_target_names(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetManager = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + auto asset = (EntityId)fl_value_get_int(fl_value_get_list_value(args, 1)); + auto meshName = fl_value_get_string(fl_value_get_list_value(args, 2)); + + g_autoptr(FlValue) result = fl_value_new_list(); + + auto numNames = get_morph_target_name_count(assetManager, asset, meshName); + + for(int i = 0; i < numNames; i++) { + gchar out[255]; + get_morph_target_name(assetManager, asset, meshName, out, i); + fl_value_append_take (result, fl_value_new_string (out)); + } + + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + +static FlMethodResponse* _set_tone_mapping(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + flutter_filament::ToneMapping toneMapping = static_cast(fl_value_get_int(args)); + set_tone_mapping(self->viewer, toneMapping); + return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_bool(true))); +} + +static FlMethodResponse* _set_bloom(FlutterFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + set_bloom(self->viewer, fl_value_get_float(args)); + return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_bool(true))); +} + +// Called when a method call is received from Flutter. +static void flutter_filament_plugin_handle_method_call( + FlutterFilamentPlugin* self, + FlMethodCall* method_call) { + + g_autoptr(FlMethodResponse) response = nullptr; + + const gchar* method = fl_method_call_get_name(method_call); + + if(strcmp(method, "createFilamentViewer") == 0) { + response = _create_filament_viewer(self, method_call); + } else if(strcmp(method, "createTexture") == 0) { + response = _create_texture(self, method_call); + } else if(strcmp(method, "updateViewportAndCameraProjection")==0){ + response = _update_viewport_and_camera_projection(self, method_call); + } else if(strcmp(method, "getAssetManager") ==0){ + response = _get_asset_manager(self, method_call); + } else if(strcmp(method, "setToneMapping") == 0) { + response = _set_tone_mapping(self, method_call); + } else if(strcmp(method, "setBloom") == 0) { + response = _set_bloom(self, method_call); + } else if(strcmp(method, "resize") == 0) { + response = _resize(self, method_call); + } else if(strcmp(method, "getContext") == 0) { + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(glXGetCurrentContext())); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "getGlTextureId") == 0) { + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(((FilamentTextureGL*)self->texture)->texture_id)); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "getResourceLoader") == 0) { + ResourceLoaderWrapper* resourceLoader = new ResourceLoaderWrapper(loadResource, freeResource); + g_autoptr(FlValue) result = + fl_value_new_int(reinterpret_cast(resourceLoader)); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "setRendering") == 0) { + self->rendering = fl_value_get_bool(fl_method_call_get_args(method_call)); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_string("OK"))); + } else if(strcmp(method, "loadSkybox") == 0) { + response = _loadSkybox(self, method_call); + } else if(strcmp(method, "loadIbl") == 0) { + response = _loadIbl(self, method_call); + } else if(strcmp(method, "removeIbl") ==0) { + response = _remove_ibl(self, method_call); + } else if(strcmp(method, "removeSkybox") == 0) { + response = _removeSkybox(self, method_call); + } else if(strcmp(method, "render") == 0) { + render(self->viewer, 0); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "setBackgroundColor") == 0) { + response = _set_background_color(self, method_call); + } else if(strcmp(method, "setBackgroundImage") == 0) { + response = _set_background_image(self, method_call); + } else if(strcmp(method, "addLight") == 0) { + response = _add_light(self, method_call); + } else if(strcmp(method, "loadGlb") == 0) { + response = _load_glb(self, method_call); + } else if(strcmp(method, "getAnimationNames") == 0) { + response = _get_animation_names(self, method_call); + } else if(strcmp(method, "clearAssets") == 0) { + clear_assets(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "removeAsset") == 0) { + response = _remove_asset(self, method_call); + } else if(strcmp(method, "transformToUnitCube") == 0) { + response = _transform_to_unit_cube(self, method_call); + } else if(strcmp(method, "clearLights") == 0) { + clear_lights(self->viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else if(strcmp(method, "panStart") == 0) { + response = _pan_start(self, method_call); + } else if(strcmp(method, "panEnd") == 0) { + response = _pan_end(self, method_call); + } else if(strcmp(method, "panUpdate") == 0) { + response = _pan_update(self, method_call); + } else if(strcmp(method, "rotateStart") == 0) { + response = _rotate_start(self, method_call); + } else if(strcmp(method, "rotateEnd") == 0) { + response = _rotate_end(self, method_call); + } else if(strcmp(method, "rotateUpdate") == 0) { + response = _rotate_update(self, method_call); + } else if(strcmp(method, "setRotation") == 0) { + response = _set_rotation(self, method_call); + } else if(strcmp(method, "setCamera") == 0) { + response = _set_camera(self, method_call); + } else if(strcmp(method, "setCameraModelMatrix") == 0) { + response = _set_camera_model_matrix(self, method_call); + } else if(strcmp(method, "setCameraExposure") == 0) { + response = _set_camera_exposure(self, method_call); + } else if(strcmp(method, "setCameraPosition") == 0) { + response = _set_camera_position(self, method_call); + } else if(strcmp(method, "setCameraRotation") == 0) { + response = _set_camera_rotation(self, method_call); + } else if(strcmp(method, "setFrameInterval") == 0) { + response = _set_frame_interval(self, method_call); + } else if(strcmp(method, "scrollBegin") == 0) { + response = _scroll_begin(self, method_call); + } else if(strcmp(method, "scrollEnd") == 0) { + response = _scroll_end(self, method_call); + } else if(strcmp(method, "scrollUpdate") == 0) { + response = _scroll_update(self, method_call); + } else if(strcmp(method, "grabBegin") == 0) { + response = _grab_begin(self, method_call); + } else if(strcmp(method, "grabEnd") == 0) { + response = _grab_end(self, method_call); + } else if(strcmp(method, "grabUpdate") == 0) { + response = _grab_update(self, method_call); + } else if(strcmp(method, "playAnimation") == 0) { + response = _play_animation(self, method_call); + } else if(strcmp(method, "stopAnimation") == 0) { + response = _stop_animation(self, method_call); + } else if(strcmp(method, "setMorphTargetWeights") == 0) { + response = _set_morph_target_weights(self, method_call); + } else if(strcmp(method, "setMorphAnimation") == 0) { + response = _set_morph_animation(self, method_call); + } else if(strcmp(method, "getMorphTargetNames") == 0) { + response = _get_morph_target_names(self, method_call); + } else if(strcmp(method, "setPosition") == 0) { + response = _set_position(self, method_call); + } else if(strcmp(method, "setBoneTransform") == 0) { + response = _set_bone_transform(self, method_call); + } else { + response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); + } + + fl_method_call_respond(method_call, response, nullptr); + +} + +static void flutter_filament_plugin_dispose(GObject* object) { + G_OBJECT_CLASS(flutter_filament_plugin_parent_class)->dispose(object); +} + +static void flutter_filament_plugin_class_init(FlutterFilamentPluginClass* klass) { + G_OBJECT_CLASS(klass)->dispose = flutter_filament_plugin_dispose; +} + +static void flutter_filament_plugin_init(FlutterFilamentPlugin* self) {} + +static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + FlutterFilamentPlugin* plugin = FLUTTER_FILAMENT_PLUGIN(user_data); + flutter_filament_plugin_handle_method_call(plugin, method_call); +} + +void flutter_filament_plugin_register_with_registrar(FlPluginRegistrar* registrar) { + FlutterFilamentPlugin* plugin = FLUTTER_FILAMENT_PLUGIN( + g_object_new(flutter_filament_plugin_get_type(), nullptr)); + + FlView* fl_view = fl_plugin_registrar_get_view(registrar); + plugin->fl_view = fl_view; + + plugin->texture_registrar = + fl_plugin_registrar_get_texture_registrar(registrar); + + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); + g_autoptr(FlMethodChannel) channel = + fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), + "app.polyvox.filament/event", + FL_METHOD_CODEC(codec)); + fl_method_channel_set_method_call_handler(channel, method_call_cb, + g_object_ref(plugin), + g_object_unref); + + g_object_unref(plugin); +} + + + + + + + + \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/linux/flutter_filament_plugin_private.h b/flutter_filament_federated/flutter_filament/linux/flutter_filament_plugin_private.h new file mode 100644 index 00000000..3b008af0 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/flutter_filament_plugin_private.h @@ -0,0 +1,10 @@ +#include + +#include "include/flutter_filament/flutter_filament_plugin.h" + +// This file exposes some plugin internals for unit testing. See +// https://github.com/flutter/flutter/issues/88724 for current limitations +// in the unit-testable API. + +// Handles the getPlatformVersion method call. +FlMethodResponse *get_platform_version(); diff --git a/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/filament_pb_texture.h b/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/filament_pb_texture.h new file mode 100644 index 00000000..6decb3b4 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/filament_pb_texture.h @@ -0,0 +1,44 @@ +#ifndef FILAMENT_PB_TEXTURE_H +#define FILAMENT_PB_TEXTURE_H +#include +#include +#include +#include +#include +#include +#include + + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define FLUTTER_PLUGIN_EXPORT +#endif + + +G_BEGIN_DECLS + +#define FILAMENT_PB_TEXTURE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), filament_pb_texture_get_type(), \ + FilamentPBTexture)) + +struct _FilamentPBTexture { + FlPixelBufferTexture parent_instance; +}; + +typedef struct _FilamentPBTexture FilamentPBTexture; +typedef struct { + FlPixelBufferTextureClass parent_instance; + gboolean (*copy_pixels)(FlPixelBufferTexture* texture, + const uint8_t** buffer, + uint32_t* width, + uint32_t* height, + GError** error); + +} FilamentPBTextureClass; + +G_END_DECLS + +FLUTTER_PLUGIN_EXPORT FlTexture* create_filament_pb_texture(uint32_t width, uint32_t height, FlTextureRegistrar* registrar); + +#endif \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/filament_texture.h b/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/filament_texture.h new file mode 100644 index 00000000..2db13c43 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/filament_texture.h @@ -0,0 +1,49 @@ +#ifndef FILAMENT_TEXTURE_H +#define FILAMENT_TEXTURE_H +#include +#include +#include +#include +#include +#include + + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define FLUTTER_PLUGIN_EXPORT +#endif + + +G_BEGIN_DECLS + +#define FILAMENT_TEXTURE_GL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), filament_texture_gl_get_type(), \ + FilamentTextureGL)) + +struct _FilamentTextureGL { + FlTextureGL parent_instance; + GLuint texture_id; + uint32_t width; + uint32_t height; + FlTextureRegistrar* registrar; +}; + +typedef struct _FilamentTextureGL FilamentTextureGL; +typedef struct { + FlTextureGLClass parent_instance; + gboolean (*populate)(FlTextureGL* texture, + uint32_t* target, + uint32_t* name, + uint32_t* width, + uint32_t* height, + GError** error); + GLuint texture_id; +} FilamentTextureGLClass; + +G_END_DECLS + +FLUTTER_PLUGIN_EXPORT FlTexture* create_filament_texture(uint32_t width, uint32_t height, FlTextureRegistrar* registrar); +FLUTTER_PLUGIN_EXPORT void destroy_filament_texture(FlTexture* texture, FlTextureRegistrar* registrar); + +#endif \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/flutter_filament_plugin.h b/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/flutter_filament_plugin.h new file mode 100644 index 00000000..514ee05a --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/flutter_filament_plugin.h @@ -0,0 +1,27 @@ +#ifndef FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ +#define FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ + +#include +#include + +G_BEGIN_DECLS + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define FLUTTER_PLUGIN_EXPORT +#endif + +typedef struct _FlutterFilamentPlugin FlutterFilamentPlugin; +typedef struct { + GObjectClass parent_class; +} FlutterFilamentPluginClass; + +FLUTTER_PLUGIN_EXPORT GType flutter_filament_plugin_get_type(); + +FLUTTER_PLUGIN_EXPORT void flutter_filament_plugin_register_with_registrar( + FlPluginRegistrar* registrar); + +G_END_DECLS + +#endif // FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ diff --git a/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/resource_loader.hpp b/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/resource_loader.hpp new file mode 100644 index 00000000..2ba1af5e --- /dev/null +++ b/flutter_filament_federated/flutter_filament/linux/include/flutter_filament/resource_loader.hpp @@ -0,0 +1,70 @@ +#ifndef FLUTTER_FILAMENT_LINUX_RESOURCE_LOADER_H +#define FLUTTER_FILAMENT_LINUX_RESOURCE_LOADER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ResourceBuffer.hpp" + + +static std::map _file_assets; +static uint32_t _i = 0; + +ResourceBuffer loadResource(const char* name) { + + std::cout << "LOADING RESOURCE" << std::endl; + + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + std::cout << "Current working dir: " << cwd << std::endl; + } + + string name_str(name); + auto id = _i++; + + // this functions accepts URIs, so + // - file:// points to a file on the filesystem + // - asset:// points to an asset, usually resolved relative to the current working directory + // - no prefix is presumed to be an asset + if (name_str.rfind("file://", 0) == 0) { + name_str = name_str.substr(7); + } else if(name_str.rfind("asset://", 0) == 0) { + name_str = name_str.substr(7); + name_str = string(cwd) + string("/") + name_str; + } else { + name_str = string(cwd) + string("/build/linux/x64/debug/bundle/data/flutter_assets/") + name_str; + } + + std::cout << "Loading resource at " << name_str.c_str() << std::endl; + + streampos length; + ifstream is(name_str, ios::binary); + if(!is) { + std::cout << "Failed to find resource at file path " << name_str.c_str() << std::endl; + return ResourceBuffer(nullptr, 0, -1); + } + is.seekg (0, ios::end); + length = is.tellg(); + char * buffer; + buffer = new char [length]; + is.seekg (0, ios::beg); + is.read (buffer, length); + is.close(); + _file_assets[id] = buffer; + return ResourceBuffer(buffer, length, id); +} + +void freeResource(ResourceBuffer rbuf) { + auto it = _file_assets.find(rbuf.id); + if (it != _file_assets.end()) { + free(it->second); + } +} + +#endif \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/macos/Classes/DartFilamentTexture.swift b/flutter_filament_federated/flutter_filament/macos/Classes/DartFilamentTexture.swift new file mode 100644 index 00000000..61089235 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/macos/Classes/DartFilamentTexture.swift @@ -0,0 +1,102 @@ +import Foundation +import GLKit + +@objc public class DartFilamentTexture : NSObject { + + public var pixelBuffer: CVPixelBuffer? + + var pixelBufferAttrs = [ + kCVPixelBufferPixelFormatTypeKey: NSNumber(value: kCVPixelFormatType_32ABGR ), + kCVPixelBufferIOSurfacePropertiesKey: [:] as CFDictionary + ] as [CFString : Any] as CFDictionary + + @objc public var cvMetalTextureCache:CVMetalTextureCache? + @objc public var cvMetalTexture:CVMetalTexture? + @objc public var metalTexture:MTLTexture? + @objc public var metalDevice:MTLDevice? + @objc public var metalTextureAddress:Int = -1 + + @objc override public init() { + + } + + @objc public init(width:Int64, height:Int64) { + + self.metalDevice = MTLCreateSystemDefaultDevice()! + + // create pixel buffer + if(CVPixelBufferCreate(kCFAllocatorDefault, Int(width), Int(height), + kCVPixelFormatType_32BGRA, pixelBufferAttrs, &pixelBuffer) != kCVReturnSuccess) { + print("Error allocating pixel buffer") + metalTextureAddress = -1; + return + } + + var cvret = CVMetalTextureCacheCreate( + kCFAllocatorDefault, + nil, + metalDevice!, + nil, + &cvMetalTextureCache); + if(cvret != 0) { + print("Error creating Metal texture cache") + metalTextureAddress = -1 + return + } + cvret = CVMetalTextureCacheCreateTextureFromImage( + kCFAllocatorDefault, + cvMetalTextureCache!, + pixelBuffer!, nil, + MTLPixelFormat.bgra8Unorm, + Int(width), Int(height), + 0, + &cvMetalTexture) + if(cvret != 0) { + print("Error creating texture from image") + metalTextureAddress = -1 + return + } + metalTexture = CVMetalTextureGetTexture(cvMetalTexture!) + let metalTexturePtr = Unmanaged.passUnretained(metalTexture!).toOpaque() + metalTextureAddress = Int(bitPattern:metalTexturePtr) + + print("Created metal texture @ \(metalTextureAddress)") + + // CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0)) + // let bufferWidth = Int(CVPixelBufferGetWidth(pixelBuffer!)) + // let bufferHeight = Int(CVPixelBufferGetHeight(pixelBuffer!)) + // let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer!) + + // guard let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer!) else { + // return + // } + + // for row in 0.. Unmanaged? { + return Unmanaged.passRetained(pixelBuffer!); + } + + public func onTextureUnregistered(_ texture:FlutterTexture) { + print("Texture unregistered") + } + + public func destroy() { + self.registry.unregisterTexture(self.flutterTextureId) + self.destroyTexture() + } + +} \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/macos/Classes/SwiftFlutterFilamentPlugin.swift b/flutter_filament_federated/flutter_filament/macos/Classes/SwiftFlutterFilamentPlugin.swift new file mode 100644 index 00000000..e6217c2d --- /dev/null +++ b/flutter_filament_federated/flutter_filament/macos/Classes/SwiftFlutterFilamentPlugin.swift @@ -0,0 +1,115 @@ +import FlutterMacOS +import GLKit + +public class SwiftFlutterFilamentPlugin: NSObject, FlutterPlugin { + + var registrar : FlutterPluginRegistrar + var registry: FlutterTextureRegistry + var texture: FlutterFilamentTexture? + + var createdAt = Date() + + var resources:[UInt32:NSData] = [:] + + static var messenger : FlutterBinaryMessenger? = nil; + + var loadResource : @convention(c) (UnsafePointer?, UnsafeMutableRawPointer?) -> ResourceBuffer = { uri, resourcesPtr in + + let instance:SwiftFlutterFilamentPlugin = Unmanaged.fromOpaque(resourcesPtr!).takeUnretainedValue() + + var uriString = String(cString:uri!) + + var path:String? = nil + + print("Received request to load \(uriString)") + + if(uriString.hasPrefix("file://")) { + path = String(uriString.dropFirst(7)) + } else { + if(uriString.hasPrefix("asset://")) { + uriString = String(uriString.dropFirst(8)) + } + let bundle = Bundle.init(identifier: "io.flutter.flutter.app")! + path = bundle.path(forResource:uriString, ofType: nil, inDirectory: "flutter_assets") + } + + if(path != nil) { + do { + let data = try Data(contentsOf: URL(fileURLWithPath:path!)) + let nsData = data as NSData + let resId = UInt32(instance.resources.count) + instance.resources[resId] = nsData + let length = nsData.length + print("Resolved asset to file of length \(Int32(length)) at path \(path!)") + return ResourceBuffer(data:nsData.bytes, size:Int32(UInt32(nsData.length)), id:Int32(UInt32(resId))) + } catch { + print("ERROR LOADING RESOURCE") + } + } + return ResourceBuffer() + } + + var freeResource : @convention(c) (ResourceBuffer,UnsafeMutableRawPointer?) -> () = { rbuf, resourcesPtr in + let instance:SwiftFlutterFilamentPlugin = Unmanaged.fromOpaque(resourcesPtr!).takeUnretainedValue() + instance.resources.removeValue(forKey:UInt32(rbuf.id)) + } + + var markTextureFrameAvailable : @convention(c) (UnsafeMutableRawPointer?) -> () = { instancePtr in + let instance:SwiftFlutterFilamentPlugin = Unmanaged.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": + var resourceLoaderWrapper = make_resource_loader(loadResource, freeResource, Unmanaged.passUnretained(self).toOpaque()) + result(unsafeBitCast(resourceLoaderWrapper, to:Int64.self)) + case "getRenderCallback": + let renderCallback = markTextureFrameAvailable + let resultArray:[Any] = [ + unsafeBitCast(renderCallback, to:Int64.self), unsafeBitCast(Unmanaged.passUnretained(self), to:UInt64.self)] + result(resultArray) + 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(registry: registry, width: width, height: height) + + if(self.texture?.metalTextureAddress == -1) { + result(nil) + } else { + result([self.texture!.flutterTextureId as Any, self.texture?.metalTextureAddress, nil]) + } + case "destroyTexture": + self.texture?.destroy() + self.texture = nil + result(true) + default: + result(FlutterMethodNotImplemented) + } + } +} + diff --git a/flutter_filament_federated/flutter_filament/macos/flutter_filament.podspec b/flutter_filament_federated/flutter_filament/macos/flutter_filament.podspec new file mode 100644 index 00000000..0a8340a7 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/macos/flutter_filament.podspec @@ -0,0 +1,28 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint flutter_filament.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'flutter_filament' + 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/ResourceBuffer.hpp','include/SwiftFlutterFilamentPlugin-Bridging-Header.h' + s.public_header_files = 'include/SwiftFlutterFilamentPlugin-Bridging-Header.h', 'include/ResourceBuffer.hpp' + s.dependency 'FlutterMacOS' + + s.platform = :osx, '13' + + s.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES', + 'OTHER_CFLAGS' => '"-fvisibility=default" "$(inherited)"', + } + s.swift_version = '5.0' + +end diff --git a/flutter_filament_federated/flutter_filament/macos/include/ResourceBuffer.hpp b/flutter_filament_federated/flutter_filament/macos/include/ResourceBuffer.hpp new file mode 100644 index 00000000..8ae27f18 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/macos/include/ResourceBuffer.hpp @@ -0,0 +1,117 @@ +#ifndef RESOURCE_BUFFER_H +#define RESOURCE_BUFFER_H + +#include +#include + +// +// 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 flutter_filament { + +// struct ResourceBufferImpl : public ResourceBuffer +// { + +// ResourceBufferImpl(const void *const mData, const int32_t mSize, const int32_t mId) +// { +// data = mData; +// size = mSize; +// id = mId; +// }; + +// ResourceBufferImpl(const ResourceBufferImpl &rb) +// { +// (void *)data = rb.data; +// size = rb.size; +// id = rb.id; +// }; + +// ResourceBufferImpl(const ResourceBufferImpl &&rb) noexcept +// { +// data = rb.data; +// size = rb.size; +// id = rb.id; +// }; +// ResourceBufferImpl &operator=(const ResourceBufferImpl &other) = delete; +// }; + +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 diff --git a/flutter_filament_federated/flutter_filament/macos/include/SwiftFlutterFilamentPlugin-Bridging-Header.h b/flutter_filament_federated/flutter_filament/macos/include/SwiftFlutterFilamentPlugin-Bridging-Header.h new file mode 100644 index 00000000..e1af2872 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/macos/include/SwiftFlutterFilamentPlugin-Bridging-Header.h @@ -0,0 +1,17 @@ +#ifndef SwiftFlutterFilamentPlugin_Bridging_Header_h +#define SwiftFlutterFilamentPlugin_Bridging_Header_h + +#include + +#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; +} + +#endif diff --git a/flutter_filament_federated/flutter_filament/output.log b/flutter_filament_federated/flutter_filament/output.log new file mode 100644 index 00000000..199b1abd --- /dev/null +++ b/flutter_filament_federated/flutter_filament/output.log @@ -0,0 +1 @@ +Target file "lib/main.dart" not found. diff --git a/flutter_filament_federated/flutter_filament/pubspec.lock b/flutter_filament_federated/flutter_filament/pubspec.lock new file mode 100644 index 00000000..32cf750a --- /dev/null +++ b/flutter_filament_federated/flutter_filament/pubspec.lock @@ -0,0 +1,358 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + animation_tools_dart: + dependency: "direct main" + description: + name: animation_tools_dart + sha256: c4bc4096d43227b573345a3ea3cb26c3af47a70af31cd7d7d3a5b7c99e33d615 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + dart_filament: + dependency: "direct main" + description: + path: "../../dart_filament" + relative: true + source: path + version: "0.5.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: "direct main" + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_filament_ffi: + dependency: "direct main" + description: + path: "../flutter_filament_ffi" + relative: true + source: path + version: "0.0.1" + flutter_filament_platform_interface: + dependency: "direct main" + description: + path: "../flutter_filament_platform_interface" + relative: true + source: path + version: "0.0.1" + flutter_filament_web: + dependency: "direct main" + description: + path: "../flutter_filament_web" + relative: true + source: path + version: "2.0.5" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" + source: hosted + version: "1.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "25dfcaf170a0190f47ca6355bdd4552cb8924b430512ff0cafb8db9bd41fe33b" + url: "https://pub.dev" + source: hosted + version: "1.14.0" + native_assets_cli: + dependency: "direct dev" + description: + name: native_assets_cli + sha256: "9c1b67ccf85ec9282f34e5348ae78dcb7da2c7dc965c0265306477d977853a0d" + url: "https://pub.dev" + source: hosted + version: "0.5.4" + native_toolchain_c: + dependency: "direct dev" + description: + name: native_toolchain_c + sha256: "1b1b86f47570378d0003f0d949fbb03b637ec9d2dcbcf698a16f7cbffb3a945c" + url: "https://pub.dev" + source: hosted + version: "0.4.1" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + plugin_platform_interface: + dependency: "direct main" + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "2419f20b0c8677b2d67c8ac4d1ac7372d862dc6c460cdbb052b40155408cd794" + url: "https://pub.dev" + source: hosted + version: "0.7.1" + tuple: + dependency: "direct main" + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: "direct main" + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "7475cb4dd713d57b6f7464c0e13f06da0d535d8b2067e188962a59bac2cf280b" + url: "https://pub.dev" + source: hosted + version: "14.2.2" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/flutter_filament_federated/flutter_filament/pubspec.yaml b/flutter_filament_federated/flutter_filament/pubspec.yaml new file mode 100644 index 00000000..737104f5 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/pubspec.yaml @@ -0,0 +1,50 @@ +name: flutter_filament +description: A Flutter plugin to wrap the Filament rendering engine. +version: 0.6.0 +homepage: + +environment: + sdk: ">=3.1.0 <4.0.0" + flutter: ">=3.16.0-0.2.pre" + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + vector_math: ^2.1.2 + plugin_platform_interface: ^2.0.0 + tuple: + ffi: + animation_tools_dart: ^0.0.2 + dart_filament: + path: ../../dart_filament + flutter_filament_platform_interface: + path: ../flutter_filament_platform_interface + flutter_filament_ffi: + path: ../flutter_filament_ffi + flutter_filament_web: + path: ../flutter_filament_web + + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^1.0.0 + native_assets_cli: ^0.5.0 + native_toolchain_c: ^0.4.0 + +flutter: + plugin: + platforms: + android: + pluginClass: FlutterFilamentPlugin + package: app.polyvox.filament + ios: + pluginClass: SwiftFlutterFilamentPlugin + macos: + pluginClass: SwiftFlutterFilamentPlugin + windows: + pluginClass: FlutterFilamentPluginCApi + linux: + pluginClass: FlutterFilamentPlugin diff --git a/flutter_filament_federated/flutter_filament/test/Makefile b/flutter_filament_federated/flutter_filament/test/Makefile new file mode 100644 index 00000000..232b7489 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/test/Makefile @@ -0,0 +1,10 @@ +LDFLAGS:=-lfilament -lbackend -lfilameshio -lviewer -lfilamat -lgeometry -lutils -lfilabridge -lgltfio_core -lfilament-iblprefilter -limage -limageio -ltinyexr -lgltfio_core -lfilaflat -ldracodec -libl -lktxreader -lpng -lz -lstb -luberzlib -lsmol-v -luberarchive -lzstd -lvkshaders -lbluegl -lbluevk -lbasis_transcoder -lmeshoptimizer -L../macos/lib -framework CoreFoundation -framework Foundation -framework CoreVideo -framework Metal -framework QuartzCore -framework Cocoa + +clean: + rm ./out/test +run: build + ./out/test +build: cpp/test.cpp + mkdir -p out + clang++ -I../ios/include/filament -I../ios/include/ cpp/test.cpp ../macos/src/SceneManager.cpp --std=c++17 $(LDFLAGS) -o out/test + diff --git a/flutter_filament_federated/flutter_filament/test/cpp/test.cpp b/flutter_filament_federated/flutter_filament/test/cpp/test.cpp new file mode 100644 index 00000000..1de753ef --- /dev/null +++ b/flutter_filament_federated/flutter_filament/test/cpp/test.cpp @@ -0,0 +1,94 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SceneManager.hpp" + +#include "ResourceBuffer.hpp" + +using namespace filament; +using namespace flutter_filament; +using namespace std; + +int _i = 0; + +ResourceBuffer loadResource(const char* name) { + + std::cout << "LOADING RESOURCE" << std::endl; + + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + std::cout << "Current working dir: " << cwd << std::endl; + } + + string name_str(name); + auto id = _i++; + + name_str = string(cwd) + string("/") + name_str; + + std::cout << "Loading resource at " << name_str.c_str() << std::endl; + + streampos length; + ifstream is(name_str, ios::binary); + ResourceBuffer rb { nullptr, -1, 0 }; + if(!is) { + std::cout << "Failed to find resource at file path " << name_str.c_str() << std::endl; + return rb; + } + is.seekg (0, ios::end); + length = is.tellg(); + char * buffer; + buffer = new char [length]; + is.seekg (0, ios::beg); + is.read (buffer, length); + is.close(); + return ResourceBuffer { buffer, static_cast(length), id }; +} + +void freeResource(ResourceBuffer rb) { + +} + +int main(int argc, char** argv) { + auto engine = Engine::create(); + auto scene = engine->createScene(); + auto loader = ResourceLoaderWrapper(loadResource, freeResource); + + auto sceneManager = SceneManager(&loader, engine, scene, nullptr); + + auto shapes = sceneManager.loadGlb("../example/assets/shapes/shapes.glb", 2); + + sceneManager.remove(shapes); + + shapes = sceneManager.loadGlb("../example/assets/shapes/shapes.glb", 2); + + auto instanceCount = sceneManager.getInstanceCount(shapes); + assert(instanceCount == 2); + + EntityId instances[instanceCount]; + + sceneManager.getInstances(shapes, instances); + + sceneManager.transformToUnitCube(shapes); + + auto morphTargetNames = sceneManager.getMorphTargetNames(shapes, "Cylinder"); + assert(morphTargetNames->size() == 4); + + morphTargetNames = sceneManager.getMorphTargetNames(shapes, "Cube"); + assert(morphTargetNames->size() == 2); + + morphTargetNames = sceneManager.getMorphTargetNames(shapes, "Cone"); + assert(morphTargetNames->size() == 8); + math::mat4f boneTransform; + sceneManager.setBoneTransform(shapes, "Cylinder", 0, "Bone", boneTransform); + + + sceneManager.destroyAll(); +} \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/test/frustum_unit_test.dart b/flutter_filament_federated/flutter_filament/test/frustum_unit_test.dart new file mode 100644 index 00000000..880fc702 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/test/frustum_unit_test.dart @@ -0,0 +1,66 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:vector_math/vector_math_64.dart'; + +void main() { + test('Plane', () { + var plane = Plane()..setFromComponents(1, 0, 0, 2); + print(plane.distanceToVector3(Vector3(-1, 0, 0))); + }); + + test('Check if point is inside frustum', () { + var frustum = Frustum(); + frustum.plane0.setFromComponents(-0.868, 0, 0.49, 0); + frustum.plane1.setFromComponents(0.868, 0, 0.49, 0); + frustum.plane2.setFromComponents(0, -0.919, 0.39, 0); + frustum.plane3.setFromComponents(0, 0.919, 0.39, 0); + frustum.plane4.setFromComponents(0, 0, -1, -999.88); + frustum.plane5.setFromComponents(0, 0, 1, 0.05); + + var point = Vector3(0, 0, -1); + + print(frustum.plane0.distanceToVector3(point)); + print(frustum.plane1.distanceToVector3(point)); + + print(frustum.plane2.distanceToVector3(point)); + + print(frustum.plane3.distanceToVector3(point)); + + print(frustum.plane4.distanceToVector3(point)); + + print(frustum.plane5.distanceToVector3(point)); + + print(frustum.containsVector3(point)); + }); + + test("Lukas test", () { + final frustum = Frustum(); + //left + frustum.plane0.setFromComponents(-1.0, 0, 0, 1); + //right + frustum.plane1.setFromComponents(1.0, 0, 0, 2.0); + //bottom + frustum.plane2.setFromComponents(0, -1, 0, 1); + //top + frustum.plane3.setFromComponents(0, 1, 0, 1); + //far + frustum.plane4.setFromComponents(0, 0, -1, 1); + //near + frustum.plane5.setFromComponents(0, 0, 1, 1); + + // vector3 + final point = Vector3(-0.5, 0, 0); + + print(frustum.plane0.distanceToVector3(point)); + print(frustum.plane1.distanceToVector3(point)); + + print(frustum.plane2.distanceToVector3(point)); + + print(frustum.plane3.distanceToVector3(point)); + + print(frustum.plane4.distanceToVector3(point)); + + print(frustum.plane5.distanceToVector3(point)); + + print(frustum.containsVector3(point)); + }); +} diff --git a/flutter_filament_federated/flutter_filament/test/out/test b/flutter_filament_federated/flutter_filament/test/out/test new file mode 100644 index 00000000..8b11f4ea Binary files /dev/null and b/flutter_filament_federated/flutter_filament/test/out/test differ diff --git a/flutter_filament_federated/flutter_filament/windows/.gitignore b/flutter_filament_federated/flutter_filament/windows/.gitignore new file mode 100644 index 00000000..b3eb2be1 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/flutter_filament_federated/flutter_filament/windows/CMakeLists.txt b/flutter_filament_federated/flutter_filament/windows/CMakeLists.txt new file mode 100644 index 00000000..3180cb8c --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/CMakeLists.txt @@ -0,0 +1,283 @@ +cmake_minimum_required(VERSION 3.14) +set(PROJECT_NAME "flutter_filament") +project(${PROJECT_NAME} LANGUAGES C CXX) + +cmake_policy(VERSION 3.14...3.25) + +# This value is used when generating builds using this plugin, so it must +# not be changed +set(PLUGIN_NAME "flutter_filament_plugin") + +# Any new source files that you add to the plugin should be added here. +list(APPEND PLUGIN_SOURCES + "flutter_filament_plugin.cpp" + "flutter_filament_plugin.h" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/SceneManager.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FilamentViewer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FlutterFilamentApi.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FlutterFilamentFFIApi.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/StreamBufferAdapter.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/TimeIt.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/camutils/Manipulator.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/camutils/Bookmark.cpp" +) + +set(USE_ANGLE FALSE) +set(WGL_USE_BACKING_WINDOW TRUE) + +if(USE_ANGLE) + add_compile_definitions(USE_ANGLE) + list(APPEND PLUGIN_SOURCES "flutter_angle_texture.cpp" "egl_context.cpp" ) +else() + if(WGL_USE_BACKING_WINDOW) + add_compile_definitions(WGL_USE_BACKING_WINDOW) + endif() + list(APPEND PLUGIN_SOURCES "wgl_context.cpp" "opengl_texture_buffer.cpp" "backing_window.cpp") + # if(WGL_USE_BACKING_WINDOW) + # list(APPEND PLUGIN_SOURCES ) + # else() + # list(APPEND PLUGIN_SOURCES ) + # endif() +endif() + +# Define the plugin library target. Its name must not be changed (see comment +# on PLUGIN_NAME above). +add_library(${PLUGIN_NAME} SHARED + "include/flutter_filament/flutter_filament_plugin_c_api.h" + "flutter_filament_plugin_c_api.cpp" + ${PLUGIN_SOURCES} + "include/material/image.c" +) + +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + +apply_standard_settings(${PLUGIN_NAME}) + +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_features(${PLUGIN_NAME} PUBLIC cxx_std_20) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include" +) + +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/filament") + +if(USE_ANGLE) + list(APPEND GL_LIBS + EGL + GLESv2 + ) + set(ANGLE_OR_OPENGL_DIR angle) + add_library(EGL SHARED IMPORTED) + set_property(TARGET EGL PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/libEGL.dll.lib") + set_property(TARGET EGL PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/libEGL.dll.lib") + set_property(TARGET EGL PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/libEGL.dll.lib") + add_library(GLESv2 SHARED IMPORTED) + set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/libGLESv2.dll.lib") + set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/libGLESv2.dll.lib") + set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/libGLESv2.dll.lib") +else() + list(APPEND GL_LIBS + bluegl + opengl32 + dwmapi + comctl32 + ) + set(ANGLE_OR_OPENGL_DIR opengl) + add_library(bluegl SHARED IMPORTED) + set_property(TARGET bluegl PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/opengl/bluegl.lib") + set_property(TARGET bluegl PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/opengl/bluegl.lib") + set_property(TARGET bluegl PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/opengl/bluegl.lib") +endif() + +add_library(backend SHARED IMPORTED) +set_property(TARGET backend PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/${ANGLE_OR_OPENGL_DIR}/backend.lib") +set_property(TARGET backend PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/${ANGLE_OR_OPENGL_DIR}/backend.lib") +set_property(TARGET backend PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/${ANGLE_OR_OPENGL_DIR}/backend.lib") + +add_library(geometry SHARED IMPORTED) +set_property(TARGET geometry PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/geometry.lib") +set_property(TARGET geometry PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/geometry.lib") +set_property(TARGET geometry PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/geometry.lib") + +add_library(filament SHARED IMPORTED) +set_property(TARGET filament PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/${ANGLE_OR_OPENGL_DIR}/filament.lib") +set_property(TARGET filament PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/${ANGLE_OR_OPENGL_DIR}/filament.lib") +set_property(TARGET filament PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/${ANGLE_OR_OPENGL_DIR}/filament.lib") + +add_library(filameshio SHARED IMPORTED) +set_property(TARGET filameshio PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/filameshio.lib") +set_property(TARGET filameshio PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/filameshio.lib") +set_property(TARGET filameshio PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/filameshio.lib") + +add_library(filamat SHARED IMPORTED) +set_property(TARGET filamat PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/filamat.lib") +set_property(TARGET filamat PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/filamat.lib") +set_property(TARGET filamat PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/filamat.lib") + +add_library(utils SHARED IMPORTED) +set_property(TARGET utils PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/utils.lib") +set_property(TARGET utils PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/utils.lib") +set_property(TARGET utils PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/utils.lib") + +add_library(filabridge SHARED IMPORTED) +set_property(TARGET filabridge PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/filabridge.lib") +set_property(TARGET filabridge PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/filabridge.lib") +set_property(TARGET filabridge PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/filabridge.lib") + +add_library(gltfio SHARED IMPORTED) +set_property(TARGET gltfio PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/gltfio.lib") +set_property(TARGET gltfio PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/gltfio.lib") +set_property(TARGET gltfio PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/gltfio.lib") + +add_library(gltfio_core SHARED IMPORTED) +set_property(TARGET gltfio_core PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/gltfio_core.lib") +set_property(TARGET gltfio_core PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/gltfio_core.lib") +set_property(TARGET gltfio_core PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/gltfio_core.lib") + +add_library(image SHARED IMPORTED) +set_property(TARGET image PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/image.lib") +set_property(TARGET image PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/image.lib") +set_property(TARGET image PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/image.lib") + +add_library(imageio STATIC IMPORTED) +set_property(TARGET imageio PROPERTY IMPORTED_LOCATION_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/imageio.lib") +set_property(TARGET imageio PROPERTY IMPORTED_LOCATION_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/imageio.lib") +set_property(TARGET imageio PROPERTY IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/imageio.lib") + +add_library(tinyexr STATIC IMPORTED) +set_property(TARGET tinyexr PROPERTY IMPORTED_LOCATION_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/tinyexr.lib") +set_property(TARGET tinyexr PROPERTY IMPORTED_LOCATION_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/tinyexr.lib") +set_property(TARGET tinyexr PROPERTY IMPORTED_LOCATION_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/tinyexr.lib") + +add_library(camutils SHARED IMPORTED) +set_property(TARGET camutils PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/camutils.lib") +set_property(TARGET camutils PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/camutils.lib") +set_property(TARGET camutils PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/camutils.lib") + +add_library(filaflat SHARED IMPORTED) +set_property(TARGET filaflat PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/filaflat.lib") +set_property(TARGET filaflat PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/filaflat.lib") +set_property(TARGET filaflat PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/filaflat.lib") + +add_library(dracodec SHARED IMPORTED) +set_property(TARGET dracodec PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/dracodec.lib") +set_property(TARGET dracodec PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/dracodec.lib") +set_property(TARGET dracodec PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/dracodec.lib") + +add_library(ibl SHARED IMPORTED) +set_property(TARGET ibl PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/ibl.lib") +set_property(TARGET ibl PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/ibl.lib") +set_property(TARGET ibl PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/ibl.lib") + +add_library(ktxreader SHARED IMPORTED) +set_property(TARGET ktxreader PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/ktxreader.lib") +set_property(TARGET ktxreader PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/ktxreader.lib") +set_property(TARGET ktxreader PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/ktxreader.lib") + +add_library(stb SHARED IMPORTED) +set_property(TARGET stb PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/stb.lib") +set_property(TARGET stb PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/stb.lib") +set_property(TARGET stb PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/stb.lib") + +add_library(bluevk SHARED IMPORTED) +set_property(TARGET bluevk PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/bluevk.lib") +set_property(TARGET bluevk PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/bluevk.lib") +set_property(TARGET bluevk PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/bluevk.lib") + +add_library(vkshaders SHARED IMPORTED) +set_property(TARGET vkshaders PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/vkshaders.lib") +set_property(TARGET vkshaders PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/vkshaders.lib") +set_property(TARGET vkshaders PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/vkshaders.lib") + +add_library(uberzlib SHARED IMPORTED) +set_property(TARGET uberzlib PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/uberzlib.lib") +set_property(TARGET uberzlib PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/uberzlib.lib") +set_property(TARGET uberzlib PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/uberzlib.lib") + +add_library(smol-v SHARED IMPORTED) +set_property(TARGET smol-v PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/smol-v.lib") +set_property(TARGET smol-v PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/smol-v.lib") +set_property(TARGET smol-v PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/smol-v.lib") + +add_library(uberarchive SHARED IMPORTED) +set_property(TARGET uberarchive PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/${ANGLE_OR_OPENGL_DIR}/uberarchive.lib") +set_property(TARGET uberarchive PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/${ANGLE_OR_OPENGL_DIR}/uberarchive.lib") +set_property(TARGET uberarchive PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/${ANGLE_OR_OPENGL_DIR}/uberarchive.lib") + +add_library(meshoptimizer SHARED IMPORTED) +set_property(TARGET meshoptimizer PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/meshoptimizer.lib") +set_property(TARGET meshoptimizer PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/meshoptimizer.lib") +set_property(TARGET meshoptimizer PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/meshoptimizer.lib") + +add_library(basis_transcoder SHARED IMPORTED) +set_property(TARGET basis_transcoder PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/basis_transcoder.lib") +set_property(TARGET basis_transcoder PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/basis_transcoder.lib") +set_property(TARGET basis_transcoder PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/basis_transcoder.lib") + +add_library(z SHARED IMPORTED) +set_property(TARGET z PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/z.lib") +set_property(TARGET z PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/z.lib") +set_property(TARGET z PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/z.lib") + +add_library(zstd SHARED IMPORTED) +set_property(TARGET zstd PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/zstd.lib") +set_property(TARGET zstd PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/zstd.lib") +set_property(TARGET zstd PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/zstd.lib") + +add_library(png SHARED IMPORTED) +set_property(TARGET png PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/png.lib") +set_property(TARGET png PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/png.lib") +set_property(TARGET png PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/png.lib") + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../ios/include + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_link_libraries(${PLUGIN_NAME} PRIVATE + flutter + flutter_wrapper_plugin + gltfio + gltfio_core + filament + backend + geometry + filamat + filabridge + camutils + filaflat + dracodec + ibl + ktxreader + image + imageio + utils + stb + uberzlib + smol-v + uberarchive + meshoptimizer + geometry + basis_transcoder + z + zstd + png + tinyexr + Shlwapi + ${GL_LIBS} +) + +# List of absolute paths to libraries that should be bundled with the plugin +if(USE_ANGLE) +set(flutter_filament_bundled_libraries + ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/libEGL.dll + ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/libGLESv2.dll + ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/libc++.dll + ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/third_party_abseil-cpp_absl.dll + ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/third_party_zlib.dll + PARENT_SCOPE +) +endif() + diff --git a/flutter_filament_federated/flutter_filament/windows/backing_window.cpp b/flutter_filament_federated/flutter_filament/windows/backing_window.cpp new file mode 100644 index 00000000..e9668489 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/backing_window.cpp @@ -0,0 +1,357 @@ +#include "backing_window.h" + +#include +#include +#include +#include + +#include +#include +#include + +#pragma comment(lib, "dwmapi.lib") +#pragma comment(lib, "comctl32.lib") + +namespace flutter_filament { + +static constexpr auto kClassName = L"FLUTTER_FILAMENT_WINDOW"; +static constexpr auto kWindowName = L"flutter_filament_window"; +static bool was_window_hidden_due_to_minimize_ = false; +static WPARAM last_wm_size_wparam_ = SIZE_RESTORED; +uint64_t last_thread_time_ = 0; +static constexpr auto kNativeViewPositionAndShowDelay = 300; + +typedef enum _WINDOWCOMPOSITIONATTRIB { + WCA_UNDEFINED = 0, + WCA_NCRENDERING_ENABLED = 1, + WCA_NCRENDERING_POLICY = 2, + WCA_TRANSITIONS_FORCEDISABLED = 3, + WCA_ALLOW_NCPAINT = 4, + WCA_CAPTION_BUTTON_BOUNDS = 5, + WCA_NONCLIENT_RTL_LAYOUT = 6, + WCA_FORCE_ICONIC_REPRESENTATION = 7, + WCA_EXTENDED_FRAME_BOUNDS = 8, + WCA_HAS_ICONIC_BITMAP = 9, + WCA_THEME_ATTRIBUTES = 10, + WCA_NCRENDERING_EXILED = 11, + WCA_NCADORNMENTINFO = 12, + WCA_EXCLUDED_FROM_LIVEPREVIEW = 13, + WCA_VIDEO_OVERLAY_ACTIVE = 14, + WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15, + WCA_DISALLOW_PEEK = 16, + WCA_CLOAK = 17, + WCA_CLOAKED = 18, + WCA_ACCENT_POLICY = 19, + WCA_FREEZE_REPRESENTATION = 20, + WCA_EVER_UNCLOAKED = 21, + WCA_VISUAL_OWNER = 22, + WCA_HOLOGRAPHIC = 23, + WCA_EXCLUDED_FROM_DDA = 24, + WCA_PASSIVEUPDATEMODE = 25, + WCA_USEDARKMODECOLORS = 26, + WCA_LAST = 27 +} WINDOWCOMPOSITIONATTRIB; + +typedef struct _WINDOWCOMPOSITIONATTRIBDATA { + WINDOWCOMPOSITIONATTRIB Attrib; + PVOID pvData; + SIZE_T cbData; +} WINDOWCOMPOSITIONATTRIBDATA; + +typedef enum _ACCENT_STATE { + ACCENT_DISABLED = 0, + ACCENT_ENABLE_GRADIENT = 1, + ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, + ACCENT_ENABLE_BLURBEHIND = 3, + ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, + ACCENT_ENABLE_HOSTBACKDROP = 5, + ACCENT_INVALID_STATE = 6 +} ACCENT_STATE; + +typedef struct _ACCENT_POLICY { + ACCENT_STATE AccentState; + DWORD AccentFlags; + DWORD GradientColor; + DWORD AnimationId; +} ACCENT_POLICY; + +typedef BOOL(WINAPI* _GetWindowCompositionAttribute)( + HWND, WINDOWCOMPOSITIONATTRIBDATA*); +typedef BOOL(WINAPI* _SetWindowCompositionAttribute)( + HWND, WINDOWCOMPOSITIONATTRIBDATA*); + +static _SetWindowCompositionAttribute g_set_window_composition_attribute = NULL; +static bool g_set_window_composition_attribute_initialized = false; + +typedef LONG NTSTATUS, *PNTSTATUS; +#define STATUS_SUCCESS (0x00000000) + +typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); + +RTL_OSVERSIONINFOW GetWindowsVersion() { + HMODULE hmodule = ::GetModuleHandleW(L"ntdll.dll"); + if (hmodule) { + RtlGetVersionPtr rtl_get_version_ptr = + (RtlGetVersionPtr)::GetProcAddress(hmodule, "RtlGetVersion"); + if (rtl_get_version_ptr != nullptr) { + RTL_OSVERSIONINFOW rovi = {0}; + rovi.dwOSVersionInfoSize = sizeof(rovi); + if (STATUS_SUCCESS == rtl_get_version_ptr(&rovi)) { + return rovi; + } + } + } + RTL_OSVERSIONINFOW rovi = {0}; + return rovi; +} + +void SetWindowComposition(HWND window, int32_t accent_state, + int32_t gradient_color) { + // TODO: Look for a better available API. + if (GetWindowsVersion().dwBuildNumber >= 18362) { + if (!g_set_window_composition_attribute_initialized) { + auto user32 = ::GetModuleHandleA("user32.dll"); + if (user32) { + g_set_window_composition_attribute = + reinterpret_cast<_SetWindowCompositionAttribute>( + ::GetProcAddress(user32, "SetWindowCompositionAttribute")); + if (g_set_window_composition_attribute) { + g_set_window_composition_attribute_initialized = true; + } + } + } + ACCENT_POLICY accent = {static_cast(accent_state), 2, + static_cast(gradient_color), 0}; + WINDOWCOMPOSITIONATTRIBDATA data; + data.Attrib = WCA_ACCENT_POLICY; + data.pvData = &accent; + data.cbData = sizeof(accent); + g_set_window_composition_attribute(window, &data); + } +} + + +LRESULT CALLBACK FilamentWindowProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_MOUSEMOVE: { + TRACKMOUSEEVENT event; + event.cbSize = sizeof(event); + event.hwndTrack = window; + event.dwFlags = TME_HOVER; + event.dwHoverTime = 200; + auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA); + if (user_data) { + HWND flutterRootWindow = reinterpret_cast(user_data); + ::SetForegroundWindow(flutterRootWindow); + LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE); + ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED); + ::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style); + } + break; + } + case WM_ERASEBKGND: { + // Prevent erasing of |window| when it is unfocused and minimized or + // moved out of screen etc. + break; + } + case WM_SIZE: + break; + case WM_MOVE: + case WM_MOVING: + case WM_ACTIVATE: + case WM_WINDOWPOSCHANGED: { + // NativeViewCore::GetInstance()->SetHitTestBehavior(0); + auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA); + if (user_data) { + HWND flutterRootWindow = reinterpret_cast(user_data); + ::SetForegroundWindow(flutterRootWindow); + // NativeViewCore::GetInstance()->SetHitTestBehavior(0); + LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE); + ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED); + ::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style); + } + break; + } + default: + break; + } + return ::DefWindowProc(window, message, wparam, lparam); +} + +BackingWindow::BackingWindow(flutter::PluginRegistrarWindows *pluginRegistrar, + int width, + int height, + int left, + int top) : _width(width), _height(height), _left(left), _top(top) { + // a Flutter application actually has two windows - the innner window contains the FlutterView. + // although we will use the outer window for various events, we always position things relative to the inner window. + _flutterViewWindow = pluginRegistrar->GetView()->GetNativeWindow(); + _flutterRootWindow = ::GetAncestor(_flutterViewWindow, GA_ROOT); + + RECT flutterChildRect; + ::GetWindowRect(_flutterViewWindow, &flutterChildRect); + + // set composition to allow transparency + SetWindowComposition(_flutterRootWindow, 6, 0); + + // register a top-level WindowProcDelegate to handle window events + pluginRegistrar->RegisterTopLevelWindowProcDelegate([=](HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + case WM_MOUSEMOVE: { + break; + } + case WM_ACTIVATE: { + RECT rootWindowRect; + ::GetWindowRect(_flutterViewWindow, &rootWindowRect); + // Position |native_view| such that it's z order is behind |window_| & + // redraw aswell. + ::SetWindowPos(_windowHandle, _flutterRootWindow, rootWindowRect.left + _left, + rootWindowRect.top + _top, _width, + _height, SWP_NOACTIVATE); + break; + } + case WM_SIZE: { + if (wparam != SIZE_RESTORED || last_wm_size_wparam_ == SIZE_MINIMIZED || + last_wm_size_wparam_ == SIZE_MAXIMIZED || + was_window_hidden_due_to_minimize_) { + was_window_hidden_due_to_minimize_ = false; + // Minimize condition is handled separately inside |WM_WINDOWPOSCHANGED| + // case, since we don't want to cause unnecessary redraws (& show/hide) + // when user is resizing the window by dragging the window border. + SetWindowComposition(_flutterRootWindow, 0, 0); + ::ShowWindow(_windowHandle, SW_HIDE); + last_thread_time_ = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + std::thread( + [=](uint64_t time) { + if (time < last_thread_time_) { + return; + } + std::this_thread::sleep_for( + std::chrono::milliseconds(kNativeViewPositionAndShowDelay)); + SetWindowComposition(_flutterRootWindow, 6, 0); + // Handling SIZE_MINIMIZED separately. + if (wparam != SIZE_MINIMIZED) { + ::ShowWindow(_windowHandle, SW_SHOWNOACTIVATE); + } + + RECT flutterViewRect; + ::GetWindowRect(_flutterViewWindow, &flutterViewRect); + ::SetWindowPos(_windowHandle, _flutterRootWindow, flutterViewRect.left + _left, + flutterViewRect.top + _top, _width, _height, + SWP_NOACTIVATE); + }, + last_thread_time_) + .detach(); + } + last_wm_size_wparam_ = wparam; + break; + } + case WM_MOVE: + case WM_MOVING: + case WM_WINDOWPOSCHANGED: { + RECT rootWindowRect; + ::GetWindowRect(_flutterViewWindow, &rootWindowRect); + if (rootWindowRect.right - rootWindowRect.left > 0 && + rootWindowRect.bottom - rootWindowRect.top > 0) { + ::SetWindowPos(_windowHandle, _flutterRootWindow, rootWindowRect.left + _left, + rootWindowRect.top + _top, _width, + _height, SWP_NOACTIVATE); + // |window_| is minimized. + if (rootWindowRect.left < 0 && rootWindowRect.top < 0 && + rootWindowRect.right < 0 && rootWindowRect.bottom < 0) { + // Hide |native_view_container_| to prevent showing + // |native_view_container_| before |window_| placement + // i.e when restoring window after clicking the taskbar icon. + SetWindowComposition(_flutterRootWindow, 0, 0); + ::ShowWindow(_windowHandle, SW_HIDE); + was_window_hidden_due_to_minimize_ = true; + } + } + break; + } + case WM_CLOSE: { + // close + break; + } + default: + break; + } + return std::nullopt; + }); + + // create the HWND for Filament + auto window_class = WNDCLASSEX{}; + ::SecureZeroMemory(&window_class, sizeof(window_class)); + window_class.cbSize = sizeof(window_class); + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.lpfnWndProc = FilamentWindowProc; + window_class.hInstance = 0; + window_class.lpszClassName = kClassName; + window_class.hCursor = ::LoadCursorW(nullptr, IDC_ARROW); + window_class.hbrBackground = ::CreateSolidBrush(0); + ::RegisterClassExW(&window_class); + _windowHandle = ::CreateWindow(kClassName, kWindowName, WS_OVERLAPPEDWINDOW, + 0, 0, _width, _height, nullptr, + nullptr, GetModuleHandle(nullptr), nullptr); + + // Disable DWM animations + auto disable_window_transitions = TRUE; + DwmSetWindowAttribute(_windowHandle, DWMWA_TRANSITIONS_FORCEDISABLED, + &disable_window_transitions, + sizeof(disable_window_transitions)); + + auto style = ::GetWindowLong(_windowHandle, GWL_STYLE); + style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | + WS_EX_APPWINDOW); + ::SetWindowLong(_windowHandle, GWL_STYLE, style); + + ::SetWindowLongPtr(_windowHandle, GWLP_USERDATA, + reinterpret_cast(_flutterRootWindow)); + + RECT flutterViewRect; + ::GetWindowRect(_flutterViewWindow, &flutterViewRect); + + ::SetWindowPos(_windowHandle, _flutterRootWindow, flutterViewRect.left + _left, + flutterViewRect.top + _top, _width, _height, + SWP_NOACTIVATE); + + // remove taskbar entry for the window we created + ITaskbarList3* taskbar = nullptr; + ::CoCreateInstance(CLSID_TaskbarList, 0, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&taskbar)); + taskbar->DeleteTab(_windowHandle); + taskbar->Release(); + + ::ShowWindow(_windowHandle, SW_SHOW); + ::ShowWindow(_flutterViewWindow, SW_SHOW); + ::SetForegroundWindow(_flutterViewWindow); + ::SetFocus(_flutterViewWindow); + LONG ex_style = ::GetWindowLong(_flutterRootWindow, GWL_EXSTYLE); + ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED); + ::SetWindowLong(_flutterRootWindow, GWL_EXSTYLE, ex_style); +} + +void BackingWindow::Resize(int width, int height, int left, int top) { + _width = width; + _height = height; + _left = left; + _top = top; + RECT flutterViewRect; + ::GetWindowRect(_flutterViewWindow, &flutterViewRect); + std::cout << "Resizing to " << _width << " x " << _height << " with LT" << _left << " " << _top << " flutter view rect" << flutterViewRect.left << " " << flutterViewRect.top << " " << flutterViewRect.right << " " << flutterViewRect.bottom << std::endl; + + ::SetWindowPos(_windowHandle, _flutterRootWindow, flutterViewRect.left + _left, + flutterViewRect.top + _top, _width, _height, + SWP_NOACTIVATE); +} + +HWND BackingWindow::GetHandle() { return _windowHandle; } +} // namespace flutter_filament diff --git a/flutter_filament_federated/flutter_filament/windows/backing_window.h b/flutter_filament_federated/flutter_filament/windows/backing_window.h new file mode 100644 index 00000000..72488145 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/backing_window.h @@ -0,0 +1,31 @@ +#ifndef _BACKING_WINDOW_H +#define _BACKING_WINDOW_H + +#include +#include +#include + +namespace flutter_filament { + +class BackingWindow { + public: + BackingWindow( + flutter::PluginRegistrarWindows *pluginRegistrar, + int width, + int height, + int left, + int top); + HWND GetHandle(); + void Resize(int width, int height, int left, int top); + private: + HWND _windowHandle; + HWND _flutterRootWindow; + HWND _flutterViewWindow; + uint32_t _width = 0; + uint32_t _height = 0; + uint32_t _left = 0; + uint32_t _top = 0; +}; + +} +#endif \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/egl_context.cpp b/flutter_filament_federated/flutter_filament/windows/egl_context.cpp new file mode 100644 index 00000000..342a4d5f --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/egl_context.cpp @@ -0,0 +1,200 @@ + +#include "egl_context.h" + +#define FILAMENT_USE_EXTERNAL_GLES3 +#include + +#pragma comment(lib, "dwmapi.lib") +#pragma comment(lib, "comctl32.lib") + +namespace flutter_filament { + +FlutterEGLContext::FlutterEGLContext( + flutter::PluginRegistrarWindows* pluginRegistrar, + flutter::TextureRegistrar* textureRegistrar) : FlutterRenderContext(pluginRegistrar, textureRegistrar) { + + _platform = new filament::backend::PlatformEGL(); + + // D3D starts here + IDXGIAdapter *adapter_ = nullptr; + + // first, we need to initialize the D3D device and create the backing texture + // this has been taken from + // https://github.com/alexmercerind/flutter-windows-ANGLE-OpenGL-ES/blob/master/windows/angle_surface_manager.cc + auto feature_levels = { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + }; + // NOTE: Not enabling DirectX 12. + // |D3D11CreateDevice| crashes directly on Windows 7. + // D3D_FEATURE_LEVEL_12_2, D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, + // D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, + // D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, + IDXGIFactory *dxgi = nullptr; + ::CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)&dxgi); + // Manually selecting adapter. As far as my experience goes, this is the + // safest approach. Passing NULL (so-called default) seems to cause issues + // on Windows 7 or maybe some older graphics drivers. + // First adapter is the default. + // |D3D_DRIVER_TYPE_UNKNOWN| must be passed with manual adapter selection. + dxgi->EnumAdapters(0, &adapter_); + dxgi->Release(); + if (!adapter_) { + std::cout << "Failed to locate default D3D adapter" << std::endl; + return; + } + + DXGI_ADAPTER_DESC adapter_desc_; + adapter_->GetDesc(&adapter_desc_); + std::wcout << L"D3D adapter description: " << adapter_desc_.Description + << std::endl; + + auto hr = ::D3D11CreateDevice( + adapter_, D3D_DRIVER_TYPE_UNKNOWN, 0, 0, feature_levels.begin(), + static_cast(feature_levels.size()), D3D11_SDK_VERSION, + &_D3D11Device, 0, &_D3D11DeviceContext); + + if (FAILED(hr)) { + std::cout << "Failed to create D3D device" << std::endl; + return; + } + + Microsoft::WRL::ComPtr dxgi_device = nullptr; + auto dxgi_device_success = _D3D11Device->QueryInterface( + __uuidof(IDXGIDevice), (void **)&dxgi_device); + if (SUCCEEDED(dxgi_device_success) && dxgi_device != nullptr) { + dxgi_device->SetGPUThreadPriority(5); // Must be in interval [-7, 7]. + } + auto level = _D3D11Device->GetFeatureLevel(); + std::cout << "media_kit: ANGLESurfaceManager: Direct3D Feature Level: " + << (((unsigned)level) >> 12) << "_" + << ((((unsigned)level) >> 8) & 0xf) << std::endl; + + // ******************* + // * * + // * * + // * EGL starts here * + // * * + // * * + // * * + // ******************* + EGLBoolean bindAPI = eglBindAPI(EGL_OPENGL_ES_API); + if (UTILS_UNLIKELY(!bindAPI)) { + std::cout << "eglBindAPI EGL_OPENGL_ES_API failed" << std::endl; + return; + } + + _eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + assert_invariant(_eglDisplay != EGL_NO_DISPLAY); + + EGLint major, minor; + EGLBoolean initialized = false; + + EGLDeviceEXT eglDevice; + EGLint numDevices; + + if (auto *getPlatformDisplay = + reinterpret_cast( + eglGetProcAddress("eglGetPlatformDisplayEXT"))) { + + EGLint kD3D11DisplayAttributes[] = { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, + EGL_TRUE, + EGL_NONE, + }; + _eglDisplay = getPlatformDisplay( + EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, kD3D11DisplayAttributes); + initialized = eglInitialize(_eglDisplay, &major, &minor); + } + + std::cout << "Got major " << major << " and minor " << minor << std::endl; + + if (UTILS_UNLIKELY(!initialized)) { + std::cout << "eglInitialize failed" << std::endl; + return; + } + + glext::importGLESExtensionsEntryPoints(); + + EGLint configsCount; + + EGLint configAttribs[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, EGL_ALPHA_SIZE, 8, + EGL_NONE}; + + EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE, + EGL_NONE, // reserved for EGL_CONTEXT_OPENGL_NO_ERROR_KHR below + EGL_NONE}; + + // find an opaque config + if (!eglChooseConfig(_eglDisplay, configAttribs, &_eglConfig, 1, + &configsCount)) { + std::cout << "Failed to find EGL config" << std::endl; + return; + } + + auto ctx = eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT,contextAttribs); + _context = (void*)ctx; + + if (UTILS_UNLIKELY(_context == EGL_NO_CONTEXT)) { + return; + } +} + +void FlutterEGLContext::CreateRenderingSurface( + uint32_t width, uint32_t height, + std::unique_ptr> result, + uint32_t left, uint32_t top + ) { + + glext::importGLESExtensionsEntryPoints(); + + if(left != 0 || top != 0) { + result->Error("ERROR", + "Rendering with EGL uses a Texture render target/Flutter widget and does not need a window offset."); + return; + } + + if (_active.get()) { + result->Error("ERROR", + "Texture already exists. You must call destroyTexture before " + "attempting to create a new one."); + return; + } + + std::unique_ptr active = std::make_unique( + _pluginRegistrar, _textureRegistrar, std::move(result), width, height, + _D3D11Device, _D3D11DeviceContext, _eglConfig, _eglDisplay, _context, + [=](size_t width, size_t height) { + std::cout << "RESIZE" << std::endl; + std::vector list; + list.push_back((int64_t)width); + list.push_back((int64_t)height); + // auto val = std::make_unique(list); + // this->_channel->InvokeMethod("resize", std::move(val), nullptr); + }); + _active = std::move(active); + +} + +void FlutterEGLContext::RenderCallback() { + if(_active.get()) { + ((FlutterAngleTexture*)_active.get())->RenderCallback(); + } +} + +void* FlutterEGLContext::GetSharedContext() { + return (void*)_context; +} + +void* FlutterEGLContext::GetPlatform() { + return (void*)_platform; +} + +} \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/egl_context.h b/flutter_filament_federated/flutter_filament/windows/egl_context.h new file mode 100644 index 00000000..c77b7216 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/egl_context.h @@ -0,0 +1,36 @@ +#ifndef _EGL_CONTEXT_H +#define _EGL_CONTEXT_H + +#include + +#include +#include +#include +#include + +#include "flutter_angle_texture.h" +#include "backend/platforms/PlatformEGL.h" +#include "flutter_render_context.h" + +namespace flutter_filament { + +class FlutterEGLContext : public FlutterRenderContext { +public: + FlutterEGLContext(flutter::PluginRegistrarWindows* pluginRegistrar, flutter::TextureRegistrar* textureRegistrar); + void* GetSharedContext(); + void RenderCallback(); + void* GetPlatform(); + void CreateRenderingSurface(uint32_t width, uint32_t height, std::unique_ptr> result, uint32_t left, uint32_t top ); + +private: + void* _context = nullptr; + EGLConfig _eglConfig = NULL; + EGLDisplay _eglDisplay = NULL; + ID3D11Device* _D3D11Device = nullptr; + ID3D11DeviceContext* _D3D11DeviceContext = nullptr; + filament::backend::Platform* _platform = nullptr; +}; + +} + +#endif \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/flutter_angle_texture.cpp b/flutter_filament_federated/flutter_filament/windows/flutter_angle_texture.cpp new file mode 100644 index 00000000..832e20e6 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/flutter_angle_texture.cpp @@ -0,0 +1,243 @@ +#include "flutter_angle_texture.h" + +#include +#include +#include +#include + +#include + +namespace flutter_filament { + +static void logEglError(const char *name) noexcept { + const char *err; + switch (eglGetError()) { + case EGL_NOT_INITIALIZED: + err = "EGL_NOT_INITIALIZED"; + break; + case EGL_BAD_ACCESS: + err = "EGL_BAD_ACCESS"; + break; + case EGL_BAD_ALLOC: + err = "EGL_BAD_ALLOC"; + break; + case EGL_BAD_ATTRIBUTE: + err = "EGL_BAD_ATTRIBUTE"; + break; + case EGL_BAD_CONTEXT: + err = "EGL_BAD_CONTEXT"; + break; + case EGL_BAD_CONFIG: + err = "EGL_BAD_CONFIG"; + break; + case EGL_BAD_CURRENT_SURFACE: + err = "EGL_BAD_CURRENT_SURFACE"; + break; + case EGL_BAD_DISPLAY: + err = "EGL_BAD_DISPLAY"; + break; + case EGL_BAD_SURFACE: + err = "EGL_BAD_SURFACE"; + break; + case EGL_BAD_MATCH: + err = "EGL_BAD_MATCH"; + break; + case EGL_BAD_PARAMETER: + err = "EGL_BAD_PARAMETER"; + break; + case EGL_BAD_NATIVE_PIXMAP: + err = "EGL_BAD_NATIVE_PIXMAP"; + break; + case EGL_BAD_NATIVE_WINDOW: + err = "EGL_BAD_NATIVE_WINDOW"; + break; + case EGL_CONTEXT_LOST: + err = "EGL_CONTEXT_LOST"; + break; + default: + err = "unknown"; + break; + } + std::cout << name << " failed with " << err << std::endl; +} + +void FlutterAngleTexture::RenderCallback() { + glFinish(); + _D3D11DeviceContext->CopyResource(_externalD3DTexture2D.Get(), + _internalD3DTexture2D.Get()); + _D3D11DeviceContext->Flush(); +} + +FlutterAngleTexture::~FlutterAngleTexture() { + if (_eglDisplay != EGL_NO_DISPLAY && _eglSurface != EGL_NO_SURFACE) { + eglReleaseTexImage(_eglDisplay, _eglSurface, EGL_BACK_BUFFER); + } + auto success = eglDestroySurface(this->_eglDisplay, this->_eglSurface); + if(success != EGL_TRUE) { + std::cout << "Failed to destroy EGL Surface" << std::endl; + } + _internalD3DTexture2D->Release(); + _externalD3DTexture2D->Release(); + glDeleteTextures(1, &this->glTextureId); +} + +FlutterAngleTexture::FlutterAngleTexture( + flutter::PluginRegistrarWindows *pluginRegistrar, + flutter::TextureRegistrar *textureRegistrar, + std::unique_ptr> result, + uint32_t width, uint32_t height, ID3D11Device *D3D11Device, + ID3D11DeviceContext *D3D11DeviceContext, EGLConfig eglConfig, + EGLDisplay eglDisplay, EGLContext eglContext, + std::function onResizeRequested + ) + : _pluginRegistrar(pluginRegistrar), _textureRegistrar(textureRegistrar), + _width(width), _height(height), _D3D11Device(D3D11Device), + _D3D11DeviceContext(D3D11DeviceContext), _eglConfig(eglConfig), + _eglDisplay(eglDisplay), _eglContext(eglContext), _onResizeRequested(onResizeRequested) { + + auto d3d11_texture2D_desc = D3D11_TEXTURE2D_DESC{0}; + d3d11_texture2D_desc.Width = width; + d3d11_texture2D_desc.Height = height; + d3d11_texture2D_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + d3d11_texture2D_desc.MipLevels = 1; + d3d11_texture2D_desc.ArraySize = 1; + d3d11_texture2D_desc.SampleDesc.Count = 1; + d3d11_texture2D_desc.SampleDesc.Quality = 0; + d3d11_texture2D_desc.Usage = D3D11_USAGE_DEFAULT; + d3d11_texture2D_desc.BindFlags = + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + d3d11_texture2D_desc.CPUAccessFlags = 0; + d3d11_texture2D_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; + + // create internal texture + auto hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr, + &_internalD3DTexture2D); + if FAILED (hr) { + result->Error("ERROR", "Failed to create D3D texture", nullptr); + return; + ; + } + auto resource = Microsoft::WRL::ComPtr{}; + hr = _internalD3DTexture2D.As(&resource); + + if FAILED (hr) { + result->Error("ERROR", "Failed to create D3D texture", nullptr); + return; + ; + } + hr = resource->GetSharedHandle(&_internalD3DTextureHandle); + if FAILED (hr) { + result->Error("ERROR", "Failed to get shared handle to D3D texture", + nullptr); + return; + ; + } + _internalD3DTexture2D->AddRef(); + + std::cout << "Created internal D3D texture" << std::endl; + + // external + hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr, + &_externalD3DTexture2D); + if FAILED (hr) { + result->Error("ERROR", "Failed to create D3D texture", nullptr); + return; + ; + } + hr = _externalD3DTexture2D.As(&resource); + + if FAILED (hr) { + result->Error("ERROR", "Failed to create D3D texture", nullptr); + return; + ; + } + hr = resource->GetSharedHandle(&_externalD3DTextureHandle); + if FAILED (hr) { + result->Error("ERROR", + "Failed to get shared handle to external D3D texture", + nullptr); + return; + ; + } + _externalD3DTexture2D->AddRef(); + + std::cout << "Created external D3D texture" << std::endl; + + EGLint pbufferAttribs[] = { + EGL_WIDTH, width, EGL_HEIGHT, height, + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, + EGL_NONE, + }; + + _eglSurface = eglCreatePbufferFromClientBuffer( + _eglDisplay, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, + _internalD3DTextureHandle, _eglConfig, pbufferAttribs); + + if (!eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext)) { + // eglMakeCurrent failed + logEglError("eglMakeCurrent"); + return; + } + + glGenTextures(1, &glTextureId); + + if (glTextureId == 0) { + std::cout + << "Failed to generate OpenGL texture for ANGLE, OpenGL err was %d", + glGetError(); + return; + } + + glBindTexture(GL_TEXTURE_2D, glTextureId); + eglBindTexImage(_eglDisplay, _eglSurface, EGL_BACK_BUFFER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // clearGlError + GLenum const error = glGetError(); + if (error != GL_NO_ERROR) { + std::cout << "Ignoring pending GL error " << error << std::endl; + } + char const *version; + + version = (char const *)glGetString(GL_VERSION); + std::cout << "Got version " << version << std::endl; + + EGLint major, minor; + glGetIntegerv(GL_MAJOR_VERSION, &major); + glGetIntegerv(GL_MINOR_VERSION, &minor); + + _textureDescriptor = std::make_unique(); + _textureDescriptor->struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor); + _textureDescriptor->handle = _externalD3DTextureHandle; + _textureDescriptor->width = _textureDescriptor->visible_width = width; + _textureDescriptor->height = _textureDescriptor->visible_height = height; + _textureDescriptor->release_context = nullptr; + _textureDescriptor->release_callback = [](void *release_context) { + + }; + _textureDescriptor->format = kFlutterDesktopPixelFormatBGRA8888; + + texture = + std::make_unique(flutter::GpuSurfaceTexture( + kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle, + [&](size_t width, size_t height) { + if(width != this->_width || height != this->_height) { + this->_onResizeRequested(width, height); + } + return _textureDescriptor.get(); + })); + + flutterTextureId = _textureRegistrar->RegisterTexture(texture.get()); + std::cout << "Registered Flutter texture ID " << flutterTextureId + << std::endl; + + std::vector resultList; + resultList.push_back(flutter::EncodableValue(flutterTextureId)); + resultList.push_back(flutter::EncodableValue((int64_t) nullptr)); + resultList.push_back(flutter::EncodableValue(glTextureId)); + resultList.push_back(flutter::EncodableValue((int64_t) eglContext)); + result->Success(resultList); +} + +} // namespace flutter_filament \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/flutter_angle_texture.h b/flutter_filament_federated/flutter_filament/windows/flutter_angle_texture.h new file mode 100644 index 00000000..c207b7bb --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/flutter_angle_texture.h @@ -0,0 +1,80 @@ +#pragma once + +#ifndef _FLUTTER_ANGLE_TEXTURE_H +#define _FLUTTER_ANGLE_TEXTURE_H + +#include + +#include +#include +#include + +#include +#include + +#include "EGL/egl.h" +#include "EGL/eglext.h" +#include "EGL/eglplatform.h" +#include "GLES2/gl2.h" +#include "GLES2/gl2ext.h" +#include + +#include +#include + +#include "flutter_texture_buffer.h" + +typedef uint32_t GLuint; + +namespace flutter_filament { + +class FlutterAngleTexture : public FlutterTextureBuffer { + public: + FlutterAngleTexture( + flutter::PluginRegistrarWindows* pluginRegistrar, + flutter::TextureRegistrar* textureRegistrar, + std::unique_ptr> result, + uint32_t width, + uint32_t height, + ID3D11Device* D3D11Device, + ID3D11DeviceContext* D3D11DeviceContext, + EGLConfig eglConfig, + EGLDisplay eglDisplay, + EGLContext eglContext, + std::function onResizeRequested + ); + ~FlutterAngleTexture(); + + void RenderCallback(); + + GLuint glTextureId = 0; + std::unique_ptr texture; + + private: + flutter::PluginRegistrarWindows* _pluginRegistrar; + flutter::TextureRegistrar* _textureRegistrar; + uint32_t _width = 0; + uint32_t _height = 0; + bool logged = false; + std::function _onResizeRequested; + + // Device + ID3D11Device* _D3D11Device = nullptr; + ID3D11DeviceContext* _D3D11DeviceContext = nullptr; + // Texture objects/shared handles + Microsoft::WRL::ComPtr _externalD3DTexture2D; + Microsoft::WRL::ComPtr _internalD3DTexture2D; + HANDLE _externalD3DTextureHandle = nullptr; + HANDLE _internalD3DTextureHandle = nullptr; + + EGLDisplay _eglDisplay = EGL_NO_DISPLAY; + EGLContext _eglContext = EGL_NO_CONTEXT; + EGLConfig _eglConfig = EGL_NO_CONFIG_KHR; + EGLSurface _eglSurface = EGL_NO_SURFACE; + + std::unique_ptr _textureDescriptor = nullptr; + +}; + +} +#endif // _FLUTTER_ANGLE_TEXTURE \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin.cpp b/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin.cpp new file mode 100644 index 00000000..3670da36 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin.cpp @@ -0,0 +1,270 @@ +#pragma comment(lib, "dxgi.lib") +#pragma comment(lib, "d3d11.lib") + +#include "flutter_filament_plugin.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FlutterFilamentApi.h" + +#include "flutter_render_context.h" + +#if USE_ANGLE +#include "egl_context.h" +#else +#include "wgl_context.h" +#endif + +namespace flutter_filament { + + using namespace std::chrono_literals; + + +void FlutterFilamentPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + auto channel = + std::make_unique>( + registrar->messenger(), "app.polyvox.filament/event", + &flutter::StandardMethodCodec::GetInstance()); + + auto plugin = std::make_unique( + registrar->texture_registrar(), registrar, channel); + + registrar->AddPlugin(std::move(plugin)); +} + +FlutterFilamentPlugin::FlutterFilamentPlugin( + flutter::TextureRegistrar *textureRegistrar, + flutter::PluginRegistrarWindows *pluginRegistrar, + std::unique_ptr> &channel) + : _textureRegistrar(textureRegistrar), _pluginRegistrar(pluginRegistrar), + _channel(std::move(channel)) { + + // attach the method call handler for incoming messages + _channel->SetMethodCallHandler([=](const auto &call, auto result) { + std::cout << call.method_name() << std::endl; + this->HandleMethodCall(call, std::move(result)); + }); +} + + +FlutterFilamentPlugin::~FlutterFilamentPlugin() {} + +ResourceBuffer FlutterFilamentPlugin::loadResource(const char *name) { + + std::string name_str(name); + std::filesystem::path targetFilePath; + + if (name_str.rfind("file://", 0) == 0) { + targetFilePath = name_str.substr(7); + } else { + + if (name_str.rfind("asset://", 0) == 0) { + name_str = name_str.substr(8); + } + + TCHAR pBuf[512]; + size_t len = sizeof(pBuf); + int bytes = GetModuleFileName(NULL, pBuf, len); + std::wstring_convert> converter; + std::wstring assetPath = converter.from_bytes(name_str.c_str()); + + std::wstring exePathBuf(pBuf); + std::filesystem::path exePath(exePathBuf); + auto exeDir = exePath.remove_filename(); + targetFilePath = exeDir.wstring() + L"data/flutter_assets/" + assetPath; + } + std::streampos length; + + std::ifstream is(targetFilePath.c_str(), std::ios::binary); + if (!is) { + std::cout << "Failed to find resource at file path " << targetFilePath + << std::endl; + return ResourceBuffer(nullptr, 0, -1); + } + is.seekg(0, std::ios::end); + length = is.tellg(); + + char *buffer; + buffer = new char[length]; + is.seekg(0, std::ios::beg); + is.read(buffer, length); + is.close(); + auto id = _resources.size(); + auto rb = ResourceBuffer(buffer, length, id); + _resources.emplace(id, rb); + + std::wcout << "Loaded resource of length " << length << " from path " + << targetFilePath << std::endl; + + return rb; +} + +void FlutterFilamentPlugin::freeResource(ResourceBuffer rbuf) { + free((void *)rbuf.data); +} + +static ResourceBuffer _loadResource(const char *path, void *const plugin) { + return ((FlutterFilamentPlugin *)plugin)->loadResource(path); +} + +static void _freeResource(ResourceBuffer rbf, void *const plugin) { + ((FlutterFilamentPlugin *)plugin)->freeResource(rbf); +} + +// this is the C-style function that will be returned via getRenderCallback +// called on every frame by the FFI API +// this is just a convenient wrapper to call RenderCallback on the actual plugin +// instance +void render_callback(void *owner) { + ((FlutterFilamentPlugin *)owner)->RenderCallback(); +} + +// this is the method on FlutterFilamentPlugin that will copy between D3D +// textures +void FlutterFilamentPlugin::RenderCallback() { + if (_context) { + auto flutterTextureId = _context->GetFlutterTextureId(); + if(flutterTextureId == -1) { + std::cout << "Bad texture" << std::endl; + return; + } +#ifdef USE_ANGLE + _context->RenderCallback(); +#endif +#if !WGL_USE_BACKING_WINDOW + _textureRegistrar->MarkTextureFrameAvailable(flutterTextureId); +#endif + } +} + +void FlutterFilamentPlugin::CreateTexture( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + double dWidth = *(std::get_if(&(args->at(0)))); + double dHeight = *(std::get_if(&(args->at(1)))); + double dLeft = *(std::get_if(&(args->at(2)))); + double dTop = *(std::get_if(&(args->at(3)))); + auto width = (uint32_t)round(dWidth ); + auto height = (uint32_t)round(dHeight ); + auto left = (uint32_t)round(dLeft ); + auto top = (uint32_t)round(dTop ); + + std::cout << "Using " << width << "x" << height << std::endl; + + // create a single shared context for the life of the application + // this will be used to create a backing texture and passed to Filament + if (!_context) { +#ifdef USE_ANGLE + _context = std::make_unique(_pluginRegistrar, _textureRegistrar); +#else + _context = std::make_unique(_pluginRegistrar, _textureRegistrar); +#endif + } + _context->CreateRenderingSurface(width, height, std::move(result), left, top); +} + +void FlutterFilamentPlugin::DestroyTexture( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *flutterTextureId = std::get_if(methodCall.arguments()); + + if (!flutterTextureId) { + result->Error("NOT_IMPLEMENTED", "Flutter texture ID must be provided"); + return; + } + + if (_context) { + _context->DestroyTexture(std::move(result)); + } + else { + result->Error("NO_CONTEXT", "No rendering context is active"); + } + +} + +void FlutterFilamentPlugin::HandleMethodCall( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + if (methodCall.method_name() == "usesBackingWindow") { + result->Success(flutter::EncodableValue( + #ifdef WGL_USE_BACKING_WINDOW + true + #else + false + #endif + )); + } else if (methodCall.method_name() == "getResourceLoaderWrapper") { + const ResourceLoaderWrapper *const resourceLoader = + new ResourceLoaderWrapper(_loadResource, _freeResource, this); + result->Success(flutter::EncodableValue((int64_t)resourceLoader)); + } else if (methodCall.method_name() == "resizeWindow") { + #if WGL_USE_BACKING_WINDOW + const auto *args = + std::get_if(methodCall.arguments()); + double dWidth = *(std::get_if(&(args->at(0)))); + double dHeight = *(std::get_if(&(args->at(1)))); + double dLeft = *(std::get_if(&(args->at(2)))); + double dTop = *(std::get_if(&(args->at(3)))); + auto width = (uint32_t)round(dWidth ); + auto height = (uint32_t)round(dHeight ); + auto left = (uint32_t)round(dLeft ); + auto top = (uint32_t)round(dTop ); + _context->ResizeRenderingSurface(width, height, left, top); + result->Success(); + #else + result->Error("ERROR", "resizeWindow is only available when using a backing window"); + #endif + } else if (methodCall.method_name() == "createTexture") { + CreateTexture(methodCall, std::move(result)); + } else if (methodCall.method_name() == "destroyTexture") { + DestroyTexture(methodCall, std::move(result)); + } else if (methodCall.method_name() == "getRenderCallback") { + flutter::EncodableList resultList; + #if !ANGLE && WGL_USE_BACKING_WINDOW + resultList.push_back(flutter::EncodableValue((int64_t)nullptr)); + resultList.push_back(flutter::EncodableValue((int64_t)nullptr)); + #else + resultList.push_back(flutter::EncodableValue((int64_t)&render_callback)); + resultList.push_back(flutter::EncodableValue((int64_t)this)); + #endif + result->Success(resultList); + } else if (methodCall.method_name() == "getDriverPlatform") { +#ifdef USE_ANGLE + result->Success(flutter::EncodableValue((int64_t)_context->GetPlatform())); +#else + result->Success(flutter::EncodableValue((int64_t) nullptr)); +#endif + } else { + result->Error("NOT_IMPLEMENTED", "Method is not implemented %s", + methodCall.method_name()); + } +} + +} // namespace flutter_filament diff --git a/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin.h b/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin.h new file mode 100644 index 00000000..3b918fc1 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin.h @@ -0,0 +1,71 @@ +#ifndef FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ +#define FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ + +#include +#include + +#include +#include +#include + +#include +#include + +#include "GL/GL.h" +#include "GL/GLu.h" + +#include "FlutterFilamentApi.h" + +#if USE_ANGLE +#include "egl_context.h" +#else +#include "wgl_context.h" +#endif + +namespace flutter_filament { + +class FlutterFilamentPlugin : public flutter::Plugin { +public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + + FlutterFilamentPlugin(flutter::TextureRegistrar *textureRegistrar, + flutter::PluginRegistrarWindows *registrar, + std::unique_ptr>& channel); + virtual ~FlutterFilamentPlugin(); + + // Disallow copy and assign. + FlutterFilamentPlugin(const FlutterFilamentPlugin &) = delete; + FlutterFilamentPlugin &operator=(const FlutterFilamentPlugin &) = delete; + + // Called when a method is called on this plugin's channel from Dart. + void HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr> result); + + flutter::PluginRegistrarWindows *_pluginRegistrar; + flutter::TextureRegistrar *_textureRegistrar; + std::unique_ptr> _channel; + std::map _resources; + + void CreateTexture( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + void DestroyTexture( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + void RenderCallback(); + + ResourceBuffer loadResource(const char *path); + void freeResource(ResourceBuffer rbuf); + + private: + #ifdef USE_ANGLE + std::unique_ptr _context = nullptr; + #else + std::unique_ptr _context = nullptr; + #endif +}; + +} // namespace flutter_filament + +#endif // FLUTTER_PLUGIN_FLUTTER_FILAMENT_PLUGIN_H_ diff --git a/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin_c_api.cpp b/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin_c_api.cpp new file mode 100644 index 00000000..6338e1e3 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/flutter_filament_plugin_c_api.cpp @@ -0,0 +1,12 @@ +#include "include/flutter_filament/flutter_filament_plugin_c_api.h" + +#include + +#include "flutter_filament_plugin.h" + +void FlutterFilamentPluginCApiRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + flutter_filament::FlutterFilamentPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/flutter_filament_federated/flutter_filament/windows/flutter_render_context.h b/flutter_filament_federated/flutter_filament/windows/flutter_render_context.h new file mode 100644 index 00000000..16092891 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/flutter_render_context.h @@ -0,0 +1,53 @@ +#ifndef _FLUTTER_RENDER_CONTEXT_H +#define _FLUTTER_RENDER_CONTEXT_H + +#include +#include +#include +#include + +#include "flutter_texture_buffer.h" + +namespace flutter_filament { + + class FlutterRenderContext { + public: + + void CreateRenderingSurface(uint32_t width, uint32_t height, std::unique_ptr> result, uint32_t left, uint32_t top ); + + void DestroyTexture(std::unique_ptr> result) { + if (!_active) { + result->Success("Texture has already been detroyed, ignoring"); + return; + } + + auto sh = std::make_shared< + std::unique_ptr>>( + std::move(result)); + + _textureRegistrar->UnregisterTexture( + _active->flutterTextureId, [=, sharedResult = std::move(sh)]() { + this->_inactive = std::move(this->_active); + auto unique = std::move(*(sharedResult.get())); + unique->Success(flutter::EncodableValue(true)); + std::cout << "Unregistered/destroyed texture." << std::endl; + }); + } + int64_t GetFlutterTextureId() { + if(!_active) { + return -1; + } + return _active->flutterTextureId; + } + + protected: + FlutterRenderContext( flutter::PluginRegistrarWindows* pluginRegistrar, flutter::TextureRegistrar* textureRegistrar) : _pluginRegistrar(pluginRegistrar), _textureRegistrar(textureRegistrar) {}; + + flutter::PluginRegistrarWindows* _pluginRegistrar; + flutter::TextureRegistrar* _textureRegistrar; + std::unique_ptr _active = nullptr; + std::unique_ptr _inactive = nullptr; + }; +} + +#endif \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/flutter_texture_buffer.h b/flutter_filament_federated/flutter_filament/windows/flutter_texture_buffer.h new file mode 100644 index 00000000..3bf0c342 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/flutter_texture_buffer.h @@ -0,0 +1,18 @@ +#ifndef _FLUTTER_TEXTURE_BUFFER_H +#define _FLUTTER_TEXTURE_BUFFER_H + +#include +#include +#include +#include + + +namespace flutter_filament { + + class FlutterTextureBuffer { + public: + int64_t flutterTextureId = -1; + }; +} + +#endif \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/opengl_texture_buffer.cpp b/flutter_filament_federated/flutter_filament/windows/opengl_texture_buffer.cpp new file mode 100644 index 00000000..4b501b21 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/opengl_texture_buffer.cpp @@ -0,0 +1,144 @@ +#include "opengl_texture_buffer.h" + +#include +#include +#include +#include + +#include + +namespace flutter_filament { + +void _release_callback(void *releaseContext) { + // ((OpenGLTextureBuffer*)releaseContext)->unlock(); +} + +OpenGLTextureBuffer::OpenGLTextureBuffer( + flutter::PluginRegistrarWindows *pluginRegistrar, + flutter::TextureRegistrar *textureRegistrar, + std::unique_ptr> result, + uint32_t width, uint32_t height, HGLRC context) + : _pluginRegistrar(pluginRegistrar), _textureRegistrar(textureRegistrar), + _width(width), _height(height), _context(context) { + + HWND hwnd = _pluginRegistrar->GetView()->GetNativeWindow(); + + HDC whdc = GetDC(hwnd); + + if (!_context || !wglMakeCurrent(whdc, _context)) { + result->Error("ERROR", "Failed to switch OpenGL context in constructor."); + return; + } + + glGenTextures(1, &glTextureId); + + if (glTextureId == 0) { + result->Error("ERROR", "Failed to generate texture, OpenGL err was %d", + glGetError()); + return; + } + + glBindTexture(GL_TEXTURE_2D, glTextureId); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _width, _height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, 0); + + GLenum err = glGetError(); + + if (err != GL_NO_ERROR) { + result->Error("ERROR", "Failed to generate texture, GL error was %d", err); + return; + } + wglMakeCurrent(NULL, NULL); + + pixelBuffer = std::make_unique(); + pixelData.reset(new uint8_t[_width * _height * 4]); + + pixelBuffer->buffer = pixelData.get(); + pixelBuffer->width = size_t(_width); + pixelBuffer->height = size_t(_height); + pixelBuffer->release_callback = _release_callback; + pixelBuffer->release_context = this; + + std::cout << "Created initial pixel data/buffer of size " << _width << "x" + << _height << std::endl; + + texture = + std::make_unique(flutter::PixelBufferTexture( + [=](size_t width, + size_t height) -> const FlutterDesktopPixelBuffer * { + + if (width != this->_width || height != this->_height) { + if(!this->logged) { + std::cout << "Front-end widget expects " << width << "x" << height << " but this is " << this->_width << "x" << this->_height + << std::endl; + this->logged = true; + } + return nullptr; + } + uint8_t *data = (uint8_t *)pixelData.get(); + + if (!_context || !wglMakeCurrent(whdc, _context)) { + std::cout << "Failed to switch OpenGL context in callback." + << std::endl; + } else { + // It seems there's at least 1 frame delay between resizing a + // front-end widget and the layout operation being performed on + // Windows. I haven't found a way to guarantee that we can resize + // the OpenGL texture before the pixel buffer callback here. (If + // you can find/suggest a way, please let me know). This means we + // need to manually check that the requested size matches the + // current size of our GL texture, and return an empty pixel + // buffer if not. + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + GLenum err = glGetError(); + + if (err != GL_NO_ERROR) { + if (err == GL_INVALID_OPERATION) { + std::cout << "Invalid op" << std::endl; + } else if (err == GL_INVALID_VALUE) { + std::cout << "Invalid value" << std::endl; + } else if (err == GL_OUT_OF_MEMORY) { + std::cout << "Out of mem" << std::endl; + } else if (err == GL_INVALID_ENUM) { + std::cout << "Invalid enum" << std::endl; + } else { + std::cout << "Unknown error" << std::endl; + } + } + wglMakeCurrent(NULL, NULL); + } + pixelBuffer->buffer = pixelData.get(); + return pixelBuffer.get(); + })); + + flutterTextureId = textureRegistrar->RegisterTexture(texture.get()); + std::cout << "Registered Flutter texture ID " << flutterTextureId + << std::endl; + + if (flutterTextureId != -1) { + std::vector resultList; + resultList.push_back(flutter::EncodableValue(flutterTextureId)); + resultList.push_back(flutter::EncodableValue((int64_t) nullptr)); + resultList.push_back(flutter::EncodableValue(glTextureId)); + resultList.push_back(flutter::EncodableValue((int64_t)_context)); + result->Success(resultList); + } +} + +OpenGLTextureBuffer::~OpenGLTextureBuffer() { + HWND hwnd = _pluginRegistrar->GetView()->GetNativeWindow(); + HDC whdc = GetDC(hwnd); + + if (!wglMakeCurrent(whdc, _context)) { + std::cout << "Failed to switch OpenGL context in destructor." << std::endl; + // result->Error("CONTEXT", "Failed to switch OpenGL context.", nullptr); + return; + } + glDeleteTextures(1, &this->glTextureId); + wglMakeCurrent(NULL, NULL); +} + +} // namespace flutter_filament \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/opengl_texture_buffer.h b/flutter_filament_federated/flutter_filament/windows/opengl_texture_buffer.h new file mode 100644 index 00000000..a8001723 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/opengl_texture_buffer.h @@ -0,0 +1,51 @@ +#pragma once + +#ifndef _OPENGL_TEXTURE_BUFFER_H +#define _OPENGL_TEXTURE_BUFFER_H + +#include + +#include +#include +#include + +#include "GL/GL.h" +#include "GL/GLu.h" +#include "GL/wglext.h" + +#include +#include + +#include "flutter_texture_buffer.h" + +typedef uint32_t GLuint; + +namespace flutter_filament { + +class OpenGLTextureBuffer : public FlutterTextureBuffer { + public: + OpenGLTextureBuffer( + flutter::PluginRegistrarWindows* pluginRegistrar, + flutter::TextureRegistrar* textureRegistrar, + std::unique_ptr> result, + uint32_t width, + uint32_t height, + HGLRC context); + + ~OpenGLTextureBuffer(); + GLuint glTextureId = 0; + std::unique_ptr pixelBuffer; + std::unique_ptr pixelData; + std::unique_ptr texture; + + private: + flutter::PluginRegistrarWindows* _pluginRegistrar; + flutter::TextureRegistrar* _textureRegistrar; + uint32_t _width = 0; + uint32_t _height = 0; + HGLRC _context = NULL; + bool logged = false; +}; + +} +#endif // _OPENGL_TEXTURE_BUFFER_H \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament/windows/test/flutter_filament_plugin_test.cpp b/flutter_filament_federated/flutter_filament/windows/test/flutter_filament_plugin_test.cpp new file mode 100644 index 00000000..af331fb5 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/test/flutter_filament_plugin_test.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "flutter_filament_plugin.h" + +namespace flutter_filament { +namespace test { + +namespace { + +using flutter::EncodableMap; +using flutter::EncodableValue; +using flutter::MethodCall; +using flutter::MethodResultFunctions; + +} // namespace + +TEST(FlutterFilamentPlugin, GetPlatformVersion) { + FlutterFilamentPlugin plugin; + // Save the reply value from the success callback. + std::string result_string; + plugin.HandleMethodCall( + MethodCall("getPlatformVersion", std::make_unique()), + std::make_unique>( + [&result_string](const EncodableValue* result) { + result_string = std::get(*result); + }, + nullptr, nullptr)); + + // Since the exact string varies by host, just ensure that it's a string + // with the expected format. + EXPECT_TRUE(result_string.rfind("Windows ", 0) == 0); +} + +} // namespace test +} // namespace flutter_filament diff --git a/flutter_filament_federated/flutter_filament/windows/wgl_context.cpp b/flutter_filament_federated/flutter_filament/windows/wgl_context.cpp new file mode 100644 index 00000000..b9d88737 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/wgl_context.cpp @@ -0,0 +1,147 @@ +#include "wgl_context.h" + +#ifdef WGL_USE_BACKING_WINDOW +#include "backing_window.h" +#endif + +#include "flutter_texture_buffer.h" + +namespace flutter_filament { + +WGLContext::WGLContext(flutter::PluginRegistrarWindows *pluginRegistrar, + flutter::TextureRegistrar *textureRegistrar) + : FlutterRenderContext(pluginRegistrar, textureRegistrar) { + + #if WGL_USE_BACKING_WINDOW + return; + #endif + + auto hwnd = pluginRegistrar->GetView()->GetNativeWindow(); + + HDC whdc = GetDC(hwnd); + if (whdc == NULL) { + std::cout << "No device context for temporary window" << std::endl; + return; + } + + std::cout << "No GL context exists, creating" << std::endl; + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags + PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. + 24, // Colordepth of the framebuffer. + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 16, // Number of bits for the depthbuffer + 0, // Number of bits for the stencilbuffer + 0, // Number of Aux buffers in the framebuffer. + PFD_MAIN_PLANE, + 0, + 0, + 0, + 0}; + + int pixelFormat = ChoosePixelFormat(whdc, &pfd); + SetPixelFormat(whdc, pixelFormat, &pfd); + + // We need a tmp context to retrieve and call wglCreateContextAttribsARB. + HGLRC tempContext = wglCreateContext(whdc); + if (!wglMakeCurrent(whdc, tempContext)) { + std::cout << "Failed to acquire temporary context" << std::endl; + return; + } + + GLenum err = glGetError(); + + if (err != GL_NO_ERROR) { + std::cout << "GL Error @ 455 %d" << std::endl; + return; + } + + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr; + + wglCreateContextAttribs = + (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress( + "wglCreateContextAttribsARB"); + + if (!wglCreateContextAttribs) { + std::cout << "Failed to resolve wglCreateContextAttribsARB" << std::endl; + return; + } + + for (int minor = 5; minor >= 1; minor--) { + std::vector mAttribs = {WGL_CONTEXT_MAJOR_VERSION_ARB, 4, + WGL_CONTEXT_MINOR_VERSION_ARB, minor, 0}; + _context = wglCreateContextAttribs(whdc, nullptr, mAttribs.data()); + if (_context) { + break; + } + } + + wglMakeCurrent(NULL, NULL); + wglDeleteContext(tempContext); + + if (!_context || !wglMakeCurrent(whdc, _context)) { + std::cout << "Failed to create OpenGL context." << std::endl; + return; + } +} + +void WGLContext::ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) { + #if WGL_USE_BACKING_WINDOW + _backingWindow->Resize(width, height, left, top); + #endif +} + +void WGLContext::CreateRenderingSurface( + uint32_t width, uint32_t height, + std::unique_ptr> result, uint32_t left, uint32_t top) { + +#if WGL_USE_BACKING_WINDOW + if(!_backingWindow) { + _backingWindow = std::make_unique( + _pluginRegistrar, static_cast(width), static_cast(height), static_cast(left), static_cast(top)); + } else { + ResizeRenderingSurface(width, height, left, top); + } + std::vector resultList; + resultList.push_back(flutter::EncodableValue((int64_t) nullptr)); + resultList.push_back( + flutter::EncodableValue((int64_t)_backingWindow->GetHandle())); + resultList.push_back(flutter::EncodableValue((int64_t) nullptr)); + resultList.push_back(flutter::EncodableValue((int64_t)_context)); + result->Success(resultList); +#else + if(left != 0 || top != 0) { + result->Error("ERROR", + "When WGL_USE_BACKING_WINDOW is false, rendering with WGL uses a Texture render target/Flutter widget and does not need a window offset."); + } else if (_active.get()) { + result->Error("ERROR", + "Texture already exists. You must call destroyTexture before " + "attempting to create a new one."); + + } else { + auto active = std::make_unique( + _pluginRegistrar, _textureRegistrar, std::move(result), width, height, + _context); + _active = std::move(active); + } +#endif +} + +void *WGLContext::GetSharedContext() { return (void *)_context; } + +} // namespace flutter_filament diff --git a/flutter_filament_federated/flutter_filament/windows/wgl_context.h b/flutter_filament_federated/flutter_filament/windows/wgl_context.h new file mode 100644 index 00000000..33406180 --- /dev/null +++ b/flutter_filament_federated/flutter_filament/windows/wgl_context.h @@ -0,0 +1,30 @@ +#ifndef _WGL_CONTEXT_H +#define _WGL_CONTEXT_H + +#include +#include "opengl_texture_buffer.h" +#include "flutter_render_context.h" +#if WGL_USE_BACKING_WINDOW +#include "backing_window.h" +#endif +namespace flutter_filament { + + class WGLContext : public FlutterRenderContext { + public: + WGLContext(flutter::PluginRegistrarWindows* pluginRegistrar, flutter::TextureRegistrar* textureRegistrar); + void* GetSharedContext(); + void CreateRenderingSurface( + uint32_t width, uint32_t height, + std::unique_ptr> result, uint32_t left, uint32_t top); + void ResizeRenderingSurface( + uint32_t width, uint32_t height, uint32_t left, uint32_t top + ); + private: + HGLRC _context = NULL; + #if WGL_USE_BACKING_WINDOW + std::unique_ptr _backingWindow = nullptr; + #endif + }; + +} +#endif \ No newline at end of file diff --git a/flutter_filament_federated/flutter_filament_ffi/lib/flutter_filament_ffi.dart b/flutter_filament_federated/flutter_filament_ffi/lib/flutter_filament_ffi.dart new file mode 100644 index 00000000..a2c93097 --- /dev/null +++ b/flutter_filament_federated/flutter_filament_ffi/lib/flutter_filament_ffi.dart @@ -0,0 +1,132 @@ +import 'dart:async'; +import 'package:flutter/services.dart'; +import 'dart:ffi'; +import 'package:dart_filament/dart_filament.dart'; +import 'package:flutter_filament_platform_interface/flutter_filament_platform_interface.dart'; +import 'package:flutter_filament_platform_interface/flutter_filament_texture.dart'; + +/// +/// A subclass of [FilamentViewer] that uses Flutter platform channels +/// to create rendering contexts, callbacks and surfaces (either backing texture(s). +/// +class FlutterFilamentFFI extends FlutterFilamentPlatform { + final _channel = const MethodChannel("app.polyvox.filament/event"); + + late final FilamentViewer viewer; + + static void registerWith() { + FlutterFilamentPlatform.instance = FlutterFilamentFFI(); + } + + Future initialize({String? uberArchivePath}) async { + var resourceLoader = Pointer.fromAddress( + await _channel.invokeMethod("getResourceLoaderWrapper")); + + if (resourceLoader == nullptr) { + throw Exception("Failed to get resource loader"); + } + + var renderCallbackResult = await _channel.invokeMethod("getRenderCallback"); + var renderCallback = + Pointer)>>.fromAddress( + renderCallbackResult[0]); + var renderCallbackOwner = + Pointer.fromAddress(renderCallbackResult[1]); + + var driverPlatform = await _channel.invokeMethod("getDriverPlatform"); + var driverPtr = driverPlatform == null + ? nullptr + : Pointer.fromAddress(driverPlatform); + + var sharedContext = await _channel.invokeMethod("getSharedContext"); + + var sharedContextPtr = sharedContext == null + ? nullptr + : Pointer.fromAddress(sharedContext); + + viewer = FilamentViewer( + resourceLoader: resourceLoader, + renderCallback: renderCallback, + renderCallbackOwner: renderCallbackOwner, + driver: driverPtr, + sharedContext: sharedContextPtr, + uberArchivePath: uberArchivePath); + + // var plugin = FlutterFilamentFFI._(channel, + // renderCallback: renderCallback, + // renderCallbackOwner: renderCallbackOwner, + // resourceLoader: resourceLoader, + // driver: driverPtr, + // sharedContext: sharedContextPtr, + // uberArchivePath: uberArchivePath); + } + + Future createTexture( + int width, int height, int offsetLeft, int offsetRight) async { + var result = await _channel + .invokeMethod("createTexture", [width, height, offsetLeft, offsetLeft]); + + if (result == null || result[0] == -1) { + throw Exception("Failed to create texture"); + } + viewer.viewportDimensions = (width.toDouble(), height.toDouble()); + var texture = + FlutterFilamentTexture(result[0], result[1], width, height, result[2]); + + await viewer.createSwapChain(width.toDouble(), height.toDouble(), + surface: texture.surfaceAddress == null ? nullptr : Pointer.fromAddress(texture.surfaceAddress!)); + + if (texture.hardwareTextureId != null) { + var renderTarget = await viewer.createRenderTarget( + width.toDouble(), height.toDouble(), texture.hardwareTextureId!); + } + await viewer.updateViewportAndCameraProjection( + width.toDouble(), height.toDouble()); + viewer.render(); + return texture; + } + + Future destroyTexture(FlutterFilamentTexture texture) async { + await _channel.invokeMethod("destroyTexture", texture.flutterTextureId); + } + + @override + Future resizeTexture(FlutterFilamentTexture texture, + int width, int height, int offsetLeft, int offsetRight) async { + if ((width - viewer.viewportDimensions.$1).abs() < 0.001 || + (height - viewer.viewportDimensions.$2).abs() < 0.001) { + return texture; + } + bool wasRendering = viewer.rendering; + await viewer.setRendering(false); + await viewer.destroySwapChain(); + await destroyTexture(texture); + + var newTexture = + await createTexture(width, height, offsetLeft, offsetRight); + if (newTexture == null || newTexture.flutterTextureId == -1) { + throw Exception("Failed to create texture"); + } + await viewer.createSwapChain(width.toDouble(), height.toDouble(), + surface: Pointer.fromAddress(newTexture.surfaceAddress!)); + + if (newTexture!.hardwareTextureId != null) { + await viewer.createRenderTarget( + width.toDouble(), height.toDouble(), newTexture!.hardwareTextureId!); + } + await viewer.updateViewportAndCameraProjection( + width.toDouble(), height.toDouble()); + viewer.viewportDimensions = (width.toDouble(), height.toDouble()); + if (wasRendering) { + await viewer.setRendering(true); + } + return newTexture; + // await _channel.invokeMethod("resizeTexture", + // [texture.flutterTextureId, width, height, offsetLeft, offsetRight]); + } + + @override + void dispose() { + // TODO: implement dispose + } +} diff --git a/flutter_filament_federated/flutter_filament_ffi/pubspec.lock b/flutter_filament_federated/flutter_filament_ffi/pubspec.lock new file mode 100644 index 00000000..cb1edde6 --- /dev/null +++ b/flutter_filament_federated/flutter_filament_ffi/pubspec.lock @@ -0,0 +1,416 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "5aaf60d96c4cd00fe7f21594b5ad6a1b699c80a27420f8a837f4d68473ef09e3" + url: "https://pub.dev" + source: hosted + version: "68.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.1.3" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "21f1d3720fd1c70316399d5e2bccaebb415c434592d778cce8acb967b8578808" + url: "https://pub.dev" + source: hosted + version: "6.5.0" + animation_tools_dart: + dependency: transitive + description: + name: animation_tools_dart + sha256: c4bc4096d43227b573345a3ea3cb26c3af47a70af31cd7d7d3a5b7c99e33d615 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + dart_filament: + dependency: transitive + description: + path: "../../dart_filament" + relative: true + source: path + version: "0.5.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + url: "https://pub.dev" + source: hosted + version: "2.3.6" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_filament_platform_interface: + dependency: "direct main" + description: + path: "../flutter_filament_platform_interface" + relative: true + source: path + version: "0.0.1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + macros: + dependency: transitive + description: + name: macros + sha256: e4a273c4a7a81fdbea1f3faed45faa6a7c0b78a50076e89d3f02350caefc8939 + url: "https://pub.dev" + source: hosted + version: "0.1.0-main.3" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "25dfcaf170a0190f47ca6355bdd4552cb8924b430512ff0cafb8db9bd41fe33b" + url: "https://pub.dev" + source: hosted + version: "1.14.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + plugin_platform_interface: + dependency: "direct main" + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "2419f20b0c8677b2d67c8ac4d1ac7372d862dc6c460cdbb052b40155408cd794" + url: "https://pub.dev" + source: hosted + version: "0.7.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "7475cb4dd713d57b6f7464c0e13f06da0d535d8b2067e188962a59bac2cf280b" + url: "https://pub.dev" + source: hosted + version: "14.2.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.4.0-256.0.dev <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/flutter_filament_federated/flutter_filament_ffi/pubspec.yaml b/flutter_filament_federated/flutter_filament_ffi/pubspec.yaml new file mode 100644 index 00000000..19d5d6a2 --- /dev/null +++ b/flutter_filament_federated/flutter_filament_ffi/pubspec.yaml @@ -0,0 +1,31 @@ +name: flutter_filament_ffi +description: An FFI interface for the flutter_filament plugin (all platforms except web). +repository: https://github.com/nmfisher/flutter_filament/flutter_filament +version: 0.0.1 + +environment: + sdk: ">=3.3.0 <4.0.0" + flutter: ">=3.0.0" +flutter: + plugin: + implements: flutter_filament_platform_interface + platforms: + ios: + dartPluginClass: FlutterFilamentFFI + android: + dartPluginClass: FlutterFilamentFFI + macos: + dartPluginClass: FlutterFilamentFFI + windows: + dartPluginClass: FlutterFilamentFFI +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.1.0 + flutter_filament_platform_interface: + path: ../flutter_filament_platform_interface + +dev_dependencies: + flutter_test: + sdk: flutter + mockito: ^5.0.0 diff --git a/flutter_filament_federated/flutter_filament_platform_interface/README.md b/flutter_filament_federated/flutter_filament_platform_interface/README.md new file mode 100644 index 00000000..e69de29b diff --git a/flutter_filament_federated/flutter_filament_platform_interface/lib/flutter_filament_platform_interface.dart b/flutter_filament_federated/flutter_filament_platform_interface/lib/flutter_filament_platform_interface.dart new file mode 100644 index 00000000..49bfe92d --- /dev/null +++ b/flutter_filament_federated/flutter_filament_platform_interface/lib/flutter_filament_platform_interface.dart @@ -0,0 +1,35 @@ +import 'dart:async'; + +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'flutter_filament_texture.dart'; + +abstract class FlutterFilamentPlatform extends PlatformInterface { + FlutterFilamentPlatform() : super(token: _token); + + static final Object _token = Object(); + + static late FlutterFilamentPlatform _instance; + + static FlutterFilamentPlatform get instance => _instance; + + static set instance(FlutterFilamentPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + AbstractFilamentViewer get viewer; + + Future initialize({String? uberArchivePath}); + + Future createTexture( + int width, int height, int offsetLeft, int offsetRight); + + Future destroyTexture(FlutterFilamentTexture texture); + + @override + Future resizeTexture(FlutterFilamentTexture texture, + int width, int height, int offsetLeft, int offsetRight); + + void dispose(); +} diff --git a/flutter_filament_federated/flutter_filament_platform_interface/lib/flutter_filament_texture.dart b/flutter_filament_federated/flutter_filament_platform_interface/lib/flutter_filament_texture.dart new file mode 100644 index 00000000..2ededb70 --- /dev/null +++ b/flutter_filament_federated/flutter_filament_platform_interface/lib/flutter_filament_texture.dart @@ -0,0 +1,15 @@ +class FlutterFilamentTexture { + final int width; + final int height; + final int flutterTextureId; + final int? hardwareTextureId; + final int? surfaceAddress; + + FlutterFilamentTexture(this.flutterTextureId, this.hardwareTextureId, + this.width, this.height, this.surfaceAddress) { + // surface = surfaceAddress + // if (surfaceAddress != null) { + // surface = Pointer.fromAddress(surfaceAddress!); + // } + } +} diff --git a/flutter_filament_federated/flutter_filament_platform_interface/pubspec.lock b/flutter_filament_federated/flutter_filament_platform_interface/pubspec.lock new file mode 100644 index 00000000..818d5d00 --- /dev/null +++ b/flutter_filament_federated/flutter_filament_platform_interface/pubspec.lock @@ -0,0 +1,409 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "5aaf60d96c4cd00fe7f21594b5ad6a1b699c80a27420f8a837f4d68473ef09e3" + url: "https://pub.dev" + source: hosted + version: "68.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.1.3" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "21f1d3720fd1c70316399d5e2bccaebb415c434592d778cce8acb967b8578808" + url: "https://pub.dev" + source: hosted + version: "6.5.0" + animation_tools_dart: + dependency: transitive + description: + name: animation_tools_dart + sha256: c4bc4096d43227b573345a3ea3cb26c3af47a70af31cd7d7d3a5b7c99e33d615 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + dart_filament: + dependency: "direct main" + description: + path: "../../dart_filament" + relative: true + source: path + version: "0.5.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + url: "https://pub.dev" + source: hosted + version: "2.3.6" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + macros: + dependency: transitive + description: + name: macros + sha256: e4a273c4a7a81fdbea1f3faed45faa6a7c0b78a50076e89d3f02350caefc8939 + url: "https://pub.dev" + source: hosted + version: "0.1.0-main.3" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "25dfcaf170a0190f47ca6355bdd4552cb8924b430512ff0cafb8db9bd41fe33b" + url: "https://pub.dev" + source: hosted + version: "1.14.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + plugin_platform_interface: + dependency: "direct main" + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "2419f20b0c8677b2d67c8ac4d1ac7372d862dc6c460cdbb052b40155408cd794" + url: "https://pub.dev" + source: hosted + version: "0.7.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "7475cb4dd713d57b6f7464c0e13f06da0d535d8b2067e188962a59bac2cf280b" + url: "https://pub.dev" + source: hosted + version: "14.2.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.4.0-256.0.dev <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/flutter_filament_federated/flutter_filament_platform_interface/pubspec.yaml b/flutter_filament_federated/flutter_filament_platform_interface/pubspec.yaml new file mode 100644 index 00000000..f59163fd --- /dev/null +++ b/flutter_filament_federated/flutter_filament_platform_interface/pubspec.yaml @@ -0,0 +1,20 @@ +name: flutter_filament_platform_interface +description: A common platform interface for the flutter_filament plugin. +repository: https://github.com/nmfisher/flutter_filament/flutter_filament +version: 0.0.1 + +environment: + sdk: ">=3.3.0 <4.0.0" + flutter: ">=3.0.0" + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.1.0 + dart_filament: + path: ../../dart_filament + +dev_dependencies: + flutter_test: + sdk: flutter + mockito: ^5.0.0 diff --git a/flutter_filament_federated/flutter_filament_web/lib/flutter_filament_web.dart b/flutter_filament_federated/flutter_filament_web/lib/flutter_filament_web.dart new file mode 100644 index 00000000..75ceefbc --- /dev/null +++ b/flutter_filament_federated/flutter_filament_web/lib/flutter_filament_web.dart @@ -0,0 +1,41 @@ +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:flutter_filament_platform_interface/flutter_filament_platform_interface.dart'; +import 'package:flutter_filament_platform_interface/flutter_filament_texture.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:dart_filament/dart_filament/compatibility/web/interop/dart_filament_js_extension_type.dart'; +import 'package:dart_filament/dart_filament/compatibility/web/interop/js_interop_filament_viewer.dart'; + +class FlutterFilamentWebPlugin extends FlutterFilamentPlatform { + static void registerWith(Registrar registrar) { + FlutterFilamentPlatform.instance = FlutterFilamentWebPlugin(); + } + + @override + Future createTexture( + int width, int height, int offsetLeft, int offsetRight) async {} + + @override + Future destroyTexture(FlutterFilamentTexture texture) async {} + + @override + void dispose() { + // TODO: implement dispose + } + + @override + Future initialize({String? uberArchivePath}) async { + print("Creating viewer in web plugin"); + viewer = JsInteropFilamentViewer("filamentViewer"); + print("Waiting for initialized"); + await viewer.initialized; + print("int complete"); + } + + @override + Future resizeTexture(FlutterFilamentTexture texture, + int width, int height, int offsetLeft, int offsetRight) async {} + + @override + // TODO: implement viewer + late final AbstractFilamentViewer viewer; +} diff --git a/flutter_filament_federated/flutter_filament_web/pubspec.lock b/flutter_filament_federated/flutter_filament_web/pubspec.lock new file mode 100644 index 00000000..3fd78658 --- /dev/null +++ b/flutter_filament_federated/flutter_filament_web/pubspec.lock @@ -0,0 +1,421 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "5aaf60d96c4cd00fe7f21594b5ad6a1b699c80a27420f8a837f4d68473ef09e3" + url: "https://pub.dev" + source: hosted + version: "68.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.1.3" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "21f1d3720fd1c70316399d5e2bccaebb415c434592d778cce8acb967b8578808" + url: "https://pub.dev" + source: hosted + version: "6.5.0" + animation_tools_dart: + dependency: transitive + description: + name: animation_tools_dart + sha256: c4bc4096d43227b573345a3ea3cb26c3af47a70af31cd7d7d3a5b7c99e33d615 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + dart_filament: + dependency: "direct main" + description: + path: "../../dart_filament" + relative: true + source: path + version: "0.5.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + url: "https://pub.dev" + source: hosted + version: "2.3.6" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_filament_platform_interface: + dependency: "direct main" + description: + path: "../flutter_filament_platform_interface" + relative: true + source: path + version: "0.0.1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + macros: + dependency: transitive + description: + name: macros + sha256: e4a273c4a7a81fdbea1f3faed45faa6a7c0b78a50076e89d3f02350caefc8939 + url: "https://pub.dev" + source: hosted + version: "0.1.0-main.3" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "25dfcaf170a0190f47ca6355bdd4552cb8924b430512ff0cafb8db9bd41fe33b" + url: "https://pub.dev" + source: hosted + version: "1.14.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + plugin_platform_interface: + dependency: "direct main" + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "2419f20b0c8677b2d67c8ac4d1ac7372d862dc6c460cdbb052b40155408cd794" + url: "https://pub.dev" + source: hosted + version: "0.7.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "7475cb4dd713d57b6f7464c0e13f06da0d535d8b2067e188962a59bac2cf280b" + url: "https://pub.dev" + source: hosted + version: "14.2.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.4.0-256.0.dev <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/flutter_filament_federated/flutter_filament_web/pubspec.yaml b/flutter_filament_federated/flutter_filament_web/pubspec.yaml new file mode 100644 index 00000000..570f9899 --- /dev/null +++ b/flutter_filament_federated/flutter_filament_web/pubspec.yaml @@ -0,0 +1,33 @@ +name: flutter_filament_web +description: A web platform interface for the flutter_filament plugin. +repository: https://github.com/nmfisher/flutter_filament/flutter_filament +version: 0.0.1 + +environment: + sdk: ">=3.3.0 <4.0.0" + flutter: ">=3.0.0" + +flutter: + plugin: + implements: flutter_filament_platform_interface + platforms: + web: + pluginClass: FlutterFilamentWebPlugin + fileName: flutter_filament_web.dart + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.1.0 + web: + dart_filament: + path: ../../dart_filament + flutter_filament_platform_interface: + path: ../flutter_filament_platform_interface + flutter_web_plugins: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + mockito: ^5.0.0 diff --git a/flutter_filament_federated/web_test/.gitignore b/flutter_filament_federated/web_test/.gitignore new file mode 100644 index 00000000..29a3a501 --- /dev/null +++ b/flutter_filament_federated/web_test/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/flutter_filament_federated/web_test/.metadata b/flutter_filament_federated/web_test/.metadata new file mode 100644 index 00000000..513eb675 --- /dev/null +++ b/flutter_filament_federated/web_test/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "607a3dad768d326fb9fb1ac24e6a2fc92303a6ab" + channel: "master" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 607a3dad768d326fb9fb1ac24e6a2fc92303a6ab + base_revision: 607a3dad768d326fb9fb1ac24e6a2fc92303a6ab + - platform: web + create_revision: 607a3dad768d326fb9fb1ac24e6a2fc92303a6ab + base_revision: 607a3dad768d326fb9fb1ac24e6a2fc92303a6ab + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter_filament_federated/web_test/README.md b/flutter_filament_federated/web_test/README.md new file mode 100644 index 00000000..7a234da4 --- /dev/null +++ b/flutter_filament_federated/web_test/README.md @@ -0,0 +1,16 @@ +# web_test + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/flutter_filament_federated/web_test/analysis_options.yaml b/flutter_filament_federated/web_test/analysis_options.yaml new file mode 100644 index 00000000..0d290213 --- /dev/null +++ b/flutter_filament_federated/web_test/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/flutter_filament_federated/web_test/lib/main.dart b/flutter_filament_federated/web_test/lib/main.dart new file mode 100644 index 00000000..31a0f39a --- /dev/null +++ b/flutter_filament_federated/web_test/lib/main.dart @@ -0,0 +1,725 @@ +import 'package:animation_tools_dart/src/bone_animation_data.dart'; +import 'package:animation_tools_dart/src/morph_animation_data.dart'; +import 'package:dart_filament/dart_filament/abstract_filament_viewer.dart'; +import 'package:dart_filament/dart_filament/entities/filament_entity.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_filament/filament/flutter_filament_plugin.dart'; +import 'package:vector_math/vector_math_64.dart'; + +// class FooViewer extends AbstractFilamentViewer { +// @override +// Future addAnimationComponent(FilamentEntity entity) { +// // TODO: implement addAnimationComponent +// throw UnimplementedError(); +// } + +// @override +// Future addBoneAnimation(FilamentEntity entity, BoneAnimationData animation) { +// // TODO: implement addBoneAnimation +// throw UnimplementedError(); +// } + +// @override +// Future addCollisionComponent(FilamentEntity entity, {void Function(int entityId1, int entityId2)? callback, bool affectsTransform = false}) { +// // TODO: implement addCollisionComponent +// throw UnimplementedError(); +// } + +// @override +// Future addLight(int type, double colour, double intensity, double posX, double posY, double posZ, double dirX, double dirY, double dirZ, bool castShadows) { +// // TODO: implement addLight +// throw UnimplementedError(); +// } + +// @override +// Future clearBackgroundImage() { +// // TODO: implement clearBackgroundImage +// throw UnimplementedError(); +// } + +// @override +// Future clearEntities() { +// // TODO: implement clearEntities +// throw UnimplementedError(); +// } + +// @override +// Future clearLights() { +// // TODO: implement clearLights +// throw UnimplementedError(); +// } + +// @override +// Future createGeometry(List vertices, List indices, {String? materialPath, PrimitiveType primitiveType = PrimitiveType.TRIANGLES}) { +// // TODO: implement createGeometry +// throw UnimplementedError(); +// } + +// @override +// Future createInstance(FilamentEntity entity) { +// // TODO: implement createInstance +// throw UnimplementedError(); +// } + +// @override +// Future dispose() { +// // TODO: implement dispose +// throw UnimplementedError(); +// } + +// @override +// Future getAnimationDuration(FilamentEntity entity, int animationIndex) { +// // TODO: implement getAnimationDuration +// throw UnimplementedError(); +// } + +// @override +// Future> getAnimationNames(FilamentEntity entity) { +// // TODO: implement getAnimationNames +// throw UnimplementedError(); +// } + +// @override +// Future getCameraCullingFar() { +// // TODO: implement getCameraCullingFar +// throw UnimplementedError(); +// } + +// @override +// Future getCameraCullingNear() { +// // TODO: implement getCameraCullingNear +// throw UnimplementedError(); +// } + +// @override +// Future getCameraCullingProjectionMatrix() { +// // TODO: implement getCameraCullingProjectionMatrix +// throw UnimplementedError(); +// } + +// @override +// Future getCameraFrustum() { +// // TODO: implement getCameraFrustum +// throw UnimplementedError(); +// } + +// @override +// Future getCameraModelMatrix() { +// // TODO: implement getCameraModelMatrix +// throw UnimplementedError(); +// } + +// @override +// Future getCameraPosition() { +// // TODO: implement getCameraPosition +// throw UnimplementedError(); +// } + +// @override +// Future getCameraProjectionMatrix() { +// // TODO: implement getCameraProjectionMatrix +// throw UnimplementedError(); +// } + +// @override +// Future getCameraRotation() { +// // TODO: implement getCameraRotation +// throw UnimplementedError(); +// } + +// @override +// Future getCameraViewMatrix() { +// // TODO: implement getCameraViewMatrix +// throw UnimplementedError(); +// } + +// @override +// Future> getChildEntities(FilamentEntity parent, bool renderableOnly) { +// // TODO: implement getChildEntities +// throw UnimplementedError(); +// } + +// @override +// Future getChildEntity(FilamentEntity parent, String childName) { +// // TODO: implement getChildEntity +// throw UnimplementedError(); +// } + +// @override +// Future> getChildEntityNames(FilamentEntity entity, {bool renderableOnly = true}) { +// // TODO: implement getChildEntityNames +// throw UnimplementedError(); +// } + +// @override +// Future getInstanceCount(FilamentEntity entity) { +// // TODO: implement getInstanceCount +// throw UnimplementedError(); +// } + +// @override +// Future> getInstances(FilamentEntity entity) { +// // TODO: implement getInstances +// throw UnimplementedError(); +// } + +// @override +// Future getMainCamera() { +// // TODO: implement getMainCamera +// throw UnimplementedError(); +// } + +// @override +// Future> getMorphTargetNames(FilamentEntity entity, String meshName) { +// // TODO: implement getMorphTargetNames +// throw UnimplementedError(); +// } + +// @override +// String? getNameForEntity(FilamentEntity entity) { +// // TODO: implement getNameForEntity +// throw UnimplementedError(); +// } + +// @override +// Future hide(FilamentEntity entity, String? meshName) { +// // TODO: implement hide +// throw UnimplementedError(); +// } + +// @override +// Future loadGlb(String path, {int numInstances = 1}) { +// // TODO: implement loadGlb +// throw UnimplementedError(); +// } + +// @override +// Future loadGltf(String path, String relativeResourcePath, {bool force = false}) { +// // TODO: implement loadGltf +// throw UnimplementedError(); +// } + +// @override +// Future loadIbl(String lightingPath, {double intensity = 30000}) { +// // TODO: implement loadIbl +// throw UnimplementedError(); +// } + +// @override +// Future loadSkybox(String skyboxPath) { +// // TODO: implement loadSkybox +// throw UnimplementedError(); +// } + +// @override +// Future moveCameraToAsset(FilamentEntity entity) { +// // TODO: implement moveCameraToAsset +// throw UnimplementedError(); +// } + +// @override +// Future panEnd() { +// // TODO: implement panEnd +// throw UnimplementedError(); +// } + +// @override +// Future panStart(double x, double y) { +// // TODO: implement panStart +// throw UnimplementedError(); +// } + +// @override +// Future panUpdate(double x, double y) { +// // TODO: implement panUpdate +// throw UnimplementedError(); +// } + +// @override +// void pick(int x, int y) { +// // TODO: implement pick +// } + +// @override +// // TODO: implement pickResult +// Stream get pickResult => throw UnimplementedError(); + +// @override +// Future playAnimation(FilamentEntity entity, int index, {bool loop = false, bool reverse = false, bool replaceActive = true, double crossfade = 0.0}) { +// // TODO: implement playAnimation +// throw UnimplementedError(); +// } + +// @override +// Future playAnimationByName(FilamentEntity entity, String name, {bool loop = false, bool reverse = false, bool replaceActive = true, double crossfade = 0.0}) { +// // TODO: implement playAnimationByName +// throw UnimplementedError(); +// } + +// @override +// Future queuePositionUpdate(FilamentEntity entity, double x, double y, double z, {bool relative = false}) { +// // TODO: implement queuePositionUpdate +// throw UnimplementedError(); +// } + +// @override +// Future queueRotationUpdate(FilamentEntity entity, double rads, double x, double y, double z, {bool relative = false}) { +// // TODO: implement queueRotationUpdate +// throw UnimplementedError(); +// } + +// @override +// Future queueRotationUpdateQuat(FilamentEntity entity, Quaternion quat, {bool relative = false}) { +// // TODO: implement queueRotationUpdateQuat +// throw UnimplementedError(); +// } + +// @override +// Future removeCollisionComponent(FilamentEntity entity) { +// // TODO: implement removeCollisionComponent +// throw UnimplementedError(); +// } + +// @override +// Future removeEntity(FilamentEntity entity) { +// // TODO: implement removeEntity +// throw UnimplementedError(); +// } + +// @override +// Future removeIbl() { +// // TODO: implement removeIbl +// throw UnimplementedError(); +// } + +// @override +// Future removeLight(FilamentEntity light) { +// // TODO: implement removeLight +// throw UnimplementedError(); +// } + +// @override +// Future removeSkybox() { +// // TODO: implement removeSkybox +// throw UnimplementedError(); +// } + +// @override +// Future render() { +// // TODO: implement render +// throw UnimplementedError(); +// } + +// @override +// // TODO: implement rendering +// bool get rendering => throw UnimplementedError(); + +// @override +// Future resetBones(FilamentEntity entity) { +// // TODO: implement resetBones +// throw UnimplementedError(); +// } + +// @override +// Future reveal(FilamentEntity entity, String? meshName) { +// // TODO: implement reveal +// throw UnimplementedError(); +// } + +// @override +// Future rotateEnd() { +// // TODO: implement rotateEnd +// throw UnimplementedError(); +// } + +// @override +// Future rotateIbl(Matrix3 rotation) { +// // TODO: implement rotateIbl +// throw UnimplementedError(); +// } + +// @override +// Future rotateStart(double x, double y) { +// // TODO: implement rotateStart +// throw UnimplementedError(); +// } + +// @override +// Future rotateUpdate(double x, double y) { +// // TODO: implement rotateUpdate +// throw UnimplementedError(); +// } + +// @override +// Future setAnimationFrame(FilamentEntity entity, int index, int animationFrame) { +// // TODO: implement setAnimationFrame +// throw UnimplementedError(); +// } + +// @override +// Future setAntiAliasing(bool msaa, bool fxaa, bool taa) { +// // TODO: implement setAntiAliasing +// throw UnimplementedError(); +// } + +// @override +// Future setBackgroundColor(double r, double g, double b, double alpha) { +// // TODO: implement setBackgroundColor +// throw UnimplementedError(); +// } + +// @override +// Future setBackgroundImage(String path, {bool fillHeight = false}) { +// // TODO: implement setBackgroundImage +// throw UnimplementedError(); +// } + +// @override +// Future setBackgroundImagePosition(double x, double y, {bool clamp = false}) { +// // TODO: implement setBackgroundImagePosition +// throw UnimplementedError(); +// } + +// @override +// Future setBloom(double bloom) { +// // TODO: implement setBloom +// throw UnimplementedError(); +// } + +// @override +// Future setCamera(FilamentEntity entity, String? name) { +// // TODO: implement setCamera +// throw UnimplementedError(); +// } + +// @override +// Future setCameraCulling(double near, double far) { +// // TODO: implement setCameraCulling +// throw UnimplementedError(); +// } + +// @override +// Future setCameraExposure(double aperture, double shutterSpeed, double sensitivity) { +// // TODO: implement setCameraExposure +// throw UnimplementedError(); +// } + +// @override +// Future setCameraFocalLength(double focalLength) { +// // TODO: implement setCameraFocalLength +// throw UnimplementedError(); +// } + +// @override +// Future setCameraFocusDistance(double focusDistance) { +// // TODO: implement setCameraFocusDistance +// throw UnimplementedError(); +// } + +// @override +// Future setCameraFov(double degrees, double width, double height) { +// // TODO: implement setCameraFov +// throw UnimplementedError(); +// } + +// @override +// Future setCameraManipulatorOptions({ManipulatorMode mode = ManipulatorMode.ORBIT, double orbitSpeedX = 0.01, double orbitSpeedY = 0.01, double zoomSpeed = 0.01}) { +// // TODO: implement setCameraManipulatorOptions +// throw UnimplementedError(); +// } + +// @override +// Future setCameraModelMatrix(List matrix) { +// // TODO: implement setCameraModelMatrix +// throw UnimplementedError(); +// } + +// @override +// Future setCameraPosition(double x, double y, double z) { +// // TODO: implement setCameraPosition +// throw UnimplementedError(); +// } + +// @override +// Future setCameraRotation(Quaternion quaternion) { +// // TODO: implement setCameraRotation +// throw UnimplementedError(); +// } + +// @override +// Future setFrameRate(int framerate) { +// // TODO: implement setFrameRate +// throw UnimplementedError(); +// } + +// @override +// Future setMainCamera() { +// // TODO: implement setMainCamera +// throw UnimplementedError(); +// } + +// @override +// Future setMaterialColor(FilamentEntity entity, String meshName, int materialIndex, double r, double g, double b, double a) { +// // TODO: implement setMaterialColor +// throw UnimplementedError(); +// } + +// @override +// Future setMorphAnimationData(FilamentEntity entity, MorphAnimationData animation, {List? targetMeshNames}) { +// // TODO: implement setMorphAnimationData +// throw UnimplementedError(); +// } + +// @override +// Future setMorphTargetWeights(FilamentEntity entity, List weights) { +// // TODO: implement setMorphTargetWeights +// throw UnimplementedError(); +// } + +// @override +// Future setParent(FilamentEntity child, FilamentEntity parent) { +// // TODO: implement setParent +// throw UnimplementedError(); +// } + +// @override +// Future setPosition(FilamentEntity entity, double x, double y, double z) { +// // TODO: implement setPosition +// throw UnimplementedError(); +// } + +// @override +// Future setPostProcessing(bool enabled) { +// // TODO: implement setPostProcessing +// throw UnimplementedError(); +// } + +// @override +// Future setPriority(FilamentEntity entityId, int priority) { +// // TODO: implement setPriority +// throw UnimplementedError(); +// } + +// @override +// Future setRecording(bool recording) { +// // TODO: implement setRecording +// throw UnimplementedError(); +// } + +// @override +// Future setRecordingOutputDirectory(String outputDirectory) { +// // TODO: implement setRecordingOutputDirectory +// throw UnimplementedError(); +// } + +// @override +// Future setRendering(bool render) { +// // TODO: implement setRendering +// throw UnimplementedError(); +// } + +// @override +// Future setRotation(FilamentEntity entity, double rads, double x, double y, double z) { +// // TODO: implement setRotation +// throw UnimplementedError(); +// } + +// @override +// Future setRotationQuat(FilamentEntity entity, Quaternion rotation) { +// // TODO: implement setRotationQuat +// throw UnimplementedError(); +// } + +// @override +// Future setScale(FilamentEntity entity, double scale) { +// // TODO: implement setScale +// throw UnimplementedError(); +// } + +// @override +// Future setToneMapping(ToneMapper mapper) { +// // TODO: implement setToneMapping +// throw UnimplementedError(); +// } + +// @override +// Future setViewFrustumCulling(bool enabled) { +// // TODO: implement setViewFrustumCulling +// throw UnimplementedError(); +// } + +// @override +// Future stopAnimation(FilamentEntity entity, int animationIndex) { +// // TODO: implement stopAnimation +// throw UnimplementedError(); +// } + +// @override +// Future stopAnimationByName(FilamentEntity entity, String name) { +// // TODO: implement stopAnimationByName +// throw UnimplementedError(); +// } + +// @override +// Future testCollisions(FilamentEntity entity) { +// // TODO: implement testCollisions +// throw UnimplementedError(); +// } + +// @override +// Future transformToUnitCube(FilamentEntity entity) { +// // TODO: implement transformToUnitCube +// throw UnimplementedError(); +// } + +// @override +// Future zoomBegin() { +// // TODO: implement zoomBegin +// throw UnimplementedError(); +// } + +// @override +// Future zoomEnd() { +// // TODO: implement zoomEnd +// throw UnimplementedError(); +// } + +// @override +// Future zoomUpdate(double x, double y, double z) { +// // TODO: implement zoomUpdate +// throw UnimplementedError(); +// } + +// @override +// // TODO: implement scene +// Scene get scene => throw UnimplementedError(); + +// } + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + // This is the theme of your application. + // + // TRY THIS: Try running your application with "flutter run". You'll see + // the application has a purple toolbar. Then, without quitting the app, + // try changing the seedColor in the colorScheme below to Colors.green + // and then invoke "hot reload" (save your changes or press the "hot + // reload" button in a Flutter-supported IDE, or press "r" if you used + // the command line to start the app). + // + // Notice that the counter didn't reset back to zero; the application + // state is not lost during the reload. To reset the state, use hot + // restart instead. + // + // This works for code too, not just values: Most code changes can be + // tested with just a hot reload. + // colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + // This widget is the home page of your application. It is stateful, meaning + // that it has a State object (defined below) that contains fields that affect + // how it looks. + + // This class is the configuration for the state. It holds the values (in this + // case the title) provided by the parent (in this case the App widget) and + // used by the build method of the State. Fields in a Widget subclass are + // always marked "final". + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + // late AbstractFilamentViewer viewer; + int _counter = 0; + + void _incrementCounter() { + final plugin = FlutterFilamentPlugin(); + + // viewer = FooViewer(); + setState(() { + // This call to setState tells the Flutter framework that something has + // changed in this State, which causes it to rerun the build method below + // so that the display can reflect the updated values. If we changed + // _counter without calling setState(), then the build method would not be + // called again, and so nothing would appear to happen. + _counter++; + }); + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + return Scaffold( + appBar: AppBar( + // TRY THIS: Try changing the color here to a specific color (to + // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar + // change color while the other colors stay the same. + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), + ), + body: Center( + // Center is a layout widget. It takes a single child and positions it + // in the middle of the parent. + child: Column( + // Column is also a layout widget. It takes a list of children and + // arranges them vertically. By default, it sizes itself to fit its + // children horizontally, and tries to be as tall as its parent. + // + // Column has various properties to control how it sizes itself and + // how it positions its children. Here we use mainAxisAlignment to + // center the children vertically; the main axis here is the vertical + // axis because Columns are vertical (the cross axis would be + // horizontal). + // + // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" + // action in the IDE, or press "p" in the console), to see the + // wireframe for each widget. + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } +} diff --git a/flutter_filament_federated/web_test/pubspec.lock b/flutter_filament_federated/web_test/pubspec.lock new file mode 100644 index 00000000..35437ce0 --- /dev/null +++ b/flutter_filament_federated/web_test/pubspec.lock @@ -0,0 +1,285 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + animation_tools_dart: + dependency: transitive + description: + name: animation_tools_dart + sha256: c4bc4096d43227b573345a3ea3cb26c3af47a70af31cd7d7d3a5b7c99e33d615 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + dart_filament: + dependency: "direct main" + description: + path: "../../dart_filament" + relative: true + source: path + version: "0.5.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_filament: + dependency: "direct main" + description: + path: "../flutter_filament" + relative: true + source: path + version: "0.6.0" + flutter_filament_ffi: + dependency: transitive + description: + path: "../flutter_filament_ffi" + relative: true + source: path + version: "0.0.1" + flutter_filament_platform_interface: + dependency: transitive + description: + path: "../flutter_filament_platform_interface" + relative: true + source: path + version: "0.0.1" + flutter_filament_web: + dependency: transitive + description: + path: "../flutter_filament_web" + relative: true + source: path + version: "2.0.5" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "25dfcaf170a0190f47ca6355bdd4552cb8924b430512ff0cafb8db9bd41fe33b" + url: "https://pub.dev" + source: hosted + version: "1.14.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "2419f20b0c8677b2d67c8ac4d1ac7372d862dc6c460cdbb052b40155408cd794" + url: "https://pub.dev" + source: hosted + version: "0.7.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "7475cb4dd713d57b6f7464c0e13f06da0d535d8b2067e188962a59bac2cf280b" + url: "https://pub.dev" + source: hosted + version: "14.2.2" +sdks: + dart: ">=3.5.0-138.0.dev <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/flutter_filament_federated/web_test/pubspec.yaml b/flutter_filament_federated/web_test/pubspec.yaml new file mode 100644 index 00000000..cb0ec78d --- /dev/null +++ b/flutter_filament_federated/web_test/pubspec.yaml @@ -0,0 +1,78 @@ +name: web_test +description: "A new Flutter project." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +version: 1.0.0+1 + +environment: + sdk: '>=3.5.0-138.0.dev <4.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + dart_filament: + path: ../../dart_filament + flutter_filament: + path: ../flutter_filament + flutter: + sdk: flutter + cupertino_icons: ^1.0.6 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^3.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/flutter_filament_federated/web_test/test/widget_test.dart b/flutter_filament_federated/web_test/test/widget_test.dart new file mode 100644 index 00000000..00095e20 --- /dev/null +++ b/flutter_filament_federated/web_test/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:web_test/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/flutter_filament_federated/web_test/web/favicon.png b/flutter_filament_federated/web_test/web/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/flutter_filament_federated/web_test/web/favicon.png differ diff --git a/flutter_filament_federated/web_test/web/icons/Icon-192.png b/flutter_filament_federated/web_test/web/icons/Icon-192.png new file mode 100644 index 00000000..b749bfef Binary files /dev/null and b/flutter_filament_federated/web_test/web/icons/Icon-192.png differ diff --git a/flutter_filament_federated/web_test/web/icons/Icon-512.png b/flutter_filament_federated/web_test/web/icons/Icon-512.png new file mode 100644 index 00000000..88cfd48d Binary files /dev/null and b/flutter_filament_federated/web_test/web/icons/Icon-512.png differ diff --git a/flutter_filament_federated/web_test/web/icons/Icon-maskable-192.png b/flutter_filament_federated/web_test/web/icons/Icon-maskable-192.png new file mode 100644 index 00000000..eb9b4d76 Binary files /dev/null and b/flutter_filament_federated/web_test/web/icons/Icon-maskable-192.png differ diff --git a/flutter_filament_federated/web_test/web/icons/Icon-maskable-512.png b/flutter_filament_federated/web_test/web/icons/Icon-maskable-512.png new file mode 100644 index 00000000..d69c5669 Binary files /dev/null and b/flutter_filament_federated/web_test/web/icons/Icon-maskable-512.png differ diff --git a/flutter_filament_federated/web_test/web/index.html b/flutter_filament_federated/web_test/web/index.html new file mode 100644 index 00000000..52dddb96 --- /dev/null +++ b/flutter_filament_federated/web_test/web/index.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + web_test + + + + + + diff --git a/flutter_filament_federated/web_test/web/manifest.json b/flutter_filament_federated/web_test/web/manifest.json new file mode 100644 index 00000000..609262c9 --- /dev/null +++ b/flutter_filament_federated/web_test/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "web_test", + "short_name": "web_test", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +}