Exemplo n.º 1
0
        /// <summary>
        /// Prepares all values for calculation which is not thread-safe.
        /// </summary>
        /// <returns><c>true</c>, if threaded calculations was prepared, <c>false</c> otherwise.</returns>
        public bool PrepareThreadedCalculations()
        {
            // Component disabled?
            if (!enabled) return false;

            // Auto-Pause (start/stop calculation when particle system is out of view.
            if (pauseCalculationWhenInvisible) {
                bool skipFrustumCheck = false;
                #if UNITY_EDITOR
                if (!UnityEditor.EditorApplication.isPlaying) {
                    calculate = true;
                    skipFrustumCheck = true;
                }
                #endif
                if (!skipFrustumCheck && Camera.main!=null && PlaygroundC.frustumPlanes!=null) {
                    bool shouldRender = GeometryUtility.TestPlanesAABB(PlaygroundC.frustumPlanes, new Bounds(calculationTriggerTransform==null?particleSystemTransform.position+calculationTriggerOffset:calculationTriggerTransform.position+calculationTriggerOffset, calculationTriggerSize));
                    if (!shouldRender && calculate && !particleSystemRenderer.isVisible) {
                        calculate = false;
                        #if UNITY_EDITOR
                        if (!didHierarchyRepaint)
                            UnityEditor.EditorApplication.RepaintHierarchyWindow();
                        didHierarchyRepaint = true;
                        #endif
                        return false;
                    } else if (shouldRender && !calculate) {
                        calculate = true;
                        #if UNITY_EDITOR
                        if (!didHierarchyRepaint)
                            UnityEditor.EditorApplication.RepaintHierarchyWindow();
                        didHierarchyRepaint = true;
                        #endif
                        if (prewarm) {Start(); return false;} else SetParticleTimeNow (thisInstance);
                    }
                }
            } else if (!calculate) {
                calculate = true;
                #if UNITY_EDITOR
                if (!didHierarchyRepaint)
                    UnityEditor.EditorApplication.RepaintHierarchyWindow();
                didHierarchyRepaint = true;
                #endif
                if (prewarm) {Start(); return false;} else SetParticleTimeNow (thisInstance);
            }
            if (!calculate) return false;

            // Has the calculation been paused previously?
            if (cameFromNonCalculatedFrame && hasActiveParticles) {
                StartCoroutine(Boot());
                cameFromNonCalculatedFrame = false;
                return false;
            }

            // Apply locked position
            if (applyLockPosition) {
                if (lockPositionIsLocal)
                    particleSystemTransform.localPosition = lockPosition;
                else
                    particleSystemTransform.position = lockPosition;
            }

            // Apply locked rotation
            if (applyLockRotation) {
                if (lockRotationIsLocal)
                    particleSystemTransform.localRotation = Quaternion.Euler(lockRotation);
                else
                    particleSystemTransform.rotation = Quaternion.Euler(lockRotation);
            }

            // Apply locked scale
            if (applyLockScale)
                particleSystemTransform.localScale = lockScale;

            // Update active particle check
            hasActiveParticles = !threadHadNoActiveParticles || emit&&loop&&particleCount>0;
            if (!hasActiveParticles) {
                if (disableOnDone)
                    queueEmissionHalt = true;
            }

            realSimulationTime = particleTimescale*Time.timeScale;
            cancelDeltaPositioningOnSync = false;

            // Prepare Source positions
            if (PlaygroundC.reference.IsDoneThread() && isDoneThread) {
                stRot = Quaternion.identity;
                stDir = new Vector3();
            }
            localSpace = (shurikenParticleSystem.simulationSpace == ParticleSystemSimulationSpace.Local);
            overflow = (overflowOffset!=Vector3.zero);
            skinnedWorldObjectReady = false;
            renderModeStretch = particleSystemRenderer2.renderMode==ParticleSystemRenderMode.Stretch;
            particleSystemRotation = particleSystemTransform.rotation;
            particleSystemInverseRotation = particleSystemRotation;
            particleSystemInverseRotation.x = -particleSystemInverseRotation.x;
            particleSystemInverseRotation.y = -particleSystemInverseRotation.y;
            particleSystemInverseRotation.z = -particleSystemInverseRotation.z;
            particleSystemInverseRotation.w = -particleSystemInverseRotation.w;

            // Prepare turbulence
            if (!onlySourcePositioning && !onlyLifetimePositioning && turbulenceType!=TURBULENCETYPE.None) {
                if (turbulenceType==TURBULENCETYPE.Simplex && turbulenceSimplex==null)
                    turbulenceSimplex = new SimplexNoise();
            }

            if (emit) {
                switch (source) {
                case SOURCEC.Script:

                    break;
                case SOURCEC.State:
                    if (states.Count>0) {
                        if (activeState>states.Count-1) activeState = states.Count-1;
                        if (activeState<0) activeState = 0;
                        if (states[activeState].stateTransform!=null) {
                            if (isDoneThread) {
                                if (!states[activeState].initialized)
                                    states[activeState].Initialize();

                                stRot = states[activeState].stateTransform.rotation;

                                states[activeState].UpdateMatrix(localSpace);
                            }
                            if (localSpace && (states[activeState].stateTransform.parent==particleSystemTransform || states[activeState].stateTransform==particleSystemTransform) && isDoneThread) {
                                cancelDeltaPositioningOnSync = true;
                                stRot = Quaternion.Euler (Vector3.zero);
                            }
                        }
                    } else return false;
                    break;
                case SOURCEC.Transform:

                    // Handle the availability of Playground Transforms (list of transform wrapper classes).
                    // The single sourceTransform is an old method which needs to be copied over if available.
                    if (sourceTransforms==null) {
                        sourceTransforms = new List<PlaygroundTransformC>();
                    }
                    if (sourceTransforms.Count==0) {
                        sourceTransforms.Add(new PlaygroundTransformC());
                        sourceTransforms[0].transform = sourceTransform!=null?sourceTransform:particleSystemTransform;
                    }

                    if (isDoneThread) {
                        for (int i = 0; i<sourceTransforms.Count; i++) {
                            if (!sourceTransforms[i].Update()) return false;
                            if (IsLocalSpace()) {
                                psTransformNum = -1;
                                sourceTransforms[i].SetLocalPosition(particleSystemTransform);
                                sourceTransforms[i].SetPostitionAsLocal();
                                if (sourceTransforms[i].IsSameAs (particleSystemTransform)) {
                                    sourceTransforms[i].SetZeroRotation();
                                    psTransformNum = i;
                                }
                            }
                        }
                    }

                    if (isDoneThread) {
                        stRot = sourceTransform.rotation;
                    }
                    if (localSpace && sourceTransform==particleSystemTransform && isDoneThread) {
                        cancelDeltaPositioningOnSync = true;
                        stRot = Quaternion.Euler (Vector3.zero);
                    }
                    break;
                case SOURCEC.WorldObject:

                    // Handle vertex data in active World Object
                    if (worldObject.gameObject!=null) {
                        if (worldObject.gameObject.GetInstanceID()!=worldObject.cachedId || !worldObject.initialized)
                            worldObject = NewWorldObject(worldObject.gameObject.transform);
                        if (worldObject.mesh!=null) {
                            if (isDoneThread) {
                                stRot = worldObject.transform.transform.rotation;
                            }
                            if (localSpace && isDoneThread) {
                                cancelDeltaPositioningOnSync = true;
                                stRot = Quaternion.Euler (Vector3.zero);
                            }

                            worldObject.UpdateMatrix(localSpace);

                            worldObject.updateNormals = worldObjectUpdateNormals;
                            if (worldObjectUpdateVertices)
                                worldObject.Update();
                        } else return false;
                    } else return false;
                    break;
                case SOURCEC.SkinnedWorldObject:

                    // Handle vertex data in active Skinned World Object
                    if (skinnedWorldObject.gameObject!=null) {
                        if (skinnedWorldObject.gameObject.GetInstanceID()!=skinnedWorldObject.cachedId) {
                            skinnedWorldObject = NewSkinnedWorldObject(skinnedWorldObject.gameObject.transform, skinnedWorldObject.downResolution);
                        }
                    }
                    skinnedWorldObjectReady = skinnedWorldObject.gameObject!=null && skinnedWorldObject.mesh!=null;
                    if (PlaygroundC.reference.skinnedMeshThreadMethod==ThreadMethodComponent.OneForAll && PlaygroundC.reference.IsFirstUnsafeAutomaticFrames() && !PlaygroundC.reference.IsDoneThreadSkinnedMeshes())
                        return false;
                    if (skinnedWorldObjectReady) {
                        if (isDoneThread) {
                            stRot = skinnedWorldObject.transform.rotation;
                            stDir = skinnedWorldObject.transform.TransformDirection (overflowOffset);
                        }
                        skinnedWorldObject.updateNormals = worldObjectUpdateNormals;

                        if (Time.frameCount%PlaygroundC.skinnedUpdateRate==0) {
                            if (worldObjectUpdateVertices)
                                skinnedWorldObject.MeshUpdate();
                            skinnedWorldObject.BoneUpdate();

                            // Forced update for skinned mesh vertices on main-thread
                            if (forceSkinnedMeshUpdateOnMainThread) {
                                skinnedWorldObject.Update();
                            }
                        }
                    } else return false;
                    break;
                case SOURCEC.Paint:
                    if (paint.initialized) {
                        if (isDoneThread) {
                            stRot = particleSystemTransform.rotation;
                        }
                        if (paint.positionLength>0) {
                            for (int p = 0; p<particleCache.Length; p++) {
                                paint.Update(p);
                            }
                        } else return false;
                    } else {
                        paint.Initialize ();
                        return false;
                    }
                    break;
                case SOURCEC.Projection:
                    if (projection.projectionTexture!=null && projection.projectionTransform!=null) {
                        if (!projection.initialized)
                            projection.Initialize();
                        stRot = projection.projectionTransform.rotation;

                        if (localSpace)
                            shurikenParticleSystem.simulationSpace = ParticleSystemSimulationSpace.World;

                        if (projection.liveUpdate || !projection.hasRefreshed) {
                            projection.UpdateSource();
                            projection.Update();
                            stDir = projection.projectionTransform.TransformDirection (overflowOffset);

                            projection.hasRefreshed = true;
                        }

                    } else return false;
                    break;
                case SOURCEC.Spline:
                    if (splines.Count>0) {
                        for (int i = 0; i<splines.Count; i++)
                            if (splines[i]==null || !splines[i].enabled || !splines[i].IsReady()) return false;
                        if (isDoneThread) {
                            stRot = particleSystemTransform.rotation;
                            if (localSpace) {
                                cancelDeltaPositioningOnSync = true;
                                stRot = Quaternion.Euler (Vector3.zero);
                            }
                        }
                    } else return false;
                    break;
                }
            }

            // Collision detection (runs on main-thread)
            if (collision)
                Collisions(thisInstance);

            // Prepare Particle colors
            stateReadyForTextureColor = (source==SOURCEC.State && states[activeState].stateTexture!=null && states[activeState].colorLength>0);

            hasEventManipulatorLocal = false;
            hasEventManipulatorGlobal = false;
            hasGlobalAffectingManipulators = false;
            manipulatorEventCount = 0;
            thisLayer = particleSystemGameObject.layer;

            // Prepare Local Manipulators
            for (int m = 0; m<manipulators.Count; m++) {
                manipulators[m].Update();
                manipulators[m].transform.SetLocalPosition(particleSystemTransform);
                manipulators[m].SetLocalTargetsPosition(particleSystemTransform);
                if (manipulators[m].trackParticles) {
                    hasEventManipulatorLocal = true;
                    manipulatorEventCount++;
                }
            }
            // Prepare Global Manipulators from this local space, bundle the thread call in case any Global Manipulator is tracking particles
            if (PlaygroundC.reference.HasEnabledGlobalManipulators()) {
                for (int m = 0; m<PlaygroundC.reference.manipulators.Count; m++) {
                    if ((PlaygroundC.reference.manipulators[m].affects.value & 1<<GetLayer())!=0) {
                        hasGlobalAffectingManipulators = true;
                        PlaygroundC.reference.manipulators[m].transform.SetLocalPosition(particleSystemTransform);
                        if (PlaygroundC.reference.manipulators[m].trackParticles && PlaygroundC.reference.threadMethod!=ThreadMethod.NoThreads) {
                            threadMethod = ThreadMethodLocal.OneForAll;
                            hasEventManipulatorGlobal = true;
                            manipulatorEventCount++;
                        }
                    }
                }
            }

            hasSeveralManipulatorEvents = (manipulatorEventCount>1);

            // Prepare events
            hasEvent = events.Count>0;
            hasTimerEvent = false;
            if (hasEvent) {
                for (int i = 0; i<events.Count; i++) {
                    events[i].Initialize();
                    if (events[i].initializedTarget && events[i].broadcastType!=EVENTBROADCASTC.EventListeners)
                        if (!events[i].target.eventControlledBy.Contains (thisInstance))
                            events[i].target.eventControlledBy.Add (thisInstance);

                    if (events[i].eventType==EVENTTYPEC.Time && ((events[i].broadcastType!=EVENTBROADCASTC.EventListeners && events[i].initializedTarget) || events[i].broadcastType==EVENTBROADCASTC.EventListeners && events[i].initializedEvent)) {
                        hasTimerEvent = events[i].UpdateTime();
                    }
                }
            }

            // All good! Next step is to send all particles to calculation.
            return true;
        }
Exemplo n.º 2
0
        public IEnumerator Boot()
        {
            if (particleSystemGameObject.activeInHierarchy && particleSystemGameObject.activeSelf && !isLoading && enabled) {

                while (PlaygroundC.reference==null) yield return null;

                // Check if particle system must be combined on threaded calls to cope with particle tracking
                if (PlaygroundC.reference.HasEnabledGlobalManipulators()) {
                    for (int m = 0; m<PlaygroundC.reference.manipulators.Count; m++) {
                        if (PlaygroundC.reference.manipulators[m].trackParticles && (PlaygroundC.reference.manipulators[m].affects.value & 1<<GetLayer())!=0 && PlaygroundC.reference.threadMethod!=ThreadMethod.NoThreads)
                            threadMethod = ThreadMethodLocal.OneForAll;
                    }
                }

                // Update time
                localTime = PlaygroundC.globalTime;
                lastTimeUpdated = localTime;

                // Update id if needed
                for (int i = 0; i<PlaygroundC.reference.particleSystems.Count; i++) {
                    if (PlaygroundC.reference.particleSystems[i].particleSystemId==particleSystemId && PlaygroundC.reference.particleSystems[i]!=this) {
                        particleSystemId = PlaygroundC.reference.particleSystems.Count-1;
                        break;
                    }
                }

                // Refresh
                if (!isYieldRefreshing)
                    StartCoroutine(YieldedRefresh());
            }
        }