public override void OnEvent(float power)
    {
        if (persistentEmitters == null)
        {
            return;
        }

        if ((overRideInputs || power > 0) && activated)
        {
            UpdateEmitters(power);
            for (int i = 0; i < persistentEmitters.Count; i++)
            {
                PersistentKSPShurikenEmitter pkse = persistentEmitters[i];
                pkse.emitting = true;
                if (pkse.pe != null)
                {
                    ParticleSystem.EmissionModule em = pkse.pe.emission;
                    em.enabled = false;
                }
            }
        }
        else
        {
            for (int j = 0; j < persistentEmitters.Count; j++)
            {
                PersistentKSPShurikenEmitter pkse = persistentEmitters[j];
                pkse.emitting = false;
                if (pkse.pe != null)
                {
                    ParticleSystem.EmissionModule em = pkse.pe.emission;
                    em.enabled = false;
                }
            }
        }
    }
예제 #2
0
    private void LateUpdate()
    {
        for (int i = 0; i < persistentEmittersShuriken.Count; i++)
        {
            PersistentKSPShurikenEmitter em = persistentEmittersShuriken[i];
            if (em.endTime > 0 && em.endTime < Time.fixedTime)
            {
                em.EmissionStop();
            }

            // If the gameObject is null clean up the emitter
            if (em.go == null || em.pe == null)
            {
                Remove(em);
                Destroy(em.go);
                i--;
            }
            // if not and the transform parent is null ( Emitter detached from part so the particle are not removed instantly )
            // then the emitter won't be updated by the effect Update Call. So update it here
            else if (em.emitOnUpdate && em.go.transform.parent == null)
            {
                em.EmitterOnUpdate(Vector3.zero);

                if (em.pe.particleCount == 0)
                {
                    Remove(em);
                    Destroy(em.go);
                    i--;
                }
            }
        }
    }
예제 #3
0
    public static void Remove(PersistentKSPShurikenEmitter pkpe)
    {
        FloatingOrigin.UnregisterParticleSystem(pkpe.pe);
        persistentEmittersShuriken.Remove(pkpe);

        Log.dbg("Removed 1 PersistentKSPParticleEmitter. Count = {0}", persistentEmittersShuriken.Count);
    }
    public static void Remove(PersistentKSPShurikenEmitter pkpe)
    {
        FloatingOrigin.UnregisterParticleSystem(pkpe.pe);
        persistentEmittersShuriken.Remove(pkpe);

        //print("[SmokeScreen PersistentEmitterManager]: Removed 1 PersistentKSPParticleEmitter. Count = " + persistentEmitters.Count);
    }
    public static void Remove(PersistentKSPShurikenEmitter pkpe)
    {
        FloatingOrigin.UnregisterParticleSystem(pkpe.pe);
        persistentEmittersShuriken.Remove(pkpe);

        //print("[SmokeScreen PersistentEmitterManager]: Removed 1 PersistentKSPParticleEmitter. Count = " + persistentEmitters.Count);
    }
    // First, I tried to emit particles on regular Update, but stuff was weird, and the plume still appeared out of sync with frame draws
    // According to https://docs.unity3d.com/Manual/ExecutionOrder.html
    // LateUpdate is the last thing that happens before frame draw. That makes it as synced to frame draws, as possible
    // LateUpdate is called after physics calculations too, so the newly emitted plume particles are right where they should be.
    public void LateUpdate()
    {
        if (persistentEmitters == null || hostPart == null || hostPart.Rigidbody == null)
        {
            return;
        }

        // I think it's important to call this even though it doesn't count active particles
        // because it calculates how many particles should be removed on next emit pass.
        SmokeScreenConfig.UpdateParticlesCount();

        for (int i = 0; i < persistentEmitters.Count; i++)
        {
            PersistentKSPShurikenEmitter emitter = persistentEmitters[i];
            if (EmitOnUpdate)
            {
                emitter.EmitterOnUpdate(hostPart.Rigidbody.velocity + Krakensbane.GetFrameVelocity());
            }
        }
    }
    public void FixedUpdate()
    {
        //Print("FixedUpdate");
        if (persistentEmitters == null || hostPart == null || hostPart.Rigidbody == null)
        {
            return;
        }

        if (singleTimerEnd > 0)
        {
            if (Time.fixedTime <= singleTimerEnd)
            {
                OnEvent(1f);
            }
            else
            {
                OnEvent(0f);
                singleTimerEnd = 0;
            }
        }
        SmokeScreenConfig.UpdateParticlesCount();

        //RaycastHit vHit = new RaycastHit();
        //Ray vRay = Camera.main.ScreenPointToRay(Input.mousePosition);
        //if(Physics.Raycast(vRay, out vHit))
        //{
        //    RaycastHit vHit2 = new RaycastHit();
        //    if (Physics.Raycast(vHit.point + vHit.normal * 10, -vHit.normal, out vHit2))
        //        Debug.Log(vHit2.collider.name);
        //}

        for (int i = 0; i < persistentEmitters.Count; i++)
        {
            PersistentKSPShurikenEmitter emitter = persistentEmitters[i];
            // This is FixedUpdate, so don't emit here if particles should emit in LateUpdate
            if (!EmitOnUpdate)
            {
                emitter.EmitterOnUpdate(hostPart.Rigidbody.velocity + Krakensbane.GetFrameVelocity());
            }
        }
    }
    public override void OnEvent(float power, int transformIdx)
    {
        if (persistentEmitters == null || transformIdx >= persistentEmitters.Count)
        {
            return;
        }

        if (transformIdx == -1)
        {
            OnEvent(power);
            return;
        }

        PersistentKSPShurikenEmitter pkse = persistentEmitters[transformIdx];

        if ((overRideInputs || power > 0) && activated)
        {
            UpdateEmitters(power);

            pkse.emitting = true;
            if (pkse.pe != null)
            {
                ParticleSystem.EmissionModule em = pkse.pe.emission;
                em.enabled = false;
            }
        }
        else
        {
            pkse.emitting = false;
            if (pkse.pe != null)
            {
                ParticleSystem.EmissionModule em = pkse.pe.emission;
                em.enabled = false;
            }
        }
    }
    public override void OnInitialize()
    {
        //Print("OnInitialize");

        // Ship spawned somehow don't call OnLoad...
        if (node_backup != string.Empty)
        {
            Restore();
        }

        List <Transform> transforms = new List <Transform>(hostPart.FindModelTransforms(transformName));

        if (transforms.Count == 0)
        {
            if (transformName == "partTransform")
            {
                transforms.Add(hostPart.partTransform);
            }
            else
            {
                Log.info("Cannot find transform {0}", transformName);
                return;
            }
        }
        GameObject model = GameDatabase.Instance.GetModel(modelName);

        if (model == null)
        {
            Log.info("Cannot find model {0}", modelName);
            return;
        }
        model.SetActive(true);
        KSPParticleEmitter templateKspParticleEmitter = model.GetComponentInChildren <KSPParticleEmitter>();

        if (templateKspParticleEmitter == null)
        {
            Log.info("Cannot find particle emitter on {0}", modelName);
            Destroy(model);
            return;
        }

        if (persistentEmitters == null)
        {
            persistentEmitters = new List <PersistentKSPShurikenEmitter>();
        }

        if (hostPart.Modules.Contains("ProceduralSRB"))
        {
            PartModule pm = hostPart.Modules["ProceduralSRB"];

            specialScale = pm.Fields.GetValue <float>("bellScale");
            Log.info("Found ProceduralSRB. Rescaling by {0:0.000} final scale {1}:0.000}", specialScale, (fixedScale * specialScale));
        }

        if (hostPart.Modules.Contains("TweakScale"))
        {
            PartModule pm           = hostPart.Modules["TweakScale"];
            float      tweakScale   = pm.Fields.GetValue <float>("currentScale");
            float      defaultScale = pm.Fields.GetValue <float>("defaultScale");
            specialScale = tweakScale / (defaultScale <= 0 ? 1 : defaultScale);
            Log.info("Found TweakScale. Rescaling by {0:0.000} final scale {1:0.000}", specialScale, (fixedScale * specialScale));
        }

        for (int i = 0; i < transforms.Count; i++)
        {
            GameObject         emitterGameObject       = i == 0 ? model : Instantiate(model);
            KSPParticleEmitter childKSPParticleEmitter = emitterGameObject.GetComponentInChildren <KSPParticleEmitter>();

            if (childKSPParticleEmitter != null)
            {
                ParticleSystem         particleSystem         = childKSPParticleEmitter.gameObject.GetComponent <ParticleSystem>();
                ParticleSystemRenderer particleSystemRenderer = childKSPParticleEmitter.gameObject.GetComponent <ParticleSystemRenderer>();

                PersistentKSPShurikenEmitter pkpe = new PersistentKSPShurikenEmitter(
                    emitterGameObject,
                    particleSystem,
                    particleSystemRenderer,
                    childKSPParticleEmitter);


                // We do the emission and animation ourselves so we disable the KSP code
                childKSPParticleEmitter.emit = false;
                childKSPParticleEmitter.SetupProperties();
                childKSPParticleEmitter.enabled = false;

                ParticleSystem.MainModule main = particleSystem.main;
                main.maxParticles = particleCountLimit;

                //particleSystemRenderer.alignment = ParticleSystemRenderSpace.View;

                pkpe.doesAnimateColor = childKSPParticleEmitter.doesAnimateColor;

                if (childKSPParticleEmitter.doesAnimateColor)
                {
                    ParticleSystem.ColorOverLifetimeModule col = particleSystem.colorOverLifetime;

                    // This one is annoying. The old particle system animate the color over the whole % life of the particle (0 - 1)
                    // The new one animate it over time. So converted system may not reach the full value
                    // The color is manually set in the update of PersistentKSPShurikenEmitter
                    col.enabled = false;

                    Color[] colors = childKSPParticleEmitter.colorAnimation;

                    pkpe.colors = new Color[colors.Length];
                    Array.Copy(colors, pkpe.colors, colors.Length);
                }

                //try
                //{
                //    particleSystemRenderer.renderMode =
                //        (ParticleSystemRenderMode)Enum.Parse(typeof (ParticleSystemRenderMode), renderMode);
                //}
                //catch (ArgumentException)
                //{
                //    Print("ModelMultiParticleFXExt: " + renderMode + " is not a valid ParticleSystemRenderMode");
                //}

                persistentEmitters.Add(pkpe);

                DisableCollider(pkpe.go);

                emitterGameObject.transform.SetParent(transforms[i], false);

                emitterGameObject.transform.localPosition = localPosition;
                emitterGameObject.transform.localRotation = Quaternion.Euler(localRotation);
                emitterGameObject.SetLayerRecursive(layerId);
            }
        }

        list.Add(this);

        // 1.0 don't seems to properly do this for engines.
        //OnEvent(0f);
    }
    public void UpdateEmitters(float power)
    {
        UpdateInputs(power);

        for (int i = 0; i < persistentEmitters.Count; i++)
        {
            PersistentKSPShurikenEmitter pkpe = persistentEmitters[i];

            if (pkpe.go == null)
            {
                continue;
            }

            float finalScale = fixedScale * specialScale;

            float finalSizeClamp = sizeClamp + sizeClampCurve.Value(inputs);

            float sizePower = size.Value(inputs) * finalScale;
            pkpe.minSize = Mathf.Min(pkpe.minSizeBase * sizePower, finalSizeClamp);
            pkpe.maxSize = Mathf.Min(pkpe.maxSizeBase * sizePower, finalSizeClamp);

            float emissionPower = emission.Value(inputs) * emissionMult;
            pkpe.minEmission = Mathf.FloorToInt(pkpe.minEmissionBase * emissionPower);
            pkpe.maxEmission = Mathf.FloorToInt(pkpe.maxEmissionBase * emissionPower);

            float energyPower = energy.Value(inputs);
            pkpe.minEnergy = pkpe.minEnergyBase * energyPower;
            pkpe.maxEnergy = pkpe.maxEnergyBase * energyPower;

            float velocityPower = speed.Value(inputs) * finalScale;
            pkpe.localVelocity = pkpe.localVelocityBase * velocityPower;
            pkpe.worldVelocity = pkpe.worldVelocityBase * velocityPower;

            float forcePower = force.Value(inputs);
            pkpe.force = pkpe.forceBase * forcePower;

            ParticleSystem.ForceOverLifetimeModule fol = pkpe.pe.forceOverLifetime;
            fol.enabled = pkpe.force.sqrMagnitude > 0 || pkpe.rndForce.sqrMagnitude > 0;
            fol.x       = new ParticleSystem.MinMaxCurve(pkpe.forceBase.x, pkpe.force.x + pkpe.rndForce.x);
            fol.y       = new ParticleSystem.MinMaxCurve(pkpe.forceBase.y, pkpe.force.y + pkpe.rndForce.y);
            fol.z       = new ParticleSystem.MinMaxCurve(pkpe.forceBase.z, pkpe.force.z + pkpe.rndForce.z);

            pkpe.sizeGrow = grow.Value(inputs);

            float currentScale = scale.Value(inputs) * finalScale;
            pkpe.shape1D = pkpe.scale1DBase * currentScale;
            pkpe.shape2D = pkpe.scale2DBase * currentScale;
            pkpe.shape3D = pkpe.scale3DBase * currentScale;

            pkpe.sizeClamp = finalSizeClamp;
            pkpe.randomInitalVelocityOffsetMaxRadius = randomInitalVelocityOffsetMaxRadius + initalVelocityOffsetMaxRadius.Value(inputs);

            pkpe.randConeEmit = randConeEmit.Value(inputs);
            pkpe.xyForce      = xyForce.Value(inputs);
            pkpe.zForce       = zForce.Value(inputs);

            pkpe.vRandPosOffset = vRandPosOffset.Value(inputs);
            pkpe.vPosOffset     = vPosOffset.Value(inputs);

            pkpe.physical        = physical && !SmokeScreenConfig.Instance.globalPhysicalDisable;
            pkpe.initialDensity  = initialDensity;
            pkpe.dragCoefficient = dragCoefficient;

            pkpe.collide      = collide && !SmokeScreenConfig.Instance.globalCollideDisable;
            pkpe.stickiness   = stickiness;
            pkpe.collideRatio = collideRatio;

            pkpe.logarithmicGrow      = logGrow.Value(inputs);
            pkpe.logarithmicGrowScale = logGrowScale.Value(inputs);

            pkpe.decluster = decluster;

            pkpe.emitOnUpdate = EmitOnUpdate;

            pkpe.linearGrow = linGrow.Value(inputs);

            if (alpha.Value(inputs) != 1 || linAlphaDecay.Value(inputs) != 0 || logAlphaDecay.Value(inputs) != 0)
            {
                //Color[] cols = new Color[5];

                GradientColorKey[] colorKeys = new GradientColorKey[5];
                GradientAlphaKey[] alphaKeys = new GradientAlphaKey[5];

                for (int t = 0; t < 5; t++)
                {
                    float a =
                        Mathf.Clamp01(alpha.Value(inputs) *
                                      (1 - linAlphaDecay.Value(inputs) * (t / 4f) -
                                       Mathf.Log(logAlphaDecay.Value(inputs) * (t / 4f) + 1)));
                    colorKeys[t] = new GradientColorKey(Color.red, t * 0.25f);
                    alphaKeys[t] = new GradientAlphaKey(a, t * 0.25f);
                }

                ParticleSystem.ColorOverLifetimeModule col = pkpe.pe.colorOverLifetime;
                col.enabled = true;

                Gradient gradient = new Gradient();
                gradient.SetKeys(colorKeys, alphaKeys);

                col.color = new ParticleSystem.MinMaxGradient(gradient);
            }

            pkpe.saturationMult = saturationMult.Value(inputs);
            pkpe.brightnessMult = brightnessMult.Value(inputs);
            pkpe.alphaMult      = alphaMult.Value(inputs);

            pkpe.go.transform.localPosition = localPosition
                                              + offset.Value(inputs) * finalScale * offsetDirection.normalized;

            pkpe.go.transform.localRotation = Quaternion.Euler(localRotation);
        }
    }
예제 #11
0
 public static void Add(PersistentKSPShurikenEmitter pkpe)
 {
     persistentEmittersShuriken.Add(pkpe);
     FloatingOrigin.RegisterParticleSystem(pkpe.pe);
 }
 public static void Add(PersistentKSPShurikenEmitter pkpe)
 {
     persistentEmittersShuriken.Add(pkpe);
     FloatingOrigin.RegisterParticleSystem(pkpe.pe);
 }
    public override void OnInitialize()
    {
        //Print("Init");

        // Restore the Curve config from the node content backup
        // Done because I could not get the serialization of MultiInputCurve to work
        if (node_backup != string.Empty)
        {
            Restore();
        }

        List<Transform> transforms = new List<Transform>(hostPart.FindModelTransforms(transformName));
        if (transforms.Count == 0)
        {
            Print("Cannot find transform " + transformName);
            return;
        }
        GameObject model = GameDatabase.Instance.GetModel(modelName);
        if (model == null)
        {
            Print("Cannot find model " + modelName);
            return;
        }
        model.SetActive(true);
        KSPParticleEmitter templateKspParticleEmitter = model.GetComponentInChildren<KSPParticleEmitter>();

        if (templateKspParticleEmitter == null)
        {
            Print("Cannot find particle emitter on " + modelName);
            Destroy(model);
            return;
        }

        if (persistentEmitters == null)
        {
            persistentEmitters = new List<PersistentKSPShurikenEmitter>();
        }

        if (hostPart.Modules.Contains("ProceduralSRB"))
        {
            PartModule pm = hostPart.Modules["ProceduralSRB"];

            specialScale = pm.Fields.GetValue<float>("bellScale");
            Print("Found ProceduralSRB. Rescaling by " + specialScale.ToString("F3") + " final scale " + (fixedScale * specialScale).ToString("F3"));
        }

        for (int i = 0; i < transforms.Count; i++)
        {
            GameObject emitterGameObject = Instantiate(model) as GameObject;
            KSPParticleEmitter childKSPParticleEmitter = emitterGameObject.GetComponentInChildren<KSPParticleEmitter>();

            //if (shader != null)
            //{
            //    childKSPParticleEmitter.material.shader = shader;
            //    childKSPParticleEmitter.pr.material.shader = shader;
            //}

            if (childKSPParticleEmitter != null)
            {
                // Destroy them ?
                childKSPParticleEmitter.pr.enabled = false;
                childKSPParticleEmitter.pe.enabled = false;
                childKSPParticleEmitter.enabled = false;

                ParticleSystem particleSystem = childKSPParticleEmitter.gameObject.AddComponent<ParticleSystem>();
                ParticleSystemRenderer particleSystemRenderer = childKSPParticleEmitter.gameObject.GetComponent<ParticleSystemRenderer>();

                PersistentKSPShurikenEmitter pkpe = new PersistentKSPShurikenEmitter(
                    emitterGameObject,
                    particleSystem,
                    particleSystemRenderer,
                    templateKspParticleEmitter);

                particleSystem.simulationSpace = childKSPParticleEmitter.pe.useWorldSpace
                    ? ParticleSystemSimulationSpace.World
                    : ParticleSystemSimulationSpace.Local;

                particleSystem.maxParticles = particleCountLimit;

                particleSystemRenderer.material = childKSPParticleEmitter.pr.material;

                // TODO Actually copy the mode from childKSPParticleEmitter.particleRenderMode?
                particleSystemRenderer.renderMode = ParticleSystemRenderMode.Billboard;

                try
                {
                    childKSPParticleEmitter.particleRenderMode =
                        (ParticleRenderMode)Enum.Parse(typeof(ParticleRenderMode), renderMode);
                }
                catch (ArgumentException)
                {
                    Print("ModelMultiParticleFXExt: " + renderMode + " is not a valid ParticleRenderMode");
                }

                switch (childKSPParticleEmitter.particleRenderMode)
                {
                    case ParticleRenderMode.Billboard:
                        particleSystemRenderer.renderMode = ParticleSystemRenderMode.Billboard;
                        break;
                    case ParticleRenderMode.Stretch:
                        particleSystemRenderer.renderMode = ParticleSystemRenderMode.Stretch;
                        break;
                    case ParticleRenderMode.SortedBillboard:
                        particleSystemRenderer.renderMode = ParticleSystemRenderMode.Billboard;
                        particleSystemRenderer.sortMode = ParticleSystemSortMode.Distance;
                        break;
                    case ParticleRenderMode.HorizontalBillboard:
                        particleSystemRenderer.renderMode = ParticleSystemRenderMode.HorizontalBillboard;
                        break;
                    case ParticleRenderMode.VerticalBillboard:
                        particleSystemRenderer.renderMode = ParticleSystemRenderMode.VerticalBillboard;
                        break;
                    default:
                        particleSystemRenderer.renderMode = ParticleSystemRenderMode.Billboard;
                        break;
                }

                //particleSystemRenderer.alignment = ParticleSystemRenderSpace.View;

                if (childKSPParticleEmitter.doesAnimateColor)
                {
                    ParticleSystem.ColorOverLifetimeModule col = particleSystem.colorOverLifetime;
                    col.enabled = true;

                    GradientColorKey[] colorKeys = new GradientColorKey[5];
                    GradientAlphaKey[] alphaKeys = new GradientAlphaKey[5];

                    Color[] colors = childKSPParticleEmitter.colorAnimation;

                    float step = 1f / (colors.Length - 1);

                    for (int t = 0; t < colors.Length; t++)
                    {
                        colorKeys[t] = new GradientColorKey(colors[t], t * step);
                        alphaKeys[t] = new GradientAlphaKey(colors[t].a, t * step);
                    }

                    Gradient gradient = new Gradient();
                    gradient.SetKeys(colorKeys, alphaKeys);

                    col.color = new ParticleSystem.MinMaxGradient(gradient);
                }

                //try
                //{
                //    particleSystemRenderer.renderMode =
                //        (ParticleSystemRenderMode)Enum.Parse(typeof (ParticleSystemRenderMode), renderMode);
                //}
                //catch (ArgumentException)
                //{
                //    Print("ModelMultiParticleFXExt: " + renderMode + " is not a valid ParticleSystemRenderMode");
                //}

                persistentEmitters.Add(pkpe);

                DisableCollider(pkpe.go);

                emitterGameObject.transform.SetParent(transforms[i]);

                emitterGameObject.transform.localPosition = localPosition;
                emitterGameObject.transform.localRotation = Quaternion.Euler(localRotation);
                emitterGameObject.SetLayerRecursive(layerId);
            }
        }

        Destroy(model);

        list.Add(this);

        // 1.0 don't seems to properly do this for engines.
        OnEvent(0);
    }