diff --git a/android/src/main/kotlin/app/polyvox/filament/FilamentView.kt b/android/src/main/kotlin/app/polyvox/filament/FilamentView.kt deleted file mode 100644 index df8e49e2..00000000 --- a/android/src/main/kotlin/app/polyvox/filament/FilamentView.kt +++ /dev/null @@ -1,397 +0,0 @@ -package app.polyvox.filament -import android.content.res.AssetManager - -import android.Manifest -import android.app.Activity -import android.content.Context -import android.content.pm.PackageManager -import android.graphics.Color -import android.graphics.SurfaceTexture -import android.graphics.PixelFormat - -import io.flutter.FlutterInjector - -import android.os.CountDownTimer - -import android.opengl.GLU -import javax.microedition.khronos.egl.EGLConfig -import javax.microedition.khronos.opengles.GL10 -import java.nio.ByteBuffer -import java.nio.ByteOrder -import java.nio.FloatBuffer -import android.hardware.Camera -import android.opengl.GLSurfaceView -import android.view.SurfaceView -import android.view.TextureView -import android.view.View -import android.view.Surface -import android.widget.TextView -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import androidx.lifecycle.DefaultLifecycleObserver -import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.platform.PlatformView -import java.io.IOException - -import android.util.Log - -import com.sun.jna.Library -import com.sun.jna.Native -import com.sun.jna.Pointer -import com.sun.jna.ptr.PointerByReference -import com.sun.jna.ptr.IntByReference -import com.sun.jna.Structure -import com.sun.jna.NativeLibrary -import com.sun.jna.StringArray -import com.sun.jna.JNIEnv - -import android.R.attr.path - -import java.util.Collections; - -import android.hardware.display.DisplayManager - -import com.google.android.filament.android.* -import com.google.android.filament.* - -import android.view.Choreographer -import android.view.SurfaceHolder - - -class FilamentView( - private val viewId: Int, - private val context: Context, - private val activity: Activity, - private val binaryMessenger: BinaryMessenger, - private val creationParams : Map? -) : DefaultLifecycleObserver, -MethodChannel.MethodCallHandler, -PlatformView { - - companion object { - const val TAG = "FilamentView" - } - - private val _view = SurfaceView(context) - - override fun getView(): View { - return _view - } - - private val _methodChannel: MethodChannel - - private lateinit var _lib : FilamentInterop - - private var _viewer : Pointer? = null - - private lateinit var choreographer: Choreographer - - private val frameScheduler = FrameCallback() - - private lateinit var uiHelper : UiHelper - - private lateinit var assetManager : AssetManager - - - init { - MethodChannel(binaryMessenger, PolyvoxFilamentPlugin.VIEW_TYPE + '_' + viewId).also { - _methodChannel = it - it.setMethodCallHandler(this) - } - _lib = Native.loadLibrary("filament_interop", FilamentInterop::class.java, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, true)) - - _methodChannel.invokeMethod("ready", null) - - choreographer = Choreographer.getInstance() - // _view.setAlpha(0) - _view.setZOrderOnTop(false) - _view.holder.setFormat(PixelFormat.TRANSPARENT) - - _view.holder.addCallback (object : SurfaceHolder.Callback { - override fun surfaceChanged(holder:SurfaceHolder, format:Int, width:Int, height:Int) { - Log.v(TAG, "SURFACE CHANGED") - if(_viewer != null) { - _lib.update_viewport_and_camera_projection(_viewer!!, width, height, 1.0f); - } - } - - override fun surfaceCreated(holder:SurfaceHolder) { - Log.v(TAG, "SURFACE CREATED") - if(_viewer == null) { - _viewer = _lib.filament_viewer_new( - _view.holder.surface as Object, - JNIEnv.CURRENT, - context.assets) - - choreographer.postFrameCallback(frameScheduler) - - activity.window.setFormat(PixelFormat.RGBA_8888) - - uiHelper = UiHelper(UiHelper.ContextErrorPolicy.DONT_CHECK) - uiHelper.renderCallback = SurfaceCallback() - uiHelper.attachTo(_view) - } - _lib.destroy_swap_chain(_viewer!!) - _lib.create_swap_chain(_viewer!!, _view.holder.surface, JNIEnv.CURRENT) - } - - override fun surfaceDestroyed(holder:SurfaceHolder) { - if(_viewer != null) { - _lib.destroy_swap_chain(_viewer!!) - } - } - }) - - } - - override fun dispose() { - _methodChannel.setMethodCallHandler(null) - } - - override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { - when (call.method) { - "reloadAssets" -> { - // context = context.createPackageContext(context.getPackageName(), 0) - // val assetManager = context.getAssets() - // val flutterJNI = FlutterJNI.Factory.provideFlutterJNI() - // flutterJNI.updateJavaAssetManager(assetManager, flutterApplicationInfo.flutterAssetsDir) - } - "setBackgroundImage" -> { - val args = call.arguments as String - val loader = FlutterInjector.instance().flutterLoader() - _lib.set_background_image(_viewer!!, loader.getLookupKeyForAsset(args)) - Log.v(TAG, "Package name : ${context.getPackageName()}") - result.success("OK"); - } - "loadSkybox" -> { - val args = call.arguments as String - val loader = FlutterInjector.instance().flutterLoader() - _lib.load_skybox(_viewer!!, loader.getLookupKeyForAsset(args)) - result.success("OK"); - } - "loadIbl" -> { - val args = call.arguments as String - val loader = FlutterInjector.instance().flutterLoader() - - _lib.load_ibl(_viewer!!, loader.getLookupKeyForAsset(args)) - result.success("OK"); - } - "removeIbl" -> { - _lib.remove_ibl(_viewer!!) - result.success(true); - } - "removeSkybox" -> { - _lib.remove_skybox(_viewer!!) - result.success(true); - } - "loadGlb" -> { - if (_viewer == null) - return; - val loader = FlutterInjector.instance().flutterLoader() - val key = loader.getLookupKeyForAsset(call.arguments as String) - val key2 = loader.getLookupKeyForAsset(call.arguments as String, context.packageName) - val path = loader.findAppBundlePath() - - val assetPtr = _lib.load_glb( - _viewer!!, - key - ) - result.success(Pointer.nativeValue(assetPtr)); - } - "loadGltf" -> { - if (_viewer == null) - return; - val args = call.arguments as ArrayList - val loader = FlutterInjector.instance().flutterLoader() - val assetPtr = _lib.load_gltf( - _viewer!!, - loader.getLookupKeyForAsset(args[0] as String), - loader.getLookupKeyForAsset(args[1] as String) - ) - result.success(Pointer.nativeValue(assetPtr)); - } - "transformToUnitCube" -> { - val assetPtr = Pointer(call.arguments as Long); - _lib.transform_to_unit_cube(assetPtr) - result.success("OK"); - } - "setPosition" -> { - val args = call.arguments as ArrayList<*> - val assetPtr = Pointer(args[0] as Long) - _lib.set_position(assetPtr, (args[1] as Double).toFloat(), (args[2] as Double).toFloat(), (args[3] as Double).toFloat()) - result.success("OK"); - } - "setRotation" -> { - val args = call.arguments as ArrayList<*> - val assetPtr = Pointer(args[0] as Long) - _lib.set_rotation(assetPtr, (args[1] as Double).toFloat(), (args[2] as Double).toFloat(), (args[3] as Double).toFloat(), (args[4] as Double).toFloat()) - result.success("OK"); - } - "setTexture" -> { - val args = call.arguments as ArrayList<*> - val loader = FlutterInjector.instance().flutterLoader() - val assetPtr = Pointer(args[0] as Long); - _lib.set_texture(assetPtr, loader.getLookupKeyForAsset(args[1] as String), args[2] as Int) - result.success("OK"); - } - "setCamera" -> { - val args = call.arguments as ArrayList<*> - val success = _lib.set_camera( - _viewer!!, - Pointer(args[0] as Long), - args[1] as String, - ) - if(success) { - result.success("OK"); - } else { - result.error("failed","failed", "Failed to set camera") - } - } - "zoom" -> { - if(_viewer == null) - return; - _lib.scroll(_viewer!!, 0.0f, 0.0f, (call.arguments as Double).toFloat()) - result.success("OK"); - } - "getTargetNames" -> { - if(_viewer == null) - return; - - val countPtr = IntByReference(); - val args = call.arguments as ArrayList<*> - val namesPtr = _lib.get_target_names(Pointer(args[0] as Long), args[1] as String, countPtr) - - val names = namesPtr.getStringArray(0, countPtr.value); - - for(i in 0..countPtr.value-1) { - Log.v(TAG, "Got target names ${names[i]} ${names[i].length}") - } - - val namesAsList = names.toCollection(ArrayList()) - - _lib.free_pointer(namesPtr, countPtr.getValue()) - - result.success(namesAsList) - } - "getAnimationNames" -> { - val assetPtr = Pointer(call.arguments as Long) - val countPtr = IntByReference(); - val arrPtr = _lib.get_animation_names(assetPtr, countPtr) - - val names = arrPtr.getStringArray(0, countPtr.value); - - for(i in 0..countPtr.value-1) { - val name = names[i]; - Log.v(TAG, "Got animation names ${name} ${name.length}") - } - - _lib.free_pointer(arrPtr, 1) - - result.success(names.toCollection(ArrayList())) - } - "applyWeights" -> { - val args = call.arguments as ArrayList<*> - val assetPtr = Pointer(args[0] as Long) - val weights = args[1] as ArrayList; - - _lib.apply_weights(assetPtr, weights.toFloatArray(), weights.size) - result.success("OK"); - } - "animateWeights" -> { - val args = call.arguments as ArrayList - val assetPtr = Pointer(args[0] as Long) - val frames = args[1] as ArrayList; - val numWeights = args[2] as Int - val numFrames = args[3] as Int - val frameLenInMs = args[4] as Double - - _lib.animate_weights(assetPtr, frames.toFloatArray(), numWeights, numFrames, frameLenInMs.toFloat()) - result.success("OK"); - } - "panStart" -> { - val args = call.arguments as ArrayList - _lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, true) - result.success("OK"); - } - "panUpdate" -> { - val args = call.arguments as ArrayList - _lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int) - result.success("OK"); - } - "panEnd" -> { - _lib.grab_end(_viewer!!) - result.success("OK"); - } - "rotateStart" -> { - val args = call.arguments as ArrayList - _lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, false) - result.success("OK"); - } - "rotateUpdate" -> { - val args = call.arguments as ArrayList - _lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int) - result.success("OK"); - } - "rotateEnd" -> { - _lib.grab_end(_viewer!!) - result.success("OK"); - } - "grabStart" -> { - val args = call.arguments as ArrayList - _lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, true) - result.success("OK"); - } - "grabUpdate" -> { - val args = call.arguments as ArrayList - _lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int) - result.success("OK"); - } - "grabEnd" -> { - _lib.grab_end(_viewer!!) - result.success("OK"); - } - "removeAsset" -> { - _lib.remove_asset(_viewer!!, Pointer(call.arguments as Long)) - result.success("OK"); - } - "clearAssets" -> { - _lib.clear_assets(_viewer!!) - result.success("OK"); - } - "playAnimation" -> { - val args = call.arguments as ArrayList - _lib.play_animation(Pointer(args[0] as Long), args[1] as Int, args[2] as Boolean) - result.success("OK") - } - else -> { - result.notImplemented() - } - } - } - - inner class SurfaceCallback : UiHelper.RendererCallback { - override fun onNativeWindowChanged(surface: Surface) { - _lib.destroy_swap_chain(_viewer!!) - _lib.create_swap_chain(_viewer!!, surface, JNIEnv.CURRENT) - } - - override fun onDetachedFromSurface() { - _lib.destroy_swap_chain(_viewer!!) - } - - override fun onResized(width: Int, height: Int) { - _lib.update_viewport_and_camera_projection(_viewer!!, width, height, 1.0f) - } - } - - - inner class FrameCallback : Choreographer.FrameCallback { - private val startTime = System.nanoTime() - override fun doFrame(frameTimeNanos: Long) { - choreographer.postFrameCallback(this) - _lib.render(_viewer!!) - } - } -} diff --git a/android/src/main/kotlin/app/polyvox/filament/FilamentViewFactory.kt b/android/src/main/kotlin/app/polyvox/filament/FilamentViewFactory.kt deleted file mode 100644 index baad1899..00000000 --- a/android/src/main/kotlin/app/polyvox/filament/FilamentViewFactory.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.polyvox.filament - -import io.flutter.plugin.common.BinaryMessenger -import android.app.Activity - -import android.content.Context -import android.view.View -import io.flutter.plugin.common.StandardMessageCodec -import io.flutter.plugin.platform.PlatformView -import io.flutter.plugin.platform.PlatformViewFactory - -class FilamentViewFactory( - private val activity: Activity, - private val binaryMessenger: BinaryMessenger -) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { - override fun create(context: Context?, viewId: Int, args: Any?): PlatformView { - val creationParams = args as Map? - return FilamentView(viewId, context!!, activity, binaryMessenger, creationParams) - } -} \ No newline at end of file diff --git a/android/src/main/kotlin/app/polyvox/filament/PolyvoxFilamentPlugin.kt b/android/src/main/kotlin/app/polyvox/filament/PolyvoxFilamentPlugin.kt index dd60d525..af943818 100644 --- a/android/src/main/kotlin/app/polyvox/filament/PolyvoxFilamentPlugin.kt +++ b/android/src/main/kotlin/app/polyvox/filament/PolyvoxFilamentPlugin.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.Lifecycle import io.flutter.embedding.engine.plugins.activity.ActivityAware import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler @@ -14,12 +15,82 @@ import io.flutter.plugin.common.MethodChannel.Result import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference +import android.content.res.AssetManager + +import android.Manifest +import android.app.Activity +import android.content.Context +import android.content.pm.PackageManager + +import io.flutter.FlutterInjector + +import android.os.CountDownTimer + +import android.opengl.GLU +import javax.microedition.khronos.egl.EGLConfig +import javax.microedition.khronos.opengles.GL10 +import java.nio.ByteBuffer +import java.nio.ByteOrder +import java.nio.FloatBuffer +import android.hardware.Camera +import android.opengl.GLSurfaceView +import android.view.SurfaceView +import android.view.TextureView +import android.view.View +import android.view.Surface +import android.widget.TextView +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import androidx.lifecycle.DefaultLifecycleObserver + +import io.flutter.plugin.platform.PlatformView +import java.io.IOException + +import android.util.Log + +import com.sun.jna.Library +import com.sun.jna.Native +import com.sun.jna.Pointer +import com.sun.jna.ptr.PointerByReference +import com.sun.jna.ptr.IntByReference +import com.sun.jna.Structure +import com.sun.jna.NativeLibrary +import com.sun.jna.StringArray +import com.sun.jna.JNIEnv + +import android.R.attr.path +import android.graphics.* + +import java.util.Collections; + +import android.hardware.display.DisplayManager + +import com.google.android.filament.android.* +import com.google.android.filament.* + +import android.view.Choreographer +import android.view.Surface.CHANGE_FRAME_RATE_ALWAYS +import android.view.Surface.FRAME_RATE_COMPATIBILITY_DEFAULT +import android.view.SurfaceHolder + /** PolyvoxFilamentPlugin */ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { + inner class FrameCallback : Choreographer.FrameCallback { + private val startTime = System.nanoTime() + override fun doFrame(frameTimeNanos: Long) { + choreographer.postFrameCallback(this) + if(!surface.isValid()) { + Log.v(TAG, "INVALID") + } + _lib.render(_viewer!!) + } + } + companion object { - const val VIEW_TYPE = "app.polyvox.filament/filament_view" + const val CHANNEL_NAME = "app.polyvox.filament/event" + const val TAG = "FilamentPlugin" } /// The MethodChannel that will the communication between Flutter and native Android @@ -28,41 +99,307 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { /// when the Flutter Engine is detached from the Activity private lateinit var channel : MethodChannel - /// Keep a referene to the plugin binding so we can defer construction of a FilamentViewFactory - /// until Activity is attached. + /// Keep a referene to the plugin binding so we can use the TextureRegistry when initialize is called from the platform channel. private lateinit var flutterPluginBinding : FlutterPlugin.FlutterPluginBinding private var lifecycle: Lifecycle? = null + private lateinit var _lib : FilamentInterop + + private var _viewer : Pointer? = null + + private lateinit var choreographer: Choreographer + + private val frameCallback = FrameCallback() + + private lateinit var assetManager : AssetManager + + private lateinit var surface: Surface + private lateinit var surfaceTexture: SurfaceTexture + + private lateinit var activity:Activity + override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { this.flutterPluginBinding = flutterPluginBinding - channel = MethodChannel(flutterPluginBinding.binaryMessenger, "app.polyvox.filament") + channel = MethodChannel(flutterPluginBinding.binaryMessenger, CHANNEL_NAME) channel.setMethodCallHandler(this) + + _lib = Native.loadLibrary("filament_interop", FilamentInterop::class.java, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, true)) } override fun onAttachedToActivity(binding: ActivityPluginBinding) { lifecycle = (binding.lifecycle as? HiddenLifecycleReference)?.lifecycle - flutterPluginBinding - .platformViewRegistry - .registerViewFactory(VIEW_TYPE, FilamentViewFactory(binding.activity, flutterPluginBinding.binaryMessenger)) + activity = binding.activity } - override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + when (call.method) { + "initialize" -> { + val args = call.arguments as ArrayList + val width = args[0] + val height = args[1] + + val entry = flutterPluginBinding.textureRegistry.createSurfaceTexture(); - if (call.method == "getPlatformVersion") { - result.success("Android ${android.os.Build.VERSION.RELEASE}") - } else { - result.notImplemented() + choreographer = Choreographer.getInstance() + + surfaceTexture = entry.surfaceTexture() + + surfaceTexture.setDefaultBufferSize(width, height) + + surface = Surface(surfaceTexture) + + _viewer = _lib.filament_viewer_new( + surface as Object, + JNIEnv.CURRENT, + (activity as Context).assets) + + choreographer.postFrameCallback(frameCallback) + + activity.window.setFormat(PixelFormat.RGBA_8888) + + _lib.update_viewport_and_camera_projection(_viewer!!, width, height, 1.0f); + + result.success(entry.id().toInt()) + } + "resize" -> { + val args = call.arguments as ArrayList + val width = args[0] + val height = args[1] + + surfaceTexture.setDefaultBufferSize(width, height) + _lib.update_viewport_and_camera_projection(_viewer!!, width, height, 1.0f); + result.success(null) + } + "reloadAssets" -> { + // context = context.createPackageContext(context.getPackageName(), 0) + // val assetManager = context.getAssets() + // val flutterJNI = FlutterJNI.Factory.provideFlutterJNI() + // flutterJNI.updateJavaAssetManager(assetManager, flutterApplicationInfo.flutterAssetsDir) + } + "setBackgroundImage" -> { + val args = call.arguments as String + val loader = FlutterInjector.instance().flutterLoader() + _lib.set_background_image(_viewer!!, loader.getLookupKeyForAsset(args)) + _lib.render(_viewer!!) + result.success("OK"); + } + "loadSkybox" -> { + val args = call.arguments as String + val loader = FlutterInjector.instance().flutterLoader() + _lib.load_skybox(_viewer!!, loader.getLookupKeyForAsset(args)) + result.success("OK"); + } + "loadIbl" -> { + val args = call.arguments as String + val loader = FlutterInjector.instance().flutterLoader() + + _lib.load_ibl(_viewer!!, loader.getLookupKeyForAsset(args)) + result.success("OK"); + } + "removeIbl" -> { + _lib.remove_ibl(_viewer!!) + result.success(true); + } + "removeSkybox" -> { + _lib.remove_skybox(_viewer!!) + result.success(true); + } + "loadGlb" -> { + if (_viewer == null) + return; + val loader = FlutterInjector.instance().flutterLoader() + val key = loader.getLookupKeyForAsset(call.arguments as String) + val key2 = loader.getLookupKeyForAsset(call.arguments as String, (activity as Context).packageName) + val path = loader.findAppBundlePath() + + val assetPtr = _lib.load_glb( + _viewer!!, + key + ) + result.success(Pointer.nativeValue(assetPtr)); + } + "loadGltf" -> { + if (_viewer == null) + return; + val args = call.arguments as ArrayList + val loader = FlutterInjector.instance().flutterLoader() + val assetPtr = _lib.load_gltf( + _viewer!!, + loader.getLookupKeyForAsset(args[0] as String), + loader.getLookupKeyForAsset(args[1] as String) + ) + result.success(Pointer.nativeValue(assetPtr)); + } + "transformToUnitCube" -> { + val assetPtr = Pointer(call.arguments as Long); + _lib.transform_to_unit_cube(assetPtr) + result.success("OK"); + } + "setPosition" -> { + val args = call.arguments as ArrayList<*> + val assetPtr = Pointer(args[0] as Long) + _lib.set_position(assetPtr, (args[1] as Double).toFloat(), (args[2] as Double).toFloat(), (args[3] as Double).toFloat()) + result.success("OK"); + } + "setRotation" -> { + val args = call.arguments as ArrayList<*> + val assetPtr = Pointer(args[0] as Long) + _lib.set_rotation(assetPtr, (args[1] as Double).toFloat(), (args[2] as Double).toFloat(), (args[3] as Double).toFloat(), (args[4] as Double).toFloat()) + result.success("OK"); + } + "setTexture" -> { + val args = call.arguments as ArrayList<*> + val loader = FlutterInjector.instance().flutterLoader() + val assetPtr = Pointer(args[0] as Long); + _lib.set_texture(assetPtr, loader.getLookupKeyForAsset(args[1] as String), args[2] as Int) + result.success("OK"); + } + "setCamera" -> { + val args = call.arguments as ArrayList<*> + val success = _lib.set_camera( + _viewer!!, + Pointer(args[0] as Long), + args[1] as String, + ) + if(success) { + result.success("OK"); + } else { + result.error("failed","failed", "Failed to set camera") + } + } + "zoom" -> { + if(_viewer == null) + return; + _lib.scroll(_viewer!!, 0.0f, 0.0f, (call.arguments as Double).toFloat()) + result.success("OK"); + } + "getTargetNames" -> { + if(_viewer == null) + return; + + val countPtr = IntByReference(); + val args = call.arguments as ArrayList<*> + val namesPtr = _lib.get_target_names(Pointer(args[0] as Long), args[1] as String, countPtr) + + val names = namesPtr.getStringArray(0, countPtr.value); + + for(i in 0..countPtr.value-1) { + Log.v(TAG, "Got target names ${names[i]} ${names[i].length}") + } + + val namesAsList = names.toCollection(ArrayList()) + + _lib.free_pointer(namesPtr, countPtr.getValue()) + + result.success(namesAsList) + } + "getAnimationNames" -> { + val assetPtr = Pointer(call.arguments as Long) + val countPtr = IntByReference(); + val arrPtr = _lib.get_animation_names(assetPtr, countPtr) + + val names = arrPtr.getStringArray(0, countPtr.value); + + for(i in 0..countPtr.value-1) { + val name = names[i]; + Log.v(TAG, "Got animation names ${name} ${name.length}") + } + + _lib.free_pointer(arrPtr, 1) + + result.success(names.toCollection(ArrayList())) + } + "applyWeights" -> { + val args = call.arguments as ArrayList<*> + val assetPtr = Pointer(args[0] as Long) + val weights = args[1] as ArrayList; + + _lib.apply_weights(assetPtr, weights.toFloatArray(), weights.size) + result.success("OK"); + } + "animateWeights" -> { + val args = call.arguments as ArrayList + val assetPtr = Pointer(args[0] as Long) + val frames = args[1] as ArrayList; + val numWeights = args[2] as Int + val numFrames = args[3] as Int + val frameLenInMs = args[4] as Double + + _lib.animate_weights(assetPtr, frames.toFloatArray(), numWeights, numFrames, frameLenInMs.toFloat()) + result.success("OK"); + } + "panStart" -> { + val args = call.arguments as ArrayList + _lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, true) + result.success("OK"); + } + "panUpdate" -> { + val args = call.arguments as ArrayList + _lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int) + result.success("OK"); + } + "panEnd" -> { + _lib.grab_end(_viewer!!) + result.success("OK"); + } + "rotateStart" -> { + val args = call.arguments as ArrayList + _lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, false) + result.success("OK"); + } + "rotateUpdate" -> { + val args = call.arguments as ArrayList + _lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int) + result.success("OK"); + } + "rotateEnd" -> { + _lib.grab_end(_viewer!!) + result.success("OK"); + } + "grabStart" -> { + val args = call.arguments as ArrayList + _lib.grab_begin(_viewer!!, args[0] as Int, args[1] as Int, true) + result.success("OK"); + } + "grabUpdate" -> { + val args = call.arguments as ArrayList + _lib.grab_update(_viewer!!, args[0] as Int, args[1] as Int) + result.success("OK"); + } + "grabEnd" -> { + _lib.grab_end(_viewer!!) + result.success("OK"); + } + "removeAsset" -> { + _lib.remove_asset(_viewer!!, Pointer(call.arguments as Long)) + result.success("OK"); + } + "clearAssets" -> { + _lib.clear_assets(_viewer!!) + result.success("OK"); + } + "playAnimation" -> { + val args = call.arguments as ArrayList + _lib.play_animation(Pointer(args[0] as Long), args[1] as Int, args[2] as Boolean) + result.success("OK") + } + else -> { + result.notImplemented() + } } - } +} override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { channel.setMethodCallHandler(null) + //_lib.destroy_swap_chain(_viewer!!) } override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { onAttachedToActivity(binding) + //_lib.create_swap_chain(_viewer!!, surface, JNIEnv.CURRENT) + } override fun onDetachedFromActivityForConfigChanges() { @@ -70,6 +407,6 @@ class PolyvoxFilamentPlugin: FlutterPlugin, MethodCallHandler, ActivityAware { } override fun onDetachedFromActivity() { - lifecycle = null + lifecycle = null } } diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 444f792d..da077a4d 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -56,10 +56,15 @@ android { buildTypes { release { signingConfig signingConfigs.debug + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile( + 'proguard-android-optimize.txt'), + 'proguard-rules.pro' } } packagingOptions { - + } aaptOptions { noCompress "ktx" @@ -71,13 +76,10 @@ flutter { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation "com.google.android.filament:filament-android:1.17.0" - implementation "com.google.android.filament:filament-utils-android:1.17.0" - implementation "com.google.android.filament:gltfio-android:1.17.0" 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" + compile 'net.java.dev.jna:jna:5.10.0@aar' } diff --git a/example/lib/main.dart b/example/lib/main.dart index f65eba49..8b1e6af9 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,8 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:polyvox_filament/filament_controller.dart'; -import 'package:polyvox_filament/view/filament_widget.dart'; +import 'package:polyvox_filament/filament_widget.dart'; void main() { runApp(const MyApp()); @@ -23,6 +25,7 @@ class _MyAppState extends State { List _targets = []; List _animationNames = []; bool _loop = false; + bool _vertical = false; @override void initState() { @@ -32,240 +35,317 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( + showPerformanceOverlay: true, color: Colors.transparent, home: Scaffold( backgroundColor: Colors.transparent, - body: Column(children: [ - Expanded( - child: SizedBox( - height: 200, - width: 200, - child: FilamentWidget( - controller: _filamentController, - ))), - Align( - alignment: Alignment.bottomLeft, - child: Container( - color: Colors.white, - padding: const EdgeInsets.all(5), - child: PopupMenuButton( - child: const Icon(Icons.menu), - onSelected: (int item) async { - switch (item) { - case 0: - await _filamentController.setBackgroundImage( - 'assets/background.png'); - break; - case 1: - await _filamentController.loadSkybox( - 'assets/default_env/default_env_skybox.ktx'); - await _filamentController.loadSkybox( - 'assets/default_env/default_env_ibl.ktx'); - break; - case 2: - await _filamentController.removeSkybox(); - break; - case 3: - _cube = await _filamentController - .loadGlb('assets/cube.glb'); + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + GestureDetector( + onScaleStart: (d) { + if (d.pointerCount == 1) + _filamentController.panStart(0.5, 0.5); + }, + onScaleEnd: (d) { + // if(d.pointerCount == 2) {} + // _filamentController.panEnd(d. .focalPoint.dx,d.focalPoint.dy); + }, + onScaleUpdate: (d) { + if (d.pointerCount == 1) { + // _filamentController.panUpdate(d.focalPoint.dx,d.focalPoint.dy); + } else { + _filamentController.zoom(10.0); + } + }, + child: Container( + width: _vertical ? 100 : 200, height: _vertical ? 200 : 100, + alignment: Alignment.center, + child: SizedBox( + child: FilamentWidget( + controller: _filamentController, + )), + )), + Align( + alignment: Alignment.bottomLeft, + child: Container( + color: Colors.white, + margin: const EdgeInsets.all(15), + child: PopupMenuButton( + padding: EdgeInsets.all(50), + iconSize: 36, + child: const Icon(Icons.menu), + onSelected: (int item) async { + switch (item) { + case 0: + await _filamentController + .setBackgroundImage( + 'assets/background.png'); + break; + case 1: + await _filamentController.loadSkybox( + 'assets/default_env/default_env_skybox.ktx'); + await _filamentController.loadSkybox( + 'assets/default_env/default_env_ibl.ktx'); + break; + case 2: + await _filamentController.removeSkybox(); + break; + case 3: + _cube = await _filamentController + .loadGlb('assets/cube.glb'); - _animationNames = await _filamentController - .getAnimationNames(_cube!); - break; - case 4: - if (_cube != null) { - await _filamentController.removeAsset(_cube!); + _animationNames = await _filamentController + .getAnimationNames(_cube!); + break; + + case 4: + if (_cube != null) { + await _filamentController + .removeAsset(_cube!); + } + _cube = await _filamentController.loadGltf( + 'assets/cube.gltf', 'assets'); + print(await _filamentController + .getAnimationNames(_cube!)); + break; + case 5: + if (_flightHelmet == null) { + _flightHelmet = + await _filamentController.loadGltf( + 'assets/FlightHelmet/FlightHelmet.gltf', + 'assets/FlightHelmet'); + } + break; + case 6: + await _filamentController + .removeAsset(_cube!); + break; + + case 7: + await _filamentController.applyWeights( + _cube!, List.filled(8, 1.0)); + break; + case 8: + await _filamentController.applyWeights( + _cube!, List.filled(8, 0)); + break; + case 9: + _filamentController.playAnimations( + _cube!, + List.generate( + _animationNames.length, (i) => i), + loop: _loop); + break; + case 10: + _filamentController.stopAnimation(_cube!); + break; + case 11: + setState(() { + _loop = !_loop; + }); + break; + case 12: + _filamentController.zoom(-1.0); + break; + case 13: + _filamentController.zoom(1.0); + break; + case 14: + _filamentController.setCamera( + _cube!, "Camera_Orientation"); + break; + case 15: + final framerate = 30; + final totalSecs = 5; + final numWeights = 8; + final totalFrames = framerate * totalSecs; + final frames = List.generate( + totalFrames, + (frame) => List.filled( + numWeights, frame / totalFrames)); + + _filamentController.animate( + _cube!, + frames.reduce((a, b) => a + b), + numWeights, + totalFrames, + 1000 / framerate.toDouble()); + break; + case 16: + final names = await _filamentController + .getTargetNames(_cube!, "Cube"); + + await showDialog( + builder: (ctx) { + return Container( + color: Colors.white, + height: 200, + width: 200, + child: Column( + mainAxisSize: + MainAxisSize.min, + children: names + .map((name) => + Text(name)) + .cast() + .toList() + + [ + ElevatedButton( + onPressed: () => + Navigator.of( + ctx) + .pop(), + child: + Text("Close")) + ])); + }, + context: context); + break; + case 17: + final names = await _filamentController + .getAnimationNames(_cube!); + + await showDialog( + builder: (ctx) { + return Container( + color: Colors.white, + height: 200, + width: 200, + child: Column( + mainAxisSize: + MainAxisSize.min, + children: names + .map((name) => + Text(name)) + .cast() + .toList() + + [ + ElevatedButton( + onPressed: () => + Navigator.of( + ctx) + .pop(), + child: + Text("Close")) + ])); + }, + context: context); + break; + case 18: + await _filamentController.panStart(1, 1); + await _filamentController.panUpdate(1, 2); + await _filamentController.panEnd(); + break; + case 19: + await _filamentController.panStart(1, 1); + await _filamentController.panUpdate(0, 0); + await _filamentController.panEnd(); + break; + case 20: + await _filamentController.clearAssets(); + break; + case 21: + await _filamentController.setTexture( + _cube!, "assets/background.png"); + break; + case 22: + await _filamentController + .transformToUnitCube(_cube!); + break; + case 23: + await _filamentController.setPosition( + _cube!, 1.0, 1.0, -1.0); + break; + case 24: + await _filamentController.setRotation( + _cube!, pi / 2, 0.0, 1.0, 0.0); + break; + case 25: + setState(() { + _vertical = !_vertical; + }); } - _cube = await _filamentController.loadGltf( - 'assets/cube.gltf', 'assets'); - print(await _filamentController - .getAnimationNames(_cube!)); - break; - case 5: - if (_flightHelmet == null) { - _flightHelmet = - await _filamentController.loadGltf( - 'assets/FlightHelmet/FlightHelmet.gltf', - 'assets/FlightHelmet'); - } - break; - case 6: - await _filamentController.removeAsset(_cube!); - break; - - case 7: - await _filamentController.applyWeights( - _cube!, List.filled(8, 1.0)); - break; - case 8: - await _filamentController.applyWeights( - _cube!, List.filled(8, 0)); - break; - case 9: - _filamentController.playAnimations( - _cube!, - List.generate( - _animationNames.length, (i) => i), - loop: _loop); - break; - case 10: - _filamentController.stopAnimation(_cube!); - break; - case 11: - setState(() { - _loop = !_loop; - }); - break; - case 12: - _filamentController.zoom(-1.0); - break; - case 13: - _filamentController.zoom(1.0); - break; - case 14: - _filamentController.setCamera( - _cube!, "Camera_Orientation"); - break; - case 15: - final framerate = 30; - final totalSecs = 5; - final numWeights = 8; - final totalFrames = framerate * totalSecs; - final frames = List.generate( - totalFrames, - (frame) => List.filled( - numWeights, frame / totalFrames)); - - _filamentController.animate( - _cube!, - frames.reduce((a, b) => a + b), - numWeights, - totalFrames, - 1000 / framerate.toDouble()); - break; - case 16: - final names = await _filamentController - .getTargetNames(_cube!, "Cube"); - - await showDialog( - builder: (ctx) { - return Container( - color: Colors.white, - height: 200, - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: names - .map((name) => Text(name)) - .cast() - .toList() + - [ - ElevatedButton( - onPressed: () => - Navigator.of(ctx) - .pop(), - child: Text("Close")) - ])); - }, - context: context); - break; - case 17: - final names = await _filamentController - .getAnimationNames(_cube!); - - await showDialog( - builder: (ctx) { - return Container( - color: Colors.white, - height: 200, - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: names - .map((name) => Text(name)) - .cast() - .toList() + - [ - ElevatedButton( - onPressed: () => - Navigator.of(ctx) - .pop(), - child: Text("Close")) - ])); - }, - context: context); - break; - case 18: - await _filamentController.panStart(1, 1); - await _filamentController.panUpdate(1, 2); - await _filamentController.panEnd(); - break; - case 19: - await _filamentController.panStart(1, 1); - await _filamentController.panUpdate(0, 0); - await _filamentController.panEnd(); - break; - case 20: - await _filamentController.clearAssets(); - } - }, - itemBuilder: (BuildContext context) => - >[ - const PopupMenuItem( - value: 0, - child: Text("load background image")), - const PopupMenuItem( - value: 1, - child: Text('load skybox'), - ), - const PopupMenuItem( - value: 2, - child: Text('remove skybox'), - ), - const PopupMenuItem( - value: 3, child: Text('load cube GLB')), - const PopupMenuItem( - value: 4, child: Text('load cube GLTF')), - const PopupMenuItem( - value: 5, - child: Text('load flight helmet')), - const PopupMenuItem( - value: 6, child: Text('remove cube')), - const PopupMenuItem( - value: 20, child: Text('remove all assets')), - const PopupMenuItem( - value: 7, - child: Text('set all weights to 1')), - const PopupMenuItem( - value: 8, - child: Text('set all weights to 0')), - const PopupMenuItem( - value: 9, - child: Text('play all animations')), - const PopupMenuItem( - value: 10, child: Text('stop animations')), - PopupMenuItem( - value: 11, - child: Text( - "toggle animation loop (currently $_loop!)")), - const PopupMenuItem( - value: 12, child: Text('zoom in')), - const PopupMenuItem( - value: 13, child: Text('zoom out')), - const PopupMenuItem( - value: 14, child: Text('set camera')), - const PopupMenuItem( - value: 15, child: Text('animate weights')), - const PopupMenuItem( - value: 16, child: Text('get target names')), - const PopupMenuItem( - value: 17, - child: Text('get animation names')), - const PopupMenuItem( - value: 18, child: Text('pan left')), - const PopupMenuItem( - value: 19, child: Text('pan right')), - ]))) - ]))); + }, + itemBuilder: (BuildContext context) => + >[ + const PopupMenuItem( + value: 0, + child: Text("load background image")), + const PopupMenuItem( + value: 1, + child: Text('load skybox'), + ), + const PopupMenuItem( + value: 2, + child: Text('remove skybox'), + ), + const PopupMenuItem( + value: 3, child: Text('load cube GLB')), + const PopupMenuItem( + value: 4, + child: Text('load cube GLTF')), + const PopupMenuItem( + value: 21, + child: Text('swap cube texture')), + const PopupMenuItem( + value: 22, + child: Text('transform to unit cube')), + const PopupMenuItem( + value: 23, + child: + Text('set position to 1, 1, -1')), + const PopupMenuItem( + value: 24, + child: + Text('rotate by pi around Y axis')), + const PopupMenuItem( + value: 5, + child: Text('load flight helmet')), + const PopupMenuItem( + value: 6, child: Text('remove cube')), + const PopupMenuItem( + value: 20, + child: Text('remove all assets')), + const PopupMenuItem( + value: 7, + child: Text('set all weights to 1')), + const PopupMenuItem( + value: 8, + child: Text('set all weights to 0')), + const PopupMenuItem( + value: 9, + child: Text('play all animations')), + const PopupMenuItem( + value: 10, + child: Text('stop animations')), + PopupMenuItem( + value: 11, + child: Text( + _loop ? "don't loop animation" : "loop animation")), + const PopupMenuItem( + value: 12, child: Text('zoom in')), + const PopupMenuItem( + value: 13, child: Text('zoom out')), + const PopupMenuItem( + value: 14, child: Text('set camera')), + const PopupMenuItem( + value: 15, + child: Text('animate weights')), + const PopupMenuItem( + value: 16, + child: Text('get target names')), + const PopupMenuItem( + value: 17, + child: Text('get animation names')), + const PopupMenuItem( + value: 18, child: Text('pan left')), + const PopupMenuItem( + value: 19, child: Text('pan right')), + PopupMenuItem( + value: 25, child: Text(_vertical ? 'set horizontal' : 'set vertical')), + ]))) + ]))); } } diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index e67a8008..2b921d18 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -5,7 +5,10 @@ import 'package:flutter/services.dart'; typedef FilamentAsset = int; abstract class FilamentController { - void onFilamentViewCreated(int id); + + late int textureId; + Future initialize(int width, int height); + Future resize(int width, int height); Future setBackgroundImage(String path); Future loadSkybox(String skyboxPath); Future removeSkybox(); @@ -45,28 +48,24 @@ abstract class FilamentController { } class PolyvoxFilamentController extends FilamentController { - late int _id; - late MethodChannel _channel; - final Function(int id)? onFilamentViewCreatedHandler; + late MethodChannel _channel = MethodChannel("app.polyvox.filament/event"); - PolyvoxFilamentController({this.onFilamentViewCreatedHandler}); - - @override - void onFilamentViewCreated(int id) async { - _id = id; - _channel = MethodChannel("app.polyvox.filament/filament_view_$id"); + PolyvoxFilamentController() { _channel.setMethodCallHandler((call) async { print("Received Filament method channel call : ${call.method}"); - if (call.method == "ready") { - onFilamentViewCreatedHandler?.call(_id); - return Future.value(true); - } else { - throw Exception("Unknown method channel invocation ${call.method}"); - } + throw Exception("Unknown method channel invocation ${call.method}"); }); } + Future initialize(int width, int height) async { + textureId = await _channel.invokeMethod("initialize", [width, height]); + } + + Future resize(int width, int height) async { + await _channel.invokeMethod("resize", [width, height]); + } + @override Future setBackgroundImage(String path) async { await _channel.invokeMethod("setBackgroundImage", path); diff --git a/lib/filament_widget.dart b/lib/filament_widget.dart new file mode 100644 index 00000000..499c6af9 --- /dev/null +++ b/lib/filament_widget.dart @@ -0,0 +1,88 @@ +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; +import 'filament_controller.dart'; + + +typedef ResizeCallback = void Function(Size oldSize, 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); + + late var _oldSize = size; + + @override + void performLayout() { + super.performLayout(); + if (size != _oldSize) { + onLayoutChangedCallback(_oldSize, size); + _oldSize = size; + } + } +} + +class FilamentWidget extends StatefulWidget { + + final FilamentController controller; + + const FilamentWidget({Key? key, required this.controller}) : super(key: key); + + @override + _FilamentWidgetState createState() => _FilamentWidgetState(); +} + +class _FilamentWidgetState extends State { + + bool _ready = false; + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + var size = ((context.findRenderObject()) as RenderBox).size; + print("Requesting texture creation for Filament of size $size"); + await widget.controller.initialize(size.width.toInt(), size.height.toInt()); + print("Filament texture available"); + setState(() { + _ready = true; + }); + }); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + if(!_ready) { + return Container(); + } + return ResizeObserver( + onResized: (Size oldSize, Size newSize) async { + await widget.controller.resize(newSize.width.toInt(), newSize.height.toInt()); + }, + child:Texture( + textureId: widget.controller.textureId, + filterQuality: FilterQuality.none, + )); + } +} diff --git a/lib/gesture_detecting_filament_view.dart b/lib/gesture_detecting_filament_view.dart index 5004ce64..76370079 100644 --- a/lib/gesture_detecting_filament_view.dart +++ b/lib/gesture_detecting_filament_view.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'filament_controller.dart'; -import 'view/filament_widget.dart'; +import 'filament_widget.dart'; class GestureDetectingFilamentView extends StatefulWidget { final FilamentController controller; diff --git a/lib/view/filament_view.dart b/lib/view/filament_view.dart deleted file mode 100644 index bfd2d774..00000000 --- a/lib/view/filament_view.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/rendering.dart'; -import 'package:flutter/widgets.dart'; - -import 'filament_view_platform.dart'; - -class FilamentView extends FilamentViewPlatform { - static const FILAMENT_VIEW_ID = 'app.polyvox.filament/filament_view'; - - @override - Widget buildView( - int creationId, - FilamentViewCreatedCallback onFilamentViewCreated, - ) { - switch (defaultTargetPlatform) { - case TargetPlatform.android: - return AndroidView( - viewType: FILAMENT_VIEW_ID, - gestureRecognizers: >{}, - hitTestBehavior: PlatformViewHitTestBehavior.opaque, - onPlatformViewCreated: (id) { - onFilamentViewCreated(id); - }); - case TargetPlatform.iOS: - return UiKitView( - viewType: FILAMENT_VIEW_ID, - onPlatformViewCreated: (int id) { - onFilamentViewCreated(id); - }, - ); - case TargetPlatform.windows: - return Text("Flutter doesn't support platform view on Windows yet."); - default: - return Text( - '$defaultTargetPlatform is not yet implemented by Filament plugin.'); - } - } -} diff --git a/lib/view/filament_view_platform.dart b/lib/view/filament_view_platform.dart deleted file mode 100644 index b2e178a1..00000000 --- a/lib/view/filament_view_platform.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:flutter/widgets.dart'; -import 'package:polyvox_filament/view/filament_view.dart'; -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -typedef FilamentViewCreatedCallback = void Function(int id); - -abstract class FilamentViewPlatform extends PlatformInterface { - FilamentViewPlatform() : super(token: _token); - - static final Object _token = Object(); - static final FilamentViewPlatform _instance = FilamentView(); - - static FilamentViewPlatform get instance => _instance; - - Widget buildView( - int creationId, - FilamentViewCreatedCallback onFilamentViewCreated, - ) { - throw UnimplementedError('buildView() has not been implemented.'); - } -} diff --git a/lib/view/filament_widget.dart b/lib/view/filament_widget.dart deleted file mode 100644 index 5d1be8f9..00000000 --- a/lib/view/filament_widget.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/rendering.dart'; -import 'package:flutter/widgets.dart'; -import 'package:polyvox_filament/view/filament_view.dart'; - -import '../filament_controller.dart'; -import 'filament_view_platform.dart'; - -int _nextFilamentCreationId = 0; - -class FilamentWidget extends StatefulWidget { - final FilamentController controller; - - const FilamentWidget({Key? key, required this.controller}) : super(key: key); - - @override - _FilamentWidgetState createState() => _FilamentWidgetState(); -} - -class _FilamentWidgetState extends State { - final _viewId = _nextFilamentCreationId++; - - @override - Widget build(BuildContext context) { - return FilamentViewPlatform.instance - .buildView(_viewId, widget.controller.onFilamentViewCreated); - } -}