public VolumeStack CreateStack()
        {
            var stack = new VolumeStack();

            stack.Reload(baseComponentTypes);
            return(stack);
        }
Example #2
0
        // Go through all listed components and lerp overriden values in the global state
        void OverrideData(VolumeStack stack, List <VolumeComponent> components, float interpFactor)
        {
            foreach (var component in components)
            {
                if (!component.active)
                {
                    continue;
                }

                var target = stack.GetComponent(component.GetType());
                int count  = component.parameters.Count;

                for (int i = 0; i < count; i++)
                {
                    var fromParam = target.parameters[i];
                    var toParam   = component.parameters[i];

                    // Keep track of the override state for debugging purpose
                    fromParam.overrideState = toParam.overrideState;

                    if (toParam.overrideState)
                    {
                        fromParam.Interp(fromParam, toParam, interpFactor);
                    }
                }
            }
        }
        // Faster version of OverrideData to force replace values in the global state
        void ReplaceData(VolumeStack stack, List <VolumeComponent> components)
        {
            foreach (var component in components)
            {
                var target = stack.GetComponent(component.GetType());
                int count  = component.parameters.Count;

                for (int i = 0; i < count; i++)
                {
                    target.parameters[i].SetValue(component.parameters[i]);
                }
            }
        }
        // Go through all listed components and lerp overriden values in the global state
        void OverrideData(VolumeStack stack, List <VolumeComponent> components, float interpFactor)
        {
            foreach (var component in components)
            {
                if (!component.active)
                {
                    continue;
                }

                var state = stack.GetComponent(component.GetType());
                component.Override(state, interpFactor);
            }
        }
        public void CheckStack(VolumeStack stack)
        {
            // The editor doesn't reload the domain when exiting play mode but still kills every
            // object created while in play mode, like stacks' component states
            var components = stack.components;

            if (components == null)
            {
                stack.Reload(baseComponentTypes);
                return;
            }

            foreach (var kvp in components)
            {
                if (kvp.Key == null || kvp.Value == null)
                {
                    stack.Reload(baseComponentTypes);
                    return;
                }
            }
        }
        // Update a specific stack - can be used to manage your own stack and store it for later use
        public void Update(VolumeStack stack, Transform trigger, LayerMask layerMask)
        {
            Assert.IsNotNull(stack);

            CheckBaseTypes();
            CheckStack(stack);

            // Start by resetting the global state to default values
            ReplaceData(stack, m_ComponentsDefaultState);

            bool onlyGlobal = trigger == null;
            var  triggerPos = onlyGlobal ? Vector3.zero : trigger.position;

            // Sort the cached volume list(s) for the given layer mask if needed and return it
            var volumes = GrabVolumes(layerMask);

            // Traverse all volumes
            foreach (var volume in volumes)
            {
                // Skip disabled volumes and volumes without any data or weight
                if (!volume.enabled || volume.profileRef == null || volume.weight <= 0f)
                {
                    continue;
                }

                // Global volumes always have influence
                if (volume.isGlobal)
                {
                    OverrideData(stack, volume.profileRef.components, Mathf.Clamp01(volume.weight));
                    continue;
                }

                if (onlyGlobal)
                {
                    continue;
                }

                // If volume isn't global and has no collider, skip it as it's useless
                var colliders = m_TempColliders;
                volume.GetComponents(colliders);
                if (colliders.Count == 0)
                {
                    continue;
                }

                // Find closest distance to volume, 0 means it's inside it
                float closestDistanceSqr = float.PositiveInfinity;

                foreach (var collider in colliders)
                {
                    if (!collider.enabled)
                    {
                        continue;
                    }

                    var closestPoint = collider.ClosestPoint(triggerPos);
                    var d            = (closestPoint - triggerPos).sqrMagnitude;

                    if (d < closestDistanceSqr)
                    {
                        closestDistanceSqr = d;
                    }
                }

                colliders.Clear();
                float blendDistSqr = volume.blendDistance * volume.blendDistance;

                // Volume has no influence, ignore it
                // Note: Volume doesn't do anything when `closestDistanceSqr = blendDistSqr` but we
                //       can't use a >= comparison as blendDistSqr could be set to 0 in which case
                //       volume would have total influence
                if (closestDistanceSqr > blendDistSqr)
                {
                    continue;
                }

                // Volume has influence
                float interpFactor = 1f;

                if (blendDistSqr > 0f)
                {
                    interpFactor = 1f - (closestDistanceSqr / blendDistSqr);
                }

                // No need to clamp01 the interpolation factor as it'll always be in [0;1[ range
                OverrideData(stack, volume.profileRef.components, interpFactor * Mathf.Clamp01(volume.weight));
            }
        }