/// <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();
            }
        }
Example #6
0
        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();
            }
        }