diff --git a/example/lib/main.dart b/example/lib/main.dart index 5bafc7d5..b4c7f4de 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -31,10 +31,7 @@ class _MyAppState extends State with SingleTickerProviderStateMixin { Widget build(BuildContext context) { return MaterialApp( // showPerformanceOverlay: true, - home: Scaffold( - body: - ExampleWidget() - )); + home: Scaffold(body: ExampleWidget())); } } @@ -60,7 +57,7 @@ class _ExampleWidgetState extends State { bool _loop = false; EdgeInsets _viewportMargin = EdgeInsets.zero; - bool _readyForScene = false; + bool _hasViewer = false; bool _rendering = false; int _framerate = 60; @@ -69,13 +66,10 @@ class _ExampleWidgetState extends State { bool _coneHidden = false; bool _frustumCulling = true; - StreamSubscription? _hasViewerListener; - @override void dispose() { super.dispose(); _pickResultListener?.cancel(); - _hasViewerListener?.cancel(); } Widget _item(void Function() onTap, String text) { @@ -99,12 +93,6 @@ class _ExampleWidgetState extends State { picked = _filamentController!.getNameForEntity(entityId!); }); }); - _hasViewerListener = - _filamentController!.hasViewer.listen((bool hasViewer) { - setState(() { - _readyForScene = hasViewer; - }); - }); } @override @@ -115,7 +103,7 @@ class _ExampleWidgetState extends State { children.addAll([ _item(() { _createController(); - }, "create viewer (default ubershader)"), + }, "create FilamentController (default ubershader)"), _item(() { _createController( uberArchivePath: Platform.isWindows @@ -125,233 +113,250 @@ class _ExampleWidgetState extends State { : Platform.isIOS ? "assets/lit_opaque_43.uberz" : "assets/lit_opaque_43_gles.uberz"); - }, "create viewer (custom ubershader - lit opaque only)"), + }, "create FilamentController (custom ubershader - lit opaque only)"), ]); - } + } else { + if (!_hasViewer) { + children.addAll([ + _item(() { + _filamentController!.createViewer(); + setState(() { + _hasViewer = true; + }); + }, "create FilamentViewer") + ]); + } else { + children.addAll([ + _item(() { + _filamentController!.destroy(); + _filamentController = null; + setState(() { + _hasViewer = true; + }); + }, "destroy viewer/texture"), + _item(() { + _filamentController!.render(); + }, "render"), + _item(() { + setState(() { + _rendering = !_rendering; + _filamentController!.setRendering(_rendering); + }); + }, "Rendering: $_rendering"), + _item(() { + setState(() { + _framerate = _framerate == 60 ? 30 : 60; + _filamentController!.setFrameRate(_framerate); + }); + }, "$_framerate fps"), + _item(() { + _filamentController!.setBackgroundColor(Color(0xFF73C9FA)); + }, "set background color"), + _item(() { + _filamentController!.setBackgroundImage('assets/background.ktx'); + }, "load background image"), + _item(() { + _filamentController! + .setBackgroundImage('assets/background.ktx', fillHeight: true); + }, "load background image (fill height)"), + _item(() { + _filamentController! + .loadSkybox('assets/default_env/default_env_skybox.ktx'); + }, 'load skybox'), + _item(() { + _filamentController! + .loadIbl('assets/default_env/default_env_ibl.ktx'); + }, 'load IBL'), + _item(() async { + _light = await _filamentController! + .addLight(1, 6500, 150000, 0, 1, 0, 0, -1, 0, true); + }, "add directional light"), + _item(() async { + await _filamentController!.clearLights(); + }, "clear lights"), + _item(() { + setState(() { + _postProcessing = !_postProcessing; + }); + _filamentController!.setPostProcessing(_postProcessing); + }, "${_postProcessing ? "Disable" : "Enable"} postprocessing"), + _item( + () { + _filamentController!.removeSkybox(); + }, + 'remove skybox', + ), + _item(() async { + _shapes = + await _filamentController!.loadGlb('assets/shapes/shapes.glb'); + _animations = + await _filamentController!.getAnimationNames(_shapes!); + setState(() {}); + }, 'load shapes GLB'), + _item(() async { + _animations = await _filamentController!.setCamera(_shapes!, null); + setState(() {}); + }, 'set camera to first camera in shapes GLB'), + _item(() async { + if (_coneHidden) { + _filamentController!.reveal(_shapes!, "Cone"); + } else { + _filamentController!.hide(_shapes!, "Cone"); + } + setState(() { + _coneHidden = !_coneHidden; + }); + }, _coneHidden ? 'show cone' : 'hide cone'), + _item(() async { + if (_shapes != null) { + _filamentController!.removeAsset(_shapes!); + } + _shapes = await _filamentController! + .loadGltf('assets/shapes/shapes.gltf', 'assets/shapes'); + }, 'load shapes GLTF'), + _item(() async { + _filamentController!.transformToUnitCube(_shapes!); + }, 'transform to unit cube'), + _item(() async { + _filamentController!.setPosition(_shapes!, 1.0, 1.0, -1.0); + }, 'set shapes position to 1, 1, -1'), + _item(() async { + _filamentController!.setCameraPosition(1.0, 1.0, -1.0); + }, 'move camera to 1, 1, -1'), + _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()); - if (_readyForScene) { - children.addAll([ - _item(() { - _filamentController!.destroy(); - _filamentController = null; - }, "destroy viewer/texture"), - _item(() { - _filamentController!.render(); - }, "render"), - _item(() { - setState(() { - _rendering = !_rendering; - _filamentController!.setRendering(_rendering); - }); - }, "Rendering: $_rendering"), - _item(() { - setState(() { - _framerate = _framerate == 60 ? 30 : 60; - _filamentController!.setFrameRate(_framerate); - }); - }, "$_framerate fps"), - _item(() { - _filamentController!.setBackgroundColor(Color(0xFF73C9FA)); - }, "set background color"), - _item(() { - _filamentController!.setBackgroundImage('assets/background.ktx'); - }, "load background image"), - _item(() { - _filamentController! - .setBackgroundImage('assets/background.ktx', fillHeight: true); - }, "load background image (fill height)"), - _item(() { - _filamentController! - .loadSkybox('assets/default_env/default_env_skybox.ktx'); - }, 'load skybox'), - _item(() { - _filamentController! - .loadIbl('assets/default_env/default_env_ibl.ktx'); - }, 'load IBL'), - _item(() async { - _light = await _filamentController! - .addLight(1, 6500, 150000, 0, 1, 0, 0, -1, 0, true); - }, "add directional light"), - _item(() async { - await _filamentController!.clearLights(); - }, "clear lights"), - _item(() { - setState(() { - _postProcessing = !_postProcessing; - }); - _filamentController!.setPostProcessing(_postProcessing); - }, "${_postProcessing ? "Disable" : "Enable"} postprocessing"), - _item( - () { - _filamentController!.removeSkybox(); - }, - 'remove skybox', - ), - _item(() async { - _shapes = - await _filamentController!.loadGlb('assets/shapes/shapes.glb'); - _animations = await _filamentController!.getAnimationNames(_shapes!); - setState(() {}); - }, 'load shapes GLB'), - _item(() async { - _animations = await _filamentController!.setCamera(_shapes!, null); - setState(() {}); - }, 'set camera to first camera in shapes GLB'), - _item(() async { - if (_coneHidden) { - _filamentController!.reveal(_shapes!, "Cone"); - } else { - _filamentController!.hide(_shapes!, "Cone"); - } - setState(() { - _coneHidden = !_coneHidden; - }); - }, _coneHidden ? 'show cone' : 'hide cone'), - _item(() async { - if (_shapes != null) { + _filamentController!.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 { _filamentController!.removeAsset(_shapes!); - } - _shapes = await _filamentController! - .loadGltf('assets/shapes/shapes.gltf', 'assets/shapes'); - }, 'load shapes GLTF'), - _item(() async { - _filamentController!.transformToUnitCube(_shapes!); - }, 'transform to unit cube'), - _item(() async { - _filamentController!.setPosition(_shapes!, 1.0, 1.0, -1.0); - }, 'set shapes position to 1, 1, -1'), - _item(() async { - _filamentController!.setCameraPosition(1.0, 1.0, -1.0); - }, 'move camera to 1, 1, -1'), - _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()); + _shapes = null; + }, 'remove shapes'), + _item(() async { + _filamentController!.clearAssets(); + _shapes = null; + }, 'clear all assets'), + _item(() async { + var names = await _filamentController! + .getMorphTargetNames(_shapes!, "Cylinder"); + await showDialog( + context: context, + builder: (ctx) { + return Container( + height: 100, + width: 100, + color: Colors.white, + child: Text(names.join(","))); + }); + }, "show morph target names for Cylinder"), + _item(() { + _filamentController!.setMorphTargetWeights( + _shapes!, "Cylinder", List.filled(4, 1.0)); + }, "set Cylinder morph weights to 1"), + _item(() { + _filamentController!.setMorphTargetWeights( + _shapes!, "Cylinder", List.filled(4, 0.0)); + }, "set Cylinder morph weights to 0.0"), + _item(() async { + var morphs = await _filamentController! + .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(); + _filamentController!.setMorphAnimationData(_shapes!, animation); + }, "animate cylinder morph weights #1 and #2"), + _item(() async { + var morphs = await _filamentController! + .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(); + _filamentController!.setMorphAnimationData(_shapes!, animation); + }, "animate cylinder morph weights #3 and #4"), + _item(() async { + var morphs = await _filamentController! + .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(); + _filamentController!.setMorphAnimationData(_shapes!, animation); + }, "animate shapes morph weights #1 and #2"), + _item(() { + _filamentController! + .setMaterialColor(_shapes!, "Cone", 0, Colors.purple); + }, "set cone material color to purple"), + _item(() { + _loop = !_loop; + setState(() {}); + }, "toggle animation looping ${_loop ? "OFF" : "ON"}"), + _item(() { + setState(() { + _viewportMargin = _viewportMargin == EdgeInsets.zero + ? EdgeInsets.all(50) + : EdgeInsets.zero; + }); + }, "resize"), + _item(() async { + await Permission.microphone.request(); + }, "request permissions (tests inactive->resume)") + ]); + if (_animations != null) { + children.addAll(_animations!.map((a) => _item(() { + _filamentController!.playAnimation( + _shapes!, _animations!.indexOf(a), + replaceActive: true, crossfade: 0.5, loop: _loop); + }, "play animation ${_animations!.indexOf(a)} (replace/fade)"))); + children.addAll(_animations!.map((a) => _item(() { + _filamentController!.playAnimation( + _shapes!, _animations!.indexOf(a), + replaceActive: false, loop: _loop); + }, "play animation ${_animations!.indexOf(a)} (noreplace)"))); + } - _filamentController!.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 { - _filamentController!.removeAsset(_shapes!); - _shapes = null; - }, 'remove shapes'), - _item(() async { - _filamentController!.clearAssets(); - _shapes = null; - }, 'clear all assets'), - _item(() async { - var names = await _filamentController! - .getMorphTargetNames(_shapes!, "Cylinder"); - await showDialog( - context: context, - builder: (ctx) { - return Container( - height: 100, - width: 100, - color: Colors.white, - child: Text(names.join(","))); - }); - }, "show morph target names for Cylinder"), - _item(() { - _filamentController! - .setMorphTargetWeights(_shapes!, "Cylinder", List.filled(4, 1.0)); - }, "set Cylinder morph weights to 1"), - _item(() { - _filamentController! - .setMorphTargetWeights(_shapes!, "Cylinder", List.filled(4, 0.0)); - }, "set Cylinder morph weights to 0.0"), - _item(() async { - var morphs = await _filamentController! - .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(); - _filamentController!.setMorphAnimationData(_shapes!, animation); - }, "animate cylinder morph weights #1 and #2"), - _item(() async { - var morphs = await _filamentController! - .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(); - _filamentController!.setMorphAnimationData(_shapes!, animation); - }, "animate cylinder morph weights #3 and #4"), - _item(() async { - var morphs = - await _filamentController!.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(); - _filamentController!.setMorphAnimationData(_shapes!, animation); - }, "animate shapes morph weights #1 and #2"), - _item(() { - _filamentController! - .setMaterialColor(_shapes!, "Cone", 0, Colors.purple); - }, "set cone material color to purple"), - _item(() { - _loop = !_loop; - setState(() {}); - }, "toggle animation looping ${_loop ? "OFF" : "ON"}"), - _item(() { + children.add(_item(() { + _filamentController!.setToneMapping(ToneMapper.LINEAR); + }, "Set tone mapping to linear")); + + children.add(_item(() { + _filamentController!.moveCameraToAsset(_shapes!); + }, "Move camera to asset")); + + children.add(_item(() { setState(() { - _viewportMargin = _viewportMargin == EdgeInsets.zero - ? EdgeInsets.all(50) - : EdgeInsets.zero; + _frustumCulling = !_frustumCulling; }); - }, "resize"), - _item(() async { - await Permission.microphone.request(); - }, "request permissions (tests inactive->resume)") - ]); - if (_animations != null) { - children.addAll(_animations!.map((a) => _item(() { - _filamentController!.playAnimation( - _shapes!, _animations!.indexOf(a), - replaceActive: true, crossfade: 0.5, loop: _loop); - }, "play animation ${_animations!.indexOf(a)} (replace/fade)"))); - children.addAll(_animations!.map((a) => _item(() { - _filamentController!.playAnimation( - _shapes!, _animations!.indexOf(a), - replaceActive: false, loop: _loop); - }, "play animation ${_animations!.indexOf(a)} (noreplace)"))); + _filamentController!.setViewFrustumCulling(_frustumCulling); + }, "${_frustumCulling ? "Disable" : "Enable"} frustum culling")); } - - children.add(_item(() { - _filamentController!.setToneMapping(ToneMapper.LINEAR); - }, "Set tone mapping to linear")); - - children.add(_item(() { - _filamentController!.moveCameraToAsset(_shapes!); - }, "Move camera to asset")); - - children.add(_item(() { - setState(() { - _frustumCulling = !_frustumCulling; - }); - _filamentController!.setViewFrustumCulling(_frustumCulling); - }, "${_frustumCulling ? "Disable" : "Enable"} frustum culling")); } return Stack(children: [ _filamentController != null