/// <summary> /// Scrub to specified time in particle recording. This will linearly interpolate between the closest recorded frames of the passed in time (normalized between 0f - 1f). /// </summary> /// <param name="normalizedTime">The normalized time (0f to 1f).</param> public void Scrub(float normalizedTime) { if (!HasRecordedFrames()) { return; } if (_isRecording) { StopRecording(); } if (!_inPlayback) { StartPlayback(); } if (multithreading) { PlaygroundC.RunAsync(() => { lock (locker) { ScrubInternal(normalizedTime); } }); } else { ScrubInternal(normalizedTime); } }
/// <summary> /// Loads frames from the Recorder Data asynchronously. /// </summary> public void LoadAsync() { if (recorderData == null) { Debug.Log("No Playground Recorder Data to load from!", gameObject); return; } PlaygroundC.RunAsync(() => { recordedFrames = recorderData.CloneAsRecordedFrames(); _hasEditedRecordData = true; }); }
public void SerializeAsync(List <RecordedFrame> recordedFrames) { version = PlaygroundC.version; PlaygroundC.RunAsync(() => { serializedFrames = null; serializedFrames = new SerializedFrame[recordedFrames.Count]; for (int i = 0; i < serializedFrames.Length; i++) { serializedFrames[i] = recordedFrames[i].CloneAsSerializedFrame(); } }); #if UNITY_EDITOR UnityEditor.EditorUtility.SetDirty(this); #endif }
/// <summary> /// Sets the particle system's live particles at normalized time of the recorded frames. If multithreading is enabled this operation will run asynchronously. /// </summary> public void SetParticleSystemAsRecording(float normalizedTime) { if (playgroundSystem == null || _playbackParticles == null) { return; } if (multithreading) { PlaygroundC.RunAsync(() => { lock (locker) { SetParticleSystemAsRecordingInternal(normalizedTime); } }); } else { SetParticleSystemAsRecordingInternal(normalizedTime); } }
void Update() { // Clamp values maxPoints = Mathf.Clamp(maxPoints, 2, 32767); // Set asynchronous available values if (billboardTransform != null) { _billboardTransformPosition = billboardTransform.position; } // Early out if no particles exist yet if (playgroundSystem == null || !playgroundSystem.IsReady() || playgroundSystem.IsSettingParticleCount() || playgroundSystem.IsSettingLifetime() || playgroundSystem.particleCache == null || playgroundSystem.particleCache.Length == 0) { return; } // Reset trails if a crucial state is changed if (_currentParticleCount != playgroundSystem.particleCount || _currentParticleMinLifetime != playgroundSystem.lifetimeMin || _currentParticleMaxLifetime != playgroundSystem.lifetime || _localSpace != (playgroundSystem.shurikenParticleSystem.simulationSpace == ParticleSystemSimulationSpace.Local)) { ResetTrails(); } // Set calculation matrix if this is local space if (_localSpace) { _localMatrix.SetTRS(playgroundSystem.particleSystemTransform.position, playgroundSystem.particleSystemTransform.rotation, playgroundSystem.particleSystemTransform.lossyScale); } // Check material if (material != _materialCache) { SetMaterial(material); } // Remove any trails that has ended if (_isDoneThread) { for (int i = 0; i < _trails.Count; i++) { if (_trails[i].trailPoints != null && _trails[i].trailPoints.Count > 1 && _trails[i].trailPoints[_trails[i].trailPoints.Count - 1] != null && _trails[i].CanRemoveTrail()) { RemoveTrail(i); i--; if (i < 0) { i = 0; } continue; } } } // Consume the particle birth queue while (_birthQueue.Count > 0) { AddTrail(_birthQueue.Dequeue()); } // Update all trail meshes and their render settings for (int i = 0; i < _trails.Count; i++) { ParticlePlaygroundTrail trail = _trails[i]; // Set shadow casting/receiving trail.trailRenderer.receiveShadows = receiveShadows; #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 trail.trailRenderer.castShadows = castShadows; #else trail.trailRenderer.shadowCastingMode = shadowCastingMode; #endif if (_isDoneThread) { trail.UpdateMesh(); } } // Finally calculate all trails if (multithreading) { if (_isDoneThread) { _calculationStartTime = Application.isPlaying? Time.time : Time.realtimeSinceStartup; _isDoneThread = false; PlaygroundC.RunAsync(() => { lock (_locker) { if (_isDoneThread) { return; } CalculateTrail(); _isDoneThread = true; } }); } } else { _calculationStartTime = Application.isPlaying? Time.time : Time.realtimeSinceStartup; CalculateTrail(); } }
void Update() { // Clamp values maxPoints = Mathf.Clamp(maxPoints, 2, 32767); // Set asynchronous available values if (billboardTransform != null) { _billboardTransformPosition = billboardTransform.position; } // Early out if no particles exist yet if (playgroundSystem == null || !playgroundSystem.IsReady() || playgroundSystem.IsSettingParticleCount() || playgroundSystem.IsSettingLifetime() || playgroundSystem.particleCache == null || playgroundSystem.particleCache.Length == 0) { return; } // Reset trails if a crucial state is changed if (_currentParticleCount != playgroundSystem.particleCount || _currentLoopValue != playgroundSystem.loop || _currentParticleMinLifetime != playgroundSystem.lifetimeMin || _currentParticleMaxLifetime != playgroundSystem.lifetime || _localSpace != (playgroundSystem.shurikenParticleSystem.simulationSpace == ParticleSystemSimulationSpace.Local)) { ResetTrails(); } // Set calculation matrix if this is local space if (_localSpace) { _localMatrix.SetTRS(playgroundSystem.particleSystemTransform.position, playgroundSystem.particleSystemTransform.rotation, playgroundSystem.particleSystemTransform.lossyScale); } // Check material if (material != _materialCache) { SetMaterial(material); } // Consume the particle birth queue while (_isDoneThread && _birthQueue.Count > 0) { // Reuse or create new trails bool canReuseTrail = trails.Count > 0 && _trailReuseQueue.Count > 0; int reuseQueuePeekValue = canReuseTrail? _trailReuseQueue.Peek() : 0; if (canReuseTrail && (reuseQueuePeekValue < 0 || reuseQueuePeekValue > trails.Count - 1 || !trails[reuseQueuePeekValue].IsQueuedForReuse())) { _trailReuseQueue.Dequeue(); canReuseTrail = false; } if (canReuseTrail) { ReuseTrail(_trailReuseQueue.Dequeue(), _birthQueue.Dequeue()); } else { CreateTrail(_birthQueue.Dequeue()); } } // Remove any trails that has ended if (_isDoneThread) { for (int i = 0; i < trails.Count; i++) { if (trails[i].trailPoints != null && trails[i].trailPoints.Count > 1 && trails[i].trailPoints[trails[i].trailPoints.Count - 1] != null && trails[i].CanRemoveTrail()) { if (!trails[i].IsQueuedForReuse()) { _trailReuseQueue.Enqueue(i); trails[i].QueueForReuse(); } } } } // Update all trail meshes and their render settings for (int i = 0; i < trails.Count; i++) { ParticlePlaygroundTrail trail = trails[i]; // Set shadow casting/receiving trail.trailRenderer.receiveShadows = receiveShadows; #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 trail.trailRenderer.castShadows = castShadows; #else trail.trailRenderer.shadowCastingMode = shadowCastingMode; #endif if (_isDoneThread && !trail.IsQueuedForReuse()) { trail.UpdateMesh(); } } // Check if there's any event listeners _hasTrailPointEventListener = trailPointEvent != null; // Check that the calculation delegate is assigned if (_trailsCalculationAction == null) { _trailsCalculationAction = CalculationDelegate; } _calculationStartTime = Application.isPlaying? Time.time : Time.realtimeSinceStartup; // Finally calculate all trails if (multithreading) { if (_isDoneThread) { _isDoneThread = false; PlaygroundC.RunAsync(_trailsCalculationAction); } } else { _isDoneThread = false; _trailsCalculationAction(); } }