internal async Task <IList <Actor> > CreateFromGLTF(string resourceUrl, string assetName, Guid?parentId, ColliderType colliderType) { UtilMethods.GetUrlParts(resourceUrl, out string rootUrl, out string filename); var loader = new WebRequestLoader(rootUrl); var importer = MREAPI.AppsAPI.GLTFImporterFactory.CreateImporter(filename, loader, _asyncHelper); var parent = _app.FindActor(parentId ?? Guid.Empty) as Actor; importer.SceneParent = parent?.transform ?? _app.SceneRoot.transform; importer.Collider = colliderType.ToGLTFColliderType(); await importer.LoadSceneAsync().ConfigureAwait(true); // note: actor properties are set in App#ProcessCreatedActors IList <Actor> actors = new List <Actor>(); importer.LastLoadedScene.name = assetName; MWGOTreeWalker.VisitTree(importer.LastLoadedScene, (go) => { go.layer = UnityConstants.ActorLayerIndex; actors.Add(go.AddComponent <Actor>()); }); importer.Dispose(); return(actors); }
internal IList <Actor> CreateFromPrefab(Guid prefabId, Guid?parentId, CollisionLayer?collisionLayer) { GameObject prefab = MREAPI.AppsAPI.AssetCache.GetAsset(prefabId) as GameObject; GameObject instance = UnityEngine.Object.Instantiate( prefab, GetGameObjectFromParentId(parentId).transform, false); // note: actor properties are set in App#ProcessCreatedActors var actorList = new List <Actor>(); MWGOTreeWalker.VisitTree(instance, go => { var collider = go.GetComponent <UnityEngine.Collider>(); if (collider != null) { MREAPI.AppsAPI.LayerApplicator.ApplyLayerToCollider(collisionLayer, collider); } else { go.layer = MREAPI.AppsAPI.LayerApplicator.DefaultLayer; } actorList.Add(go.AddComponent <Actor>()); }); return(actorList); }
private Asset GenerateAssetPatch(UnityEngine.Object unityAsset, Guid id) { if (unityAsset is GameObject go) { int actorCount = 0; MWGOTreeWalker.VisitTree(go, _ => { actorCount++; }); return(new Asset { Id = id, Prefab = new Prefab() { ActorCount = actorCount } }); } else if (unityAsset is UnityEngine.Material mat) { return(new Asset() { Id = id, Material = MREAPI.AppsAPI.MaterialPatcher.GeneratePatch(mat) }); } else if (unityAsset is UnityEngine.Texture tex) { return(new Asset() { Id = id, Texture = new MWTexture() { Resolution = new Vector2Patch() { X = tex.width, Y = tex.height }, WrapModeU = tex.wrapModeU, WrapModeV = tex.wrapModeV } }); } else if (unityAsset is AudioClip sound) { return(new Asset() { Id = id, Sound = new MWSound() { Duration = sound.length } }); } else { throw new Exception($"Asset {id} is not patchable, or not of the right type!"); } }
internal IList <Actor> CreateFromPrefab(Guid prefabId, Guid?parentId, CollisionLayer?collisionLayer) { var asset = _app.AssetManager.GetById(prefabId)?.Asset as Node; Spatial prefab = asset.Duplicate() as Spatial; // restore assigned animation. var animationPlayer = asset.GetChild <AnimationPlayer>(); if (animationPlayer != null) { var prefabAnimationPlayer = prefab.GetNode <AnimationPlayer>(animationPlayer.Name); prefabAnimationPlayer.AssignedAnimation = animationPlayer.AssignedAnimation; } Spatial parent = GetGameObjectFromParentId(parentId); parent.AddChild(prefab); // copy animation target mapping var sourceMap = prefab.GetChild <PrefabAnimationTargets>(); var destMap = asset.GetChild <PrefabAnimationTargets>(); if (sourceMap != null && destMap != null) { destMap.AnimationTargets = sourceMap.AnimationTargets; } // note: actor properties are set in App#ProcessCreatedActors var actorList = new List <Actor>(); MWGOTreeWalker.VisitTree(prefab, go => { var collider = go.GetChild <Area>(); if (collider != null) { MREAPI.AppsAPI.LayerApplicator.ApplyLayerToCollider(collisionLayer, collider); } if (go is Spatial) { var newActor = Actor.Instantiate((Spatial)go); actorList.Add(newActor); } }); return(actorList); }
internal IList <Actor> CreateFromPrefab(Guid prefabId, Guid?parentId) { GameObject prefab = MREAPI.AppsAPI.AssetCache.GetAsset(prefabId) as GameObject; GameObject instance = UnityEngine.Object.Instantiate( prefab, GetGameObjectFromParentId(parentId).transform, false); // note: actor properties are set in App#ProcessCreatedActors var actorList = new List <Actor>(); MWGOTreeWalker.VisitTree(instance, go => { go.layer = UnityConstants.ActorLayerIndex; actorList.Add(go.AddComponent <Actor>()); }); return(actorList); }
internal IList <Actor> CreateFromPrefab(Guid prefabId, Guid?parentId, CollisionLayer?collisionLayer) { GameObject prefab = _app.AssetManager.GetById(prefabId)?.Asset as GameObject; GameObject instance = UnityEngine.Object.Instantiate( prefab, GetGameObjectFromParentId(parentId).transform, false); // copy animation target mapping var sourceMap = prefab.GetComponent <PrefabAnimationTargets>(); var destMap = instance.GetComponent <PrefabAnimationTargets>(); if (sourceMap != null && destMap != null) { destMap.AnimationTargets = sourceMap.AnimationTargets; } // note: actor properties are set in App#ProcessCreatedActors var actorList = new List <Actor>(); MWGOTreeWalker.VisitTree(instance, go => { var collider = go.GetComponent <UnityEngine.Collider>(); if (collider != null) { MREAPI.AppsAPI.LayerApplicator.ApplyLayerToCollider(collisionLayer, collider); } else { go.layer = MREAPI.AppsAPI.LayerApplicator.DefaultLayer; } actorList.Add(go.AddComponent <Actor>()); }); return(actorList); }
private Asset GenerateAssetPatch(UnityEngine.Object unityAsset, Guid id) { if (unityAsset is GameObject go) { int actorCount = 0; MWGOTreeWalker.VisitTree(go, _ => { actorCount++; }); return(new Asset { Id = id, Prefab = new Prefab() { ActorCount = actorCount } }); } else if (unityAsset is UnityEngine.Material mat) { return(new Asset() { Id = id, Material = MREAPI.AppsAPI.MaterialPatcher.GeneratePatch(_app, mat) }); } else if (unityAsset is UnityEngine.Texture tex) { return(new Asset() { Id = id, Texture = new MWTexture() { Resolution = new Vector2Patch() { X = tex.width, Y = tex.height }, WrapModeU = tex.wrapModeU, WrapModeV = tex.wrapModeV } }); } else if (unityAsset is UnityEngine.Mesh mesh) { return(new Asset() { Id = id, Mesh = new MWMesh() { VertexCount = mesh.vertexCount, TriangleCount = mesh.triangles.Length / 3, BoundingBoxDimensions = new Vector3Patch() { X = mesh.bounds.size.x, Y = mesh.bounds.size.y, Z = mesh.bounds.size.z }, BoundingBoxCenter = new Vector3Patch() { X = mesh.bounds.center.x, Y = mesh.bounds.center.y, Z = mesh.bounds.center.z } } }); } else if (unityAsset is AudioClip sound) { return(new Asset() { Id = id, Sound = new MWSound() { Duration = sound.length } }); } else if (unityAsset is VideoStreamDescription videoStream) { return(new Asset() { Id = id, VideoStream = new MWVideoStream() { Duration = videoStream.Duration } }); } else if (unityAsset is AnimationDataCached animData) { return(new Asset() { Id = id }); } else { throw new Exception($"Asset {id} is not patchable, or not of the right type!"); } }
private async Task <IList <UnityEngine.Object> > LoadGltfFromStream(WebRequestLoader loader, Stream stream, ColliderType colliderType) { var assets = new List <UnityEngine.Object>(30); // pre-parse glTF document so we can get a scene count // run this on a threadpool thread so that the Unity main thread is not blocked GLTF.Schema.GLTFRoot gltfRoot = null; try { await Task.Run(() => { GLTF.GLTFParser.ParseJson(stream, out gltfRoot); }); } catch (Exception e) { Debug.LogError(e); } if (gltfRoot == null) { throw new GLTFLoadException("Failed to parse glTF"); } stream.Position = 0; using (GLTFSceneImporter importer = MREAPI.AppsAPI.GLTFImporterFactory.CreateImporter(gltfRoot, loader, _asyncHelper, stream)) { importer.SceneParent = MREAPI.AppsAPI.AssetCache.CacheRootGO.transform; importer.Collider = colliderType.ToGLTFColliderType(); // load textures if (gltfRoot.Textures != null) { for (var i = 0; i < gltfRoot.Textures.Count; i++) { await importer.LoadTextureAsync(gltfRoot.Textures[i], i, true); var texture = importer.GetTexture(i); texture.name = gltfRoot.Textures[i].Name ?? $"texture:{i}"; assets.Add(texture); } } // load meshes if (gltfRoot.Meshes != null) { var cancellationSource = new System.Threading.CancellationTokenSource(); for (var i = 0; i < gltfRoot.Meshes.Count; i++) { var mesh = await importer.LoadMeshAsync(i, cancellationSource.Token); mesh.name = gltfRoot.Meshes[i].Name ?? $"mesh:{i}"; assets.Add(mesh); } } // load materials if (gltfRoot.Materials != null) { for (var i = 0; i < gltfRoot.Materials.Count; i++) { var matdef = gltfRoot.Materials[i]; var material = await importer.LoadMaterialAsync(i); material.name = matdef.Name ?? $"material:{i}"; assets.Add(material); } } // load prefabs if (gltfRoot.Scenes != null) { for (var i = 0; i < gltfRoot.Scenes.Count; i++) { await importer.LoadSceneAsync(i).ConfigureAwait(true); GameObject rootObject = importer.LastLoadedScene; rootObject.name = gltfRoot.Scenes[i].Name ?? $"scene:{i}"; var animation = rootObject.GetComponent <UnityEngine.Animation>(); if (animation != null) { animation.playAutomatically = false; // initialize mapping so we know which gameobjects are targeted by which animation clips var mapping = rootObject.AddComponent <PrefabAnimationTargets>(); mapping.Initialize(gltfRoot, i); } MWGOTreeWalker.VisitTree(rootObject, (go) => { go.layer = MREAPI.AppsAPI.LayerApplicator.DefaultLayer; }); assets.Add(rootObject); } } } return(assets); }
private async Task <IList <Asset> > LoadAssetsFromGLTF(AssetSource source, Guid containerId, ColliderType colliderType) { IList <Asset> assets = new List <Asset>(); DeterministicGuids guidGenerator = new DeterministicGuids(UtilMethods.StringToGuid( $"{containerId}:{source.ParsedUri.AbsoluteUri}")); // download file UtilMethods.GetUrlParts(source.ParsedUri.AbsoluteUri, out string rootUrl, out string filename); var loader = new WebRequestLoader(rootUrl); await loader.LoadStream(filename); // pre-parse glTF document so we can get a scene count // TODO: run this in thread GLTF.GLTFParser.ParseJson(loader.LoadedStream, out GLTF.Schema.GLTFRoot gltfRoot); GLTFSceneImporter importer = MREAPI.AppsAPI.GLTFImporterFactory.CreateImporter(gltfRoot, loader, _asyncHelper, loader.LoadedStream); importer.SceneParent = MREAPI.AppsAPI.AssetCache.CacheRootGO().transform; importer.Collider = colliderType.ToGLTFColliderType(); // load prefabs if (gltfRoot.Scenes != null) { for (var i = 0; i < gltfRoot.Scenes.Count; i++) { await importer.LoadSceneAsync(i); GameObject rootObject = importer.LastLoadedScene; rootObject.name = gltfRoot.Scenes[i].Name ?? $"scene:{i}"; MWGOTreeWalker.VisitTree(rootObject, (go) => { go.layer = UnityConstants.ActorLayerIndex; }); var def = GenerateAssetPatch(rootObject, guidGenerator.Next()); def.Name = rootObject.name; def.Source = new AssetSource(source.ContainerType, source.Uri, $"scene:{i}"); MREAPI.AppsAPI.AssetCache.CacheAsset(rootObject, def.Id, containerId, source); assets.Add(def); } } // load textures if (gltfRoot.Textures != null) { for (var i = 0; i < gltfRoot.Textures.Count; i++) { await importer.LoadTextureAsync(gltfRoot.Textures[i], i, true); var texture = importer.GetTexture(i); texture.name = gltfRoot.Textures[i].Name ?? $"texture:{i}"; var asset = GenerateAssetPatch(texture, guidGenerator.Next()); asset.Name = texture.name; asset.Source = new AssetSource(source.ContainerType, source.Uri, $"texture:{i}"); MREAPI.AppsAPI.AssetCache.CacheAsset(texture, asset.Id, containerId, source); assets.Add(asset); } } // load materials if (gltfRoot.Materials != null) { for (var i = 0; i < gltfRoot.Materials.Count; i++) { var matdef = gltfRoot.Materials[i]; var material = await importer.LoadMaterialAsync(i); material.name = matdef.Name ?? $"material:{i}"; var asset = GenerateAssetPatch(material, guidGenerator.Next()); asset.Name = material.name; asset.Source = new AssetSource(source.ContainerType, source.Uri, $"material:{i}"); MREAPI.AppsAPI.AssetCache.CacheAsset(material, asset.Id, containerId, source); assets.Add(asset); } } importer.Dispose(); return(assets); }
private async Task <IList <Asset> > LoadAssetsFromGLTF(AssetSource source, Guid containerId, ColliderType colliderType) { IList <Asset> assets = new List <Asset>(); DeterministicGuids guidGenerator = new DeterministicGuids(UtilMethods.StringToGuid( $"{containerId}:{source.ParsedUri.AbsoluteUri}")); // download file var rootUrl = URIHelper.GetDirectoryName(source.ParsedUri.AbsoluteUri); var loader = new WebRequestLoader(rootUrl); var stream = await loader.LoadStreamAsync(URIHelper.GetFileFromUri(source.ParsedUri)); // pre-parse glTF document so we can get a scene count // TODO: run this in thread GLTF.GLTFParser.ParseJson(stream, out GLTF.Schema.GLTFRoot gltfRoot); stream.Position = 0; GLTFSceneImporter importer = MREAPI.AppsAPI.GLTFImporterFactory.CreateImporter(gltfRoot, loader, _asyncHelper, stream); importer.SceneParent = MREAPI.AppsAPI.AssetCache.CacheRootGO().transform; importer.Collider = colliderType.ToGLTFColliderType(); // load textures if (gltfRoot.Textures != null) { for (var i = 0; i < gltfRoot.Textures.Count; i++) { await importer.LoadTextureAsync(gltfRoot.Textures[i], i, true); var texture = importer.GetTexture(i); texture.name = gltfRoot.Textures[i].Name ?? $"texture:{i}"; var asset = GenerateAssetPatch(texture, guidGenerator.Next()); asset.Name = texture.name; asset.Source = new AssetSource(source.ContainerType, source.Uri, $"texture:{i}"); MREAPI.AppsAPI.AssetCache.CacheAsset(texture, asset.Id, containerId, source); assets.Add(asset); } } // load meshes if (gltfRoot.Meshes != null) { var cancellationSource = new System.Threading.CancellationTokenSource(); for (var i = 0; i < gltfRoot.Meshes.Count; i++) { var mesh = await importer.LoadMeshAsync(i, cancellationSource.Token); mesh.name = gltfRoot.Meshes[i].Name ?? $"mesh:{i}"; var asset = GenerateAssetPatch(mesh, guidGenerator.Next()); asset.Name = mesh.name; asset.Source = new AssetSource(source.ContainerType, source.Uri, $"mesh:{i}"); var colliderGeo = colliderType == ColliderType.Mesh ? (ColliderGeometry) new MeshColliderGeometry() { MeshId = asset.Id } : (ColliderGeometry) new BoxColliderGeometry() { Size = (mesh.bounds.size * 0.8f).CreateMWVector3() }; MREAPI.AppsAPI.AssetCache.CacheAsset(mesh, asset.Id, containerId, source, colliderGeo); assets.Add(asset); } } // load materials if (gltfRoot.Materials != null) { for (var i = 0; i < gltfRoot.Materials.Count; i++) { var matdef = gltfRoot.Materials[i]; var material = await importer.LoadMaterialAsync(i); material.name = matdef.Name ?? $"material:{i}"; var asset = GenerateAssetPatch(material, guidGenerator.Next()); asset.Name = material.name; asset.Source = new AssetSource(source.ContainerType, source.Uri, $"material:{i}"); MREAPI.AppsAPI.AssetCache.CacheAsset(material, asset.Id, containerId, source); assets.Add(asset); } } // load prefabs if (gltfRoot.Scenes != null) { for (var i = 0; i < gltfRoot.Scenes.Count; i++) { await importer.LoadSceneAsync(i).ConfigureAwait(true); GameObject rootObject = importer.LastLoadedScene; rootObject.name = gltfRoot.Scenes[i].Name ?? $"scene:{i}"; var animation = rootObject.GetComponent <UnityEngine.Animation>(); if (animation != null) { animation.playAutomatically = false; // initialize mapping so we know which gameobjects are targeted by which animation clips var mapping = rootObject.AddComponent <PrefabAnimationTargets>(); mapping.Initialize(gltfRoot, i); } MWGOTreeWalker.VisitTree(rootObject, (go) => { go.layer = MREAPI.AppsAPI.LayerApplicator.DefaultLayer; }); var def = GenerateAssetPatch(rootObject, guidGenerator.Next()); def.Name = rootObject.name; def.Source = new AssetSource(source.ContainerType, source.Uri, $"scene:{i}"); MREAPI.AppsAPI.AssetCache.CacheAsset(rootObject, def.Id, containerId, source); assets.Add(def); } } importer.Dispose(); return(assets); }
private Asset GenerateAssetPatch(Godot.Object unityAsset, Guid id) { if (unityAsset is Node go) { int actorCount = 0; MWGOTreeWalker.VisitTree(go, _ => { actorCount++; }); return(new Asset { Id = id, Prefab = new Prefab() { ActorCount = actorCount } }); } else if (unityAsset is Godot.SpatialMaterial mat) { return(new Asset() { Id = id, Material = MREAPI.AppsAPI.MaterialPatcher.GeneratePatch(_app, mat) }); } else if (unityAsset is Godot.Texture tex) { return(new Asset() { Id = id, Texture = new MWTexture() { Resolution = new Vector2Patch(tex.GetSize()), Flags = tex.Flags, } }); } else if (unityAsset is Godot.Mesh mesh) { ArrayMesh arrayMesh = mesh as ArrayMesh; Godot.Collections.Array array = arrayMesh.SurfaceGetArrays(0); var aabb = arrayMesh.GetAabb(); var vertexCount = (array[(int)ArrayMesh.ArrayType.Vertex] as Array).Length; return(new Asset() { Id = id, Mesh = new MWMesh() { VertexCount = vertexCount, //FIXME //TriangleCount = mesh.triangles.Length / 3, BoundingBoxDimensions = new Vector3Patch() { X = aabb.Size.x, Y = aabb.Size.y, Z = aabb.Size.z }, BoundingBoxCenter = new Vector3Patch() { X = aabb.Position.x, Y = aabb.Position.y, Z = aabb.Position.z } } }); } else if (unityAsset is AudioStream sound) { return(new Asset() { Id = id, Sound = new MWSound() { Duration = sound.GetLength() } }); } /* * else if (unityAsset is VideoStreamDescription videoStream) * { * return new Asset() * { * Id = id, * VideoStream = new MWVideoStream() * { * Duration = videoStream.Duration * } * }; * } */ else if (unityAsset is AnimationDataCached animData) { return(new Asset() { Id = id }); } else { throw new Exception($"Asset {id} is not patchable, or not of the right type!"); } }