Merge branch 'resource' into develop

This commit is contained in:
2019-08-30 21:21:18 -07:00
73 changed files with 1448 additions and 2 deletions

View File

@ -0,0 +1,160 @@
using System;
using UnityEngine;
using System.Collections.Generic;
namespace Restock
{
public class ModuleRestockHeatEffects : PartModule
{
// enable the heat glow emissive
[KSPField] public bool enableHeatEmissive = false;
// what shader property to modify. must be a color.
[KSPField] public string shaderProperty = "_EmissiveColor";
// animation curve for the red channel
[KSPField] public FloatCurve redCurve= new FloatCurve();
// animation curve for the green channel
[KSPField] public FloatCurve greenCurve = new FloatCurve();
// animation curve for the blue channel
[KSPField] public FloatCurve blueCurve = new FloatCurve();
// animation curve for the alpha channel
[KSPField] public FloatCurve alphaCurve = new FloatCurve();
// draper point, the temperature in Kelvin where materials start glowing
[KSPField] public double draperPoint = 798.0;
// temperature where the animation is at its maximum
[KSPField] public double lerpMax = double.NaN;
// temperature where the animation is at its minimum, added with draperPoint
[KSPField] public double lerpMin = 0.0;
// use the part's core temperature? (overrides useSkinTemp)
[KSPField] public bool useCoreTemp = false;
// use the part's skin temperature?
[KSPField] public bool useSkinTemp = false;
// should the module disable the stock blackbody glow effect on the included renderers?
[KSPField] public bool disableBlackbody = false;
[KSPField] public List<Renderer> renderers = new List<Renderer>();
private readonly string _shaderBlackbody = "_TemperatureColor";
private ModuleCoreHeat _coreHeatModule = null;
private int _shaderPropertyID;
private int _shaderBlackbodyID;
private double _lerpRange;
private Color _emissiveColor = new Color();
private MaterialPropertyBlock _propertyBlock = new MaterialPropertyBlock();
public void Start()
{
if (base.vessel == null) return;
if (enableHeatEmissive)
{
if (useCoreTemp)
{
_coreHeatModule = base.part.FindModuleImplementing<ModuleCoreHeat>();
if (_coreHeatModule == null)
{
this.LogError("Part has no Core Heat module, skipping");
useCoreTemp = false;
}
}
if (double.IsNaN(lerpMax))
{
if (useCoreTemp)
{
lerpMax = _coreHeatModule.CoreShutdownTemp;
}
else
{
lerpMax = useSkinTemp ? part.skinMaxTemp : part.maxTemp;
}
}
_lerpRange = lerpMax - lerpMin - draperPoint;
_shaderPropertyID = Shader.PropertyToID(shaderProperty);
}
if (disableBlackbody)
{
_shaderBlackbodyID = Shader.PropertyToID(_shaderBlackbody);
}
}
public override void OnLoad(ConfigNode node)
{
if (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight) return;
renderers = base.part.FindModelComponents<Renderer>();
if (node.HasValue("excludedRenderer"))
{
var excludedRenderers = new List<string>();
excludedRenderers.AddRange(node.GetValues("excludedRenderer"));
for (int i = renderers.Count - 1; i >= 0; i--)
{
if (renderers[i] == null || excludedRenderers.Contains(renderers[i].name))
{
renderers.RemoveAt(i);
}
}
}
}
public void LateUpdate()
{
if (!HighLogic.LoadedSceneIsFlight) return;
if (enableHeatEmissive)
{
var temp = 0.0;
if (useCoreTemp)
{
temp = _coreHeatModule.CoreTemperature;
}
else
{
temp = useSkinTemp ? base.part.skinTemperature : base.part.temperature;
}
var temp2 = (float) ((temp - draperPoint) / _lerpRange);
temp2 = Mathf.Clamp01(temp2);
_emissiveColor.r = redCurve.Evaluate(temp2);
_emissiveColor.g = greenCurve.Evaluate(temp2);
_emissiveColor.b = blueCurve.Evaluate(temp2);
_emissiveColor.a = alphaCurve.Evaluate(temp2);
_propertyBlock.SetColor(_shaderPropertyID, _emissiveColor);
}
if (disableBlackbody)
{
_propertyBlock.SetColor(_shaderBlackbodyID, Color.black);
}
foreach (var r in renderers)
{
r.SetPropertyBlock(_propertyBlock);
}
}
}
}

View File

@ -0,0 +1,351 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Restock
{
public class ModuleRestockISRUAnimation : PartModule
{
// name of the deploy animation to use
[KSPField] public string deployAnimationName = "";
// name of the retract animation to use
// will default to using the deploy animation in reverse
[KSPField] public string retractAnimationName = "";
// name of the active animation to use
[KSPField] public string activeAnimationName = "";
// name of the inactive animation to use
[KSPField] public string inactiveAnimationName = "";
// speed to run the animation when deploying
[KSPField] public float deploySpeed = 1.0f;
// speed to run the animation when retracting
[KSPField] public float retractSpeed = 1.0f;
// does this module need electric charge to be enabled?
[KSPField] public bool needsEC = false;
// should the module wait until a current looping animation completes before changing state?
[KSPField] public bool waitForComplete = false;
public bool IsDeployed => (CurrentState == State.InactiveWaiting ||
CurrentState == State.Active ||
CurrentState == State.Deploying);
private enum State
{
Inactive,
InactiveWaiting,
Deploying,
Active,
ActiveWaiting,
Retracting
}
private Animation DeployAnimation { get; set; }
private Animation RetractAnimation { get; set; }
private Animation ActiveAnimation { get; set; }
private Animation InactiveAnimation { get; set; }
private State CurrentState { get; set; }
private bool _deployAnimationPresent = false;
private bool _retractAnimationPresent = false;
private bool _activeAnimationPresent = false;
private bool _inactiveAnimationPresent = false;
private List<BaseConverter> _modules;
public void Start()
{
_modules = base.part.FindModulesImplementing<BaseConverter>();
_deployAnimationPresent = (deployAnimationName != string.Empty);
_retractAnimationPresent = (retractAnimationName != string.Empty);
_activeAnimationPresent = (activeAnimationName != string.Empty);
_inactiveAnimationPresent = (inactiveAnimationName != string.Empty);
DeployAnimation = ((_deployAnimationPresent) ?
base.part.FindModelAnimators(deployAnimationName)[0] : null);
RetractAnimation = ((_retractAnimationPresent) ?
base.part.FindModelAnimators(retractAnimationName)[0] : null);
ActiveAnimation = ((_activeAnimationPresent) ?
base.part.FindModelAnimators(activeAnimationName)[0] : null);
InactiveAnimation = ((_inactiveAnimationPresent)?
base.part.FindModelAnimators(inactiveAnimationName)[0] : null);
foreach (var a in base.part.FindModelAnimators()) a.Stop();
if (!HighLogic.LoadedSceneIsFlight) return;
if (ConvertersEnabled())
{
DeployStart(1000f);
}
else
{
RetractStart(1000f);
}
}
public override void OnLoad(ConfigNode node)
{
}
public void Update()
{
if (!HighLogic.LoadedSceneIsFlight) return;
try
{
switch (CurrentState)
{
// System is inactive, and playing the inactive animation if present
case State.Inactive:
if (ConvertersEnabled())
{
if (waitForComplete)
{
DeployWait();
}
else
{
DeployStart();
}
}
break;
// System is inactive, but waiting for the animation to end before deploying
case State.InactiveWaiting:
if (!waitForComplete || !_inactiveAnimationPresent)
{
this.LogError(
"Invalid state! waitForComplete not enabled or inactive animation not present.");
CurrentState = State.Inactive;
}
else if (!ConvertersEnabled())
{
RetractEnd();
}
else if (!InactiveAnimation.IsPlaying(inactiveAnimationName))
{
DeployStart();
}
break;
// System is deploying
case State.Deploying:
if (!_deployAnimationPresent)
{
this.LogError("Invalid state! Deploying without an animation present.");
CurrentState = State.Active;
}
else if (!ConvertersEnabled())
{
RetractStart();
}
else if (!DeployAnimation.IsPlaying(deployAnimationName))
{
DeployEnd();
}
break;
// System is active, and playing the active animation if present
case State.Active:
if (!ConvertersEnabled())
{
if (waitForComplete)
{
RetractWait();
}
else
{
RetractStart();
}
}
break;
// System is active, but waiting for the animation to finish before retracting
case State.ActiveWaiting:
if (!waitForComplete || !_activeAnimationPresent)
{
this.LogError("Invalid state! waitForComplete not enabled or active animation not present.");
CurrentState = State.Active;
}
else if (ConvertersEnabled())
{
DeployEnd();
}
else if (!ActiveAnimation.IsPlaying(activeAnimationName))
{
RetractStart();
}
break;
// System is retracting
case State.Retracting:
if (!_retractAnimationPresent && !_deployAnimationPresent)
{
this.LogError("Invalid state! Retracting without an animation present.");
CurrentState = State.Inactive;
}
else if (ConvertersEnabled())
{
DeployStart();
}
else if (!RetractAnimation.IsPlaying(retractAnimationName))
{
RetractEnd();
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
catch (Exception e)
{
this.LogException("Failed to update animation module", e);
}
}
private void DeployWait()
{
if (_inactiveAnimationPresent){
CurrentState = State.InactiveWaiting;
PlayAnimation(InactiveAnimation, inactiveAnimationName, loop: false);
}
else
{
DeployStart();
}
}
private void DeployStart(float speed = 1f)
{
if (_deployAnimationPresent)
{
if (_retractAnimationPresent && RetractAnimation.IsPlaying(retractAnimationName))
{
RetractAnimation.Stop(retractAnimationName);
}
CurrentState = State.Deploying;
PlayAnimation(DeployAnimation, deployAnimationName, speed * deploySpeed);
}
else
{
DeployEnd();
}
}
private void DeployEnd()
{
CurrentState = State.Active;
if (_activeAnimationPresent)
{
PlayAnimation(ActiveAnimation, activeAnimationName, loop: true);
}
}
private void RetractWait()
{
if (_activeAnimationPresent)
{
CurrentState = State.ActiveWaiting;
PlayAnimation(ActiveAnimation, activeAnimationName, loop: false);
}
else
{
RetractStart();
}
}
private void RetractStart(float speed = 1f)
{
if (_retractAnimationPresent)
{
if (_deployAnimationPresent && DeployAnimation.IsPlaying(deployAnimationName))
{
DeployAnimation.Stop(deployAnimationName);
}
CurrentState = State.Retracting;
PlayAnimation(RetractAnimation, retractAnimationName, speed * retractSpeed);
}
else if (_deployAnimationPresent)
{
CurrentState = State.Retracting;
PlayAnimation(DeployAnimation, deployAnimationName, speed * retractSpeed * -1);
}
else
{
RetractEnd();
}
}
private void RetractEnd()
{
CurrentState = State.Inactive;
if (_inactiveAnimationPresent)
{
PlayAnimation(InactiveAnimation, inactiveAnimationName, loop: true);
}
}
private bool ConvertersEnabled()
{
if (needsEC && !CheatOptions.InfiniteElectricity)
{
var ecHash = PartResourceLibrary.ElectricityHashcode;
base.vessel.GetConnectedResourceTotals(ecHash, out var ecAmount, out _, true);
if (ecAmount < 0.1)
{
return false;
}
}
foreach (var m in _modules)
{
if (m.ModuleIsActive())
{
return true;
}
}
return false;
}
private static void PlayAnimation(Animation anim, string name, float speed = 1f, bool loop = false)
{
var animState = anim[name];
if (animState.wrapMode != WrapMode.Loop)
{
if (speed < 0 && animState.time < Mathf.Epsilon)
{
animState.time = animState.length;
}
else if (speed > 0 && animState.time > animState.length - Mathf.Epsilon)
{
animState.time = 0.0f;
}
}
animState.speed = speed;
animState.wrapMode = loop ? WrapMode.Loop : WrapMode.Once;
//if (!anim.IsPlaying(name))
anim.Play(name);
}
}
}

View File

@ -49,6 +49,8 @@
<Compile Include="MaterialModifiers\TexturePropertyMaterialModifier.cs" />
<Compile Include="ModuleRestockLinkedMesh.cs" />
<Compile Include="ModuleRestockDepthMask.cs" />
<Compile Include="ModuleRestockHeatEffects.cs" />
<Compile Include="ModuleRestockISRUAnimation.cs" />
<Compile Include="ModuleRestockModifyFairingMaterials.cs" />
<Compile Include="ModuleRestockModifyMaterials.cs" />
<Compile Include="PartModuleExtensions.cs" />