diff --git a/README.md b/README.md index afc3e1f..1ea335f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - Load glTF/glb models with URL - File cache -## Install Option A: via OpenUPM command-line interface +## Install via OpenUPM command-line interface ```shell # Install openupm-cli @@ -25,27 +25,6 @@ cd YOUR_UNITY_PROJECT_DIR openupm add -f com.from2001.gltfast-visualscripting-nodes ``` -## Install Option B: via Unity package manager - -### 1. Setup scoped registories - -Open "Edit - Project Settings - Package Manager" on your Unity project. - -Add Scoped Registories and click "Apply". - -Name: `OpenUPM` -URL: `https://package.openupm.com` -Scopes: -`com.cysharp.unitask` -`com.from2001.gltfast-visualscripting-nodes` -`com.openupm` - -![Project Settings](https://github.com/from2001/glTFast_VisualScriptingNodes/assets/387880/dd5a5f9c-47fc-421c-b262-c27702ce882b) - -### 2. Install glTFast Visual Scripting Node Package with Package Manager - -![Package Manager](https://github.com/from2001/glTFast_VisualScriptingNodes/assets/387880/73f12fe8-164a-4774-9e76-27771b447186) - ## How to Use Notice: Check "Coroutine" in the "On Start Event" triger node. diff --git a/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Nodes/LoadGltf.cs b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Nodes/LoadGltf.cs index 4165f68..34751eb 100755 --- a/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Nodes/LoadGltf.cs +++ b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Nodes/LoadGltf.cs @@ -1,11 +1,10 @@ using UnityEngine; using Unity.VisualScripting; +using UnityEngine.UI; using Cysharp.Threading.Tasks; using System.Collections; using GLTFast; -using UnityEngine.Networking; using System; -using System.IO; using STYLY.Http; using STYLY.Http.Service; using UnityGLTF; @@ -37,6 +36,9 @@ public class LoadGltf : Unit public ValueOutput result; private GameObject resultValue; + private GameObject loadingIcon; + + private ThrobberRotator throbberRotator; protected override void Definition() { inputTrigger = ControlInputCoroutine("inputTrigger", Enter); @@ -44,7 +46,7 @@ protected override void Definition() glTF_URL = ValueInput("glTF/glb URL", ""); TargetGameobject = ValueInput("Target Game Object", null); - NormalizeScale = ValueInput("Normalize Scale", true); + NormalizeScale = ValueInput("Normalize Scale", false); result = ValueOutput("Game Object", (flow) => resultValue); } @@ -54,15 +56,105 @@ private IEnumerator Enter(Flow flow) GameObject target = flow.GetValue(TargetGameobject); bool adjustScale = flow.GetValue(NormalizeScale); GameObject gltfInstance = null; + + ShowLoadingIcon(target); + UniTask.Create(async () => { gltfInstance = await LoadGltfWithURL(url, target, adjustScale); }).Forget(); yield return new WaitUntil(() => gltfInstance); + + HideLoadingIcon(); + resultValue = gltfInstance; yield return outputTrigger; } + /// + /// Takes care of the loading icon creation and calls the animation accordingly + /// + /// + private void ShowLoadingIcon(GameObject target) + { + loadingIcon = new GameObject("LoadingIcon"); + Canvas canvas = loadingIcon.AddComponent(); + canvas.renderMode = RenderMode.WorldSpace; + CanvasScaler canvasScaler = loadingIcon.AddComponent(); + canvasScaler.dynamicPixelsPerUnit = 10; + + // Add an Image component to serve as the loading icon + GameObject icon = new GameObject("Icon"); + icon.transform.SetParent(loadingIcon.transform); + Image image = icon.AddComponent(); + + // Load the throbber sprite from Resources, the image file can be changed easily. + Sprite throbberSprite = Resources.Load("throbber"); + if (throbberSprite != null) + { + image.sprite = throbberSprite; + } + else + { + Debug.LogWarning("Throbber sprite not found in Resources/throbber"); + image.color = Color.white; // Fallback color if the sprite is not found + } + + // Set the size of the loading icon + RectTransform rectTransform = image.GetComponent(); + rectTransform.sizeDelta = new Vector2(0.5f, 0.5f); // Set size of the icon in world units. I decided to put it in 0.5 so it is not intrusive + + // Position the loading icon based on the target object + if (target != null) + { + // Calculate bounds of the target object + Bounds bounds = GetTargetBounds(target); + loadingIcon.transform.position = bounds.center; + rectTransform.anchoredPosition = Vector2.zero; // Center the icon + } + + // Add ThrobberRotator component and start the throbber animation + throbberRotator = loadingIcon.AddComponent(); + throbberRotator.Initialize(icon.transform); + } + + /// + /// Receives the location of the target model to put the loading icon on top of it + /// + /// + /// + private Bounds GetTargetBounds(GameObject target) + { + Renderer[] renderers = target.GetComponentsInChildren(); + if (renderers.Length == 0) + { + return new Bounds(target.transform.position, Vector3.one); + } + + Bounds bounds = renderers[0].bounds; + foreach (Renderer renderer in renderers) + { + bounds.Encapsulate(renderer.bounds); + } + return bounds; + } + + /// + /// Hide the loading icon after the gltf is shown + /// + private void HideLoadingIcon() + { + if (loadingIcon != null) + { + if (throbberRotator != null) + { + throbberRotator.StopRotation(); + } + GameObject.Destroy(loadingIcon); + } + } + + /// /// Load glTF/glb with URL using UnityGLTF @@ -73,6 +165,9 @@ private IEnumerator Enter(Flow flow) /// private async UniTask LoadGltfWithURL(string URL, GameObject target = null, bool normalizescale = true) { + // Load completed flag + bool loadCompleted = false; + // Create glTF GameObject GameObject glTF = new("glTF"); var UnityGltfScript = glTF.AddComponent(); @@ -85,9 +180,10 @@ private async UniTask LoadGltfWithURL(string URL, GameObject target UnityGltfScript.PlayAnimationOnLoad = true; UnityGltfScript.HideSceneObjDuringLoad = false; UnityGltfScript.Factory = null; + UnityGltfScript.onLoadComplete = () => loadCompleted = true; - // Load glTF/glb - await UnityGltfScript.Load(); + // Wait until the glTF is loaded + await UniTask.WaitUntil(() => loadCompleted); // Adjust scale to 1 unit size if (normalizescale) Utils.FitToUnitSize(glTF); diff --git a/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Nodes/ThrobberRotator.cs b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Nodes/ThrobberRotator.cs new file mode 100755 index 0000000..e69e513 --- /dev/null +++ b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Nodes/ThrobberRotator.cs @@ -0,0 +1,34 @@ +using UnityEngine; +using System.Collections; + +/// +/// Rotates the throbber to make it seem like a loading animation +/// +public class ThrobberRotator : MonoBehaviour +{ + private Transform iconTransform; + private Coroutine rotationCoroutine; + + public void Initialize(Transform iconTransform) + { + this.iconTransform = iconTransform; + rotationCoroutine = StartCoroutine(RotateThrobber()); + } + + private IEnumerator RotateThrobber() + { + while (true) + { + iconTransform.Rotate(Vector3.forward, -360 * Time.deltaTime); + yield return null; + } + } + + public void StopRotation() + { + if (rotationCoroutine != null) + { + StopCoroutine(rotationCoroutine); + } + } +} \ No newline at end of file diff --git a/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Resources/throbber.png b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Resources/throbber.png new file mode 100644 index 0000000..5ffda81 Binary files /dev/null and b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Resources/throbber.png differ diff --git a/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Resources/throbber.png.meta b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Resources/throbber.png.meta new file mode 100644 index 0000000..55e37a4 --- /dev/null +++ b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/Runtime/Resources/throbber.png.meta @@ -0,0 +1,153 @@ +fileFormatVersion: 2 +guid: 20f9e8a5c08f7431ca43de00d62751bf +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: VisionOS + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/package.json b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/package.json index fa9873d..780ba5c 100755 --- a/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/package.json +++ b/glTFast_VisualScriptingNodes/Packages/com.from2001.gltfast-visualscripting-nodes/package.json @@ -1,6 +1,6 @@ { "name": "com.from2001.gltfast-visualscripting-nodes", - "version": "0.1.3", + "version": "0.1.4", "displayName": "glTFast Visual Scripting Nodes", "description": "Unity Visual Scripting node library for glTF", "unity": "2021.3",