#if GPU_INSTANCER using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; namespace GPUInstancer.CrowdAnimations { public static class GPUICrowdAPI { #region Crowd Animator /// /// Start the given Animation Clip on the given instance /// /// Character that will play the animation clip /// Animation Clip /// (Optional) Start time of the animation clip /// (Optional) Speed of the playing clip /// (Optional) Time in seconds for smooth transition from the previous animation clips public static void StartAnimation(GPUICrowdPrefab crowdInstance, AnimationClip animationClip, float startTime = -1.0f, float speed = 1.0f, float transitionTime = 0) { crowdInstance.StartAnimation(animationClip, startTime, speed, transitionTime); } public static void StartAnimation(GPUICrowdPrefab crowdInstance, GPUIAnimationClipData clipData, float startTime = -1.0f, float speed = 1.0f, float transitionTime = 0) { crowdInstance.StartAnimation(clipData, startTime, speed, transitionTime); } /// /// Blend the given Animation Clips and start playing for the given instance /// /// Character that will play the animation clips /// Weights that will define the blending weights of the given animation clips /// Clip 1 /// Clip 2 /// (Optional) Clip 3 /// (Optional) Clip 4 /// (Optional) Time of the animation clips /// (Optional) Speed of the animation clips /// (Optional) Time in seconds for smooth transition from the previous animation clips public static void StartBlend(GPUICrowdPrefab crowdInstance, Vector4 animationWeights, AnimationClip animationClip1, AnimationClip animationClip2, AnimationClip animationClip3 = null, AnimationClip animationClip4 = null, float[] animationTimes = null, float[] animationSpeeds = null, float transitionTime = 0) { crowdInstance.StartBlend(animationWeights, animationClip1, animationClip2, animationClip3, animationClip4, animationTimes, animationSpeeds, transitionTime); } /// /// Set the blend weights of the playing animation blends /// /// Character to set the speed /// Animation Weights public static void SetAnimationWeights(GPUICrowdPrefab crowdInstance, Vector4 animationWeights) { crowdInstance.SetAnimationWeights(animationWeights); } /// /// Set the speed of the playing animation clips /// /// Character to set the speed /// Speed value public static void SetAnimationSpeed(GPUICrowdPrefab crowdInstance, float animationSpeed) { crowdInstance.SetAnimationSpeed(animationSpeed); } /// /// Set the speeds for multiple animation clips /// /// Character to set the speed /// Speed values public static void SetAnimationSpeeds(GPUICrowdPrefab crowdInstance, float[] animationSpeeds) { crowdInstance.SetAnimationSpeeds(animationSpeeds); } /// /// Returns the current time of the clip /// /// Character to get the time /// The clip to get the time for public static float GetAnimationTime(GPUICrowdPrefab crowdInstance, AnimationClip animationClip) { return crowdInstance.GetAnimationTime(animationClip); } /// /// Sets the current time of the clip /// /// Character to set the time /// The clip to set the time for /// Time in seconds public static void SetAnimationTime(GPUICrowdPrefab crowdInstance, AnimationClip animationClip, float time) { crowdInstance.SetAnimationTime(animationClip, time); } /// /// Set the animation speed for all instances of the given prototype /// /// Crowd Manager that the prototype is defined on /// Crowd Prototype /// Speed value public static void SetAnimationSpeedsForPrototype(GPUICrowdManager crowdManager, GPUICrowdPrototype crowdPrototype, float animationSpeed) { GPUICrowdRuntimeData runtimeData = (GPUICrowdRuntimeData)crowdManager.GetRuntimeData(crowdPrototype); if (runtimeData != null) { List instanceList = crowdManager.GetRegisteredPrefabsRuntimeData()[crowdPrototype]; foreach (GPUICrowdPrefab crowdInstance in instanceList) { crowdInstance.SetAnimationSpeed(animationSpeed); } } } /// /// Set the animation speeds for multiple clips for all instances of the given prototype /// /// Crowd Manager that the prototype is defined on /// Crowd Prototype /// Speed values public static void SetAnimationSpeedsForPrototype(GPUICrowdManager crowdManager, GPUICrowdPrototype crowdPrototype, float[] animationSpeeds) { GPUICrowdRuntimeData runtimeData = (GPUICrowdRuntimeData)crowdManager.GetRuntimeData(crowdPrototype); if (runtimeData != null) { List instanceList = crowdManager.GetRegisteredPrefabsRuntimeData()[crowdPrototype]; foreach (GPUICrowdPrefab crowdInstance in instanceList) { crowdInstance.SetAnimationSpeeds(animationSpeeds); } } } /// /// Add an event to an animation clip of a prototype /// /// Crowd Manager that the prototype is defined on /// Crowd Prototype /// The clip to attach the event /// Frame of the animation on which the event will take place /// UnityAction that will be invoked at the given frame for the given clip /// (Optional) Float parameter value /// (Optional) Integer parameter value /// (Optional) String parameter value public static void AddAnimationEvent(GPUICrowdManager crowdManager, GPUICrowdPrototype crowdPrototype, AnimationClip animationClip, int eventFrame, UnityAction eventAction, float floatParam = 0, int intParam = 0, string stringParam = null) { if (!crowdManager.isInitialized) crowdManager.InitializeRuntimeDataAndBuffers(); GPUICrowdRuntimeData runtimeData = (GPUICrowdRuntimeData)crowdManager.GetRuntimeData(crowdPrototype); if (runtimeData != null) { GPUIAnimationClipData clipData; if(runtimeData.animationClipDataDict.TryGetValue(animationClip.GetHashCode(), out clipData)) { if (runtimeData.eventDict == null) runtimeData.eventDict = new Dictionary>(); runtimeData.hasEvents = true; GPUIAnimationEvent animationEvent = new GPUIAnimationEvent(crowdPrototype, animationClip); animationEvent.eventFrame = eventFrame; animationEvent.floatParam = floatParam; animationEvent.intParam = intParam; animationEvent.stringParam = stringParam; List animationEvents; if (!runtimeData.eventDict.TryGetValue(clipData.clipIndex, out animationEvents)) { animationEvents = new List(); runtimeData.eventDict.Add(clipData.clipIndex, animationEvents); } animationEvents.Add(animationEvent); animationEvent.AddListener(eventAction); } } } /// /// Add an event to the manager using GPUIAnimationEvent class properties /// /// /// public static void AddAnimationEvent(GPUICrowdManager crowdManager, GPUIAnimationEvent animationEvent) { if (!crowdManager.isInitialized) crowdManager.InitializeRuntimeDataAndBuffers(); GPUICrowdRuntimeData runtimeData = (GPUICrowdRuntimeData)crowdManager.GetRuntimeData(animationEvent.prototype); if (runtimeData != null && animationEvent.animationClip != null) { int clipIndex = animationEvent.prototype.clipList.IndexOf(animationEvent.animationClip); if (clipIndex >= 0) { if (runtimeData.eventDict == null) runtimeData.eventDict = new Dictionary>(); runtimeData.hasEvents = true; List animationEvents; if (!runtimeData.eventDict.TryGetValue(clipIndex, out animationEvents)) { animationEvents = new List(); runtimeData.eventDict.Add(clipIndex, animationEvents); } animationEvents.Add(animationEvent); } } } /// /// Removes all animation events for the given prototype /// /// Crowd Manager that the prototype is defined on /// Crowd Prototype public static void ClearAnimationEvents(GPUICrowdManager crowdManager, GPUICrowdPrototype crowdPrototype) { if (crowdManager.isInitialized) { GPUICrowdRuntimeData runtimeData = (GPUICrowdRuntimeData)crowdManager.GetRuntimeData(crowdPrototype); if (runtimeData != null && runtimeData.eventDict != null) { runtimeData.eventDict.Clear(); runtimeData.hasEvents = false; } } } #endregion Crowd Animator /// /// Use this method to define Crowd Prototypes at runtime for procedurally generated GameObjects /// /// The GPUI Prefab Manager that the prefab prototype will be defined on /// GameObject to use as reference for the prototype /// public static GPUICrowdPrototype DefineGameObjectAsCrowdPrototypeAtRuntime(GPUICrowdManager crowdManager, GameObject prototypeGameObject, GPUICrowdAnimationData animationData) { return crowdManager.DefineGameObjectAsCrowdPrototypeAtRuntime(prototypeGameObject, animationData); } /// /// Can be used to change the material of a prototype at runtime /// /// GPUI Manager /// GPUI Prototype /// New material to set on the renderer /// LOD level /// Renderer index on the LOD level /// Submesh index of the renderer public static void ChangeMaterial(GPUICrowdManager crowdManager, GPUInstancerPrototype prototype, Material material, int lodLevel = 0, int rendererIndex = 0, int subMeshIndex = 0) { GPUICrowdRuntimeData runtimeData = (GPUICrowdRuntimeData)crowdManager.GetRuntimeData(prototype, true); if (runtimeData == null) return; GPUInstancerRenderer gpuiRenderer = runtimeData.instanceLODs[lodLevel].renderers[rendererIndex]; // Generate proxy GO with a Mesh Renderer to get material property blocks GameObject proxyGameObject = new GameObject("ProxyGO"); MeshFilter meshFilter = proxyGameObject.AddComponent(); MeshRenderer proxyRenderer = proxyGameObject.AddComponent(); // Set mesh to proxy GO meshFilter.mesh = gpuiRenderer.mesh; // Set new material to runtime data gpuiRenderer.materials[subMeshIndex] = GPUInstancerConstants.gpuiSettings.shaderBindings.GetInstancedMaterial(material, GPUICrowdConstants.GPUI_EXTENSION_CODE); // Set new material to proxy GO proxyRenderer.materials[subMeshIndex] = material; // Get material property blocks proxyRenderer.GetPropertyBlock(gpuiRenderer.mpb); if (gpuiRenderer.shadowMPB != null) proxyRenderer.GetPropertyBlock(gpuiRenderer.shadowMPB); // Destroy proxy GO GameObject.Destroy(proxyGameObject); // Setup new materials for instancing GPUInstancerUtility.SetAppendBuffers(runtimeData); GPUICrowdUtility.SetAppendBuffers(runtimeData); } } } #endif //GPU_INSTANCER