public override void OnUpdate() { if (enablingVariable == null) { return; } RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); if (enablingVariable.IsInRange(comp)) { base.OnUpdate(); Quaternion post = navBall.rotation; float deltaAngle = Quaternion.Angle(lastOrientation, post); float maxAngle = maxAngleChange * Time.deltaTime; // If the rotation angle exceeds what we can do, slow it down if (deltaAngle > maxAngle) { Quaternion newRotation = Quaternion.Slerp(lastOrientation, post, maxAngle / deltaAngle); lastOrientation = newRotation; navBall.rotation = newRotation; } else { lastOrientation = post; } } }
public override void OnUpdate() { if (!JUtil.UserIsInPod(part)) { StopPlaying(); return; } if (needsElectricCharge) { soundCheckCountdown--; if (soundCheckCountdown <= 0) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); soundCheckCountdown = soundCheckRate; electricChargeReserve = comp.ProcessVariable(resourceName).MassageToFloat(); if (electricChargeReserve < 0.01f) { StopPlaying(); return; } } } StartPlaying(); }
/// <summary> /// Evaluate the variable, returning it in destination. /// </summary> /// <param name="destination"></param> /// <param name="comp"></param> /// <returns></returns> public bool Get(out double destination, RPMVesselComputer comp) { if (type == VoNType.ConstantString) { destination = 0.0; return(false); } else if (type == VoNType.VariableValue) { numericValue = comp.ProcessVariable(variableName).MassageToDouble(); if (double.IsNaN(numericValue) || double.IsInfinity(numericValue)) { if (!warningMade) { JUtil.LogMessage(this, "Warning: {0} can fail to produce a usable number.", variableName); warningMade = true; } destination = numericValue; return(false); } } destination = numericValue; return(true); }
private void UpdateMethods() { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); GetSmartassMode = (Func <int>)comp.GetMethod("JSIMechJeb:GetSmartassMode", internalProp, typeof(Func <int>)); SetSmartassMode = (Action <JSIMechJeb.Target>)comp.GetMethod("JSIMechJeb:SetSmartassMode", internalProp, typeof(Action <JSIMechJeb.Target>)); SetForceRoll = (Action <bool, double>)comp.GetMethod("JSIMechJeb:ForceRoll", internalProp, typeof(Action <bool, double>)); GetModuleExists = (Func <string, bool>)comp.GetMethod("JSIMechJeb:GetModuleExists", internalProp, typeof(Func <string, bool>)); CircularizeAt = (Action <double>)comp.GetMethod("JSIMechJeb:CircularizeAt", internalProp, typeof(Action <double>)); PositionTargetExists = (Func <bool>)comp.GetMethod("JSIMechJeb:PositionTargetExists", internalProp, typeof(Func <bool>)); AutopilotEnabled = (Func <bool>)comp.GetMethod("JSIMechJeb:AutopilotEnabled", internalProp, typeof(Func <bool>)); GetForceRollAngle = (Func <double>)comp.GetMethod("JSIMechJeb:GetForceRollAngle", internalProp, typeof(Func <double>)); AscentAP = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonAscentGuidance", internalProp, typeof(Action <bool>)); AscentAPState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonAscentGuidanceState", internalProp, typeof(Func <bool>)); LandingAP = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonLandingGuidance", internalProp, typeof(Action <bool>)); LandingAPState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonLandingGuidanceState", internalProp, typeof(Func <bool>)); DockingAP = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonDockingGuidance", internalProp, typeof(Action <bool>)); DockingAPState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonDockingGuidanceState", internalProp, typeof(Func <bool>)); ForceRoll = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonForceRoll", internalProp, typeof(Action <bool>)); ForceRollState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonForceRollState", internalProp, typeof(Func <bool>)); ExecuteNextNode = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonNodeExecute", internalProp, typeof(Action <bool>)); ExecuteNextNodeState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonNodeExecuteState", internalProp, typeof(Func <bool>)); }
internal void Update(RPMVesselComputer comp) { float value; if (enablingVariable != null) { if (!enablingVariable.IsInRange(comp)) { return; } } if (variable.Get(out value, comp)) { if (useLog10) { value = JUtil.PseudoLog10(value); } float xOffset = JUtil.DualLerp(textureLimit, scale, value); MeshFilter meshFilter = barObject.GetComponent <MeshFilter>(); meshFilter.mesh.uv = new[] { new Vector2(xOffset - textureSize, 0.0f), new Vector2(xOffset + textureSize, 0.0f), new Vector2(xOffset - textureSize, 1.0f), new Vector2(xOffset + textureSize, 1.0f) }; JUtil.ShowHide(true, barObject); } }
public static string ProcessString(string input, RPMVesselComputer comp, int propID = -1) { try { if (input.IndexOf(JUtil.VariableListSeparator[0], StringComparison.Ordinal) >= 0) { string[] tokens = input.Split(JUtil.VariableListSeparator, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length != 2) { return("FORMAT ERROR"); } else { string[] vars = tokens[1].Split(JUtil.VariableSeparator, StringSplitOptions.RemoveEmptyEntries); var variables = new object[vars.Length]; for (int i = 0; i < vars.Length; i++) { variables[i] = comp.ProcessVariable(vars[i], propID); } string output = string.Format(fp, tokens[0], variables); return(output.TrimEnd()); } } } catch (Exception e) { JUtil.LogMessage(comp, "Bad format on string {0}", input); throw e; } return(input.TrimEnd()); }
public void Start() { JUtil.LogMessage(this, "Setting RasterPropMonitor debugging to {0}", debugLogging); JUtil.debugLoggingEnabled = debugLogging; if (!HighLogic.LoadedSceneIsEditor) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); comp.SetVesselDescription(vesselDescription); // Make sure we have the description strings parsed. string[] descriptionStrings = vesselDescription.UnMangleConfigText().Split(JUtil.LineSeparator, StringSplitOptions.None); for (int i = 0; i < descriptionStrings.Length; i++) { if (descriptionStrings[i].StartsWith("AG", StringComparison.Ordinal) && descriptionStrings[i][3] == '=') { uint groupID; if (uint.TryParse(descriptionStrings[i][2].ToString(), out groupID)) { descriptionStrings[i] = string.Empty; } } } vesselDescriptionForDisplay = string.Join(Environment.NewLine, descriptionStrings).MangleConfigText(); // Now let's parse our stored strings... if (!string.IsNullOrEmpty(storedStrings)) { storedStringsArray = storedStrings.Split('|'); } ParseData(); } }
/// <summary> /// Update the compass / heading bar /// </summary> private void UpdateHeading(Quaternion rotationVesselSurface, RPMVesselComputer comp) { float heading = rotationVesselSurface.eulerAngles.y / 360.0f; MeshFilter meshFilter = headingMesh.GetComponent <MeshFilter>(); meshFilter.mesh.uv = new[] { new Vector2(heading - headingBarTextureWidth, 0.0f), new Vector2(heading + headingBarTextureWidth, 0.0f), new Vector2(heading - headingBarTextureWidth, 1.0f), new Vector2(heading + headingBarTextureWidth, 1.0f) }; if (progradeHeadingIcon != null) { float slipAngle = comp.Sideslip; float slipTC = JUtil.DualLerp(0f, 1f, 0f, 360f, rotationVesselSurface.eulerAngles.y + slipAngle); float slipIconX = JUtil.DualLerp(progradeHeadingIconOrigin - 0.5f * headingBarPosition.z, progradeHeadingIconOrigin + 0.5f * headingBarPosition.z, heading - headingBarTextureWidth, heading + headingBarTextureWidth, slipTC); Vector3 position = progradeHeadingIcon.transform.position; position.x = slipIconX; progradeHeadingIcon.transform.position = position; JUtil.ShowHide(true, progradeHeadingIcon); } }
/// <summary> /// This intermediary will cache the results so that multiple variable /// requests within the frame would not result in duplicated code. /// </summary> /// <param name="input"></param> /// <returns></returns> public object ProcessVariable(string input, RPMVesselComputer comp) { input = input.Trim(); if (RPMGlobals.debugShowVariableCallCount) { debug_callCount[input] = debug_callCount[input] + 1; } if (comp == null) { comp = RPMVesselComputer.Instance(vid); } if (!variableCache.ContainsKey(input)) { AddVariable(input); } VariableCache vc = variableCache[input]; if (vc.cacheable) { return(vc.value.Get()); } else { return(vc.evaluator(input, comp)); } }
public double Evaluate(RPMVesselComputer comp, PersistenceAccessor persistence) { float result = comp.ProcessVariable(sourceVariable, persistence).MassageToFloat(); Vector2 sourceRange; if (!string.IsNullOrEmpty(sourceMinStr)) { sourceRange.x = comp.ProcessVariable(sourceMinStr, persistence).MassageToFloat(); } else { sourceRange.x = sourceMin; } if (!string.IsNullOrEmpty(sourceMaxStr)) { sourceRange.y = comp.ProcessVariable(sourceMaxStr, persistence).MassageToFloat(); } else { sourceRange.y = sourceMax; } return JUtil.DualLerp(mappedRange, sourceRange, result); }
public void Click() { activeLabel++; if (activeLabel == labelsEx.Count) { activeLabel = 0; } if (labelsEx[activeLabel].hasColor) { colorShiftRenderer.material.SetColor(colorName, labelsEx[activeLabel].color); } if (labelsEx[activeLabel].hasText) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); textObj.text.Text = StringProcessor.ProcessString(labelsEx[activeLabel].label, comp); } // Force an update. updateCountdown = 0; if (audioOutput != null && (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA || CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal)) { audioOutput.audio.Play(); } }
public double Evaluate(RPMVesselComputer comp, PersistenceAccessor persistence) { float result = comp.ProcessVariable(sourceVariable, persistence).MassageToFloat(); Vector2 sourceRange; if (!string.IsNullOrEmpty(sourceMinStr)) { sourceRange.x = comp.ProcessVariable(sourceMinStr, persistence).MassageToFloat(); } else { sourceRange.x = sourceMin; } if (!string.IsNullOrEmpty(sourceMaxStr)) { sourceRange.y = comp.ProcessVariable(sourceMaxStr, persistence).MassageToFloat(); } else { sourceRange.y = sourceMax; } return(JUtil.DualLerp(mappedRange, sourceRange, result)); }
/// <summary> /// Callback for button presses. /// </summary> public void Click() { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); bool switchEnabled = true; if (!forcedShutdown) { if (masterVariable != null) { switchEnabled = masterVariable.IsInRange(comp); } } if (!switchEnabled) { // If the master switch is 'off' and we're not here because // of a forced shutdown, don't allow this switch to work. // early return return; } for (int i = 0; i < action.Count; ++i) { action[i].Click(vessel, null, comp); } }
private IJSIAction AddAction(ConfigNode node) { if (!node.HasValue("name")) { throw new Exception("JSIAction ACTION node is missing a name"); } string name = node.GetValue("name"); RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); if (JSIActionGroupSwitch.groupList.ContainsKey(name)) { return(new JSIKSPAction(name, node)); } else if (name == "intlight") { return(new JSIIntLight(node, comp, internalModel)); } else if (name == "dummy") { return(new JSIDummy(node, comp)); } else if (name == "plugin") { return(new JSIPlugin(node)); } throw new NotImplementedException("No IJSIAction for " + name); }
public void Start() { if (string.IsNullOrEmpty(soundURL)) { JUtil.LogMessage(this, "JSIInternalBackgroundNoise called with no soundURL"); Destroy(this); return; } if (needsElectricCharge) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); comp.UpdateDataRefreshRate(soundCheckRate); electricChargeReserve = comp.ProcessVariable(resourceName).MassageToFloat(); } audioOutput = new FXGroup("RPM" + internalModel.internalName + vessel.id); audioOutput.audio = internalModel.gameObject.AddComponent <AudioSource>(); audioOutput.audio.clip = GameDatabase.Instance.GetAudioClip(soundURL.EnforceSlashes()); audioOutput.audio.Stop(); audioOutput.audio.volume = GameSettings.SHIP_VOLUME * soundVolume; audioOutput.audio.rolloffMode = AudioRolloffMode.Logarithmic; audioOutput.audio.maxDistance = 10f; audioOutput.audio.minDistance = 8f; audioOutput.audio.dopplerLevel = 0f; audioOutput.audio.panStereo = 0f; audioOutput.audio.playOnAwake = false; audioOutput.audio.priority = 255; audioOutput.audio.loop = true; audioOutput.audio.pitch = 1f; }
internal JSIDummy(ConfigNode node, RPMVesselComputer comp) : base(node) { if (!node.HasValue("perPodPersistenceName")) { throw new Exception("Trying to create Dummy JSIAction with no perPodPersistenceName"); } perPodPersistenceName = node.GetValue("perPodPersistenceName"); if (string.IsNullOrEmpty(perPodPersistenceName)) { throw new Exception("Invalid perPodPersistenceName supplied for Dummy JSIAction"); } if (node.HasValue("initialState")) { if (!bool.TryParse(node.GetValue("initialState"), out currentState)) { currentState = false; } } else { currentState = false; } currentState = comp.GetPersistentVariable(perPodPersistenceName, currentState); comp.SetPersistentVariable(perPodPersistenceName, currentState); }
// I don't like this mess of copypaste, but how can I improve it away?... public override void OnUpdate() { if (!pageActiveState || !initialized || !JUtil.VesselIsInIVA(vessel) || !UpdateCheck()) { return; } RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); if (legacyRange != null) { float scaledValue; if (!legacyRange.InverseLerp(comp, out scaledValue)) { activePage = 1; return; } activePage = (scaledValue >= threshold.x && scaledValue <= threshold.y) ? 0 : 1; } else { activePage = 0; for (activePage = 0; activePage < range.Count; ++activePage) { if (range[activePage].IsInRange(comp)) { break; } } } }
/// <summary> /// Return the persistent variable, pre-treated as a boolean. /// </summary> /// <param name="name"></param> /// <param name="defaultValue"></param> /// <param name="broadcast">Broadcast the request to other parts of the same craft?</param> /// <returns></returns> internal bool GetPersistentVariable(string name, bool defaultValue, bool broadcast) { object val; if (persistentVars.ContainsKey(name)) { val = persistentVars[name]; } else if (broadcast) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); val = comp.GetPersistentVariable(name, defaultValue); if (val.GetType() == typeof(System.Boolean)) { persistentVars[name] = val; } } else { val = defaultValue; persistentVars[name] = defaultValue; } return((val.GetType() == typeof(System.Boolean)) ? (bool)val : false); }
public static string ProcessString(string input, RasterPropMonitorComputer rpmComp) { try { if (input.IndexOf(JUtil.VariableListSeparator[0], StringComparison.Ordinal) >= 0) { string[] tokens = input.Split(JUtil.VariableListSeparator, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length != 2) { return("FORMAT ERROR"); } else { RPMVesselComputer comp = RPMVesselComputer.Instance(rpmComp.vessel); string[] vars = tokens[1].Split(JUtil.VariableSeparator, StringSplitOptions.RemoveEmptyEntries); var variables = new object[vars.Length]; for (int i = 0; i < vars.Length; i++) { variables[i] = rpmComp.ProcessVariable(vars[i].Trim(), comp); } string output = string.Format(fp, tokens[0], variables); return(output.TrimEnd()); } } } catch (Exception e) { JUtil.LogErrorMessage(rpmComp, "Bad format on string {0}: {1}", input, e); } return(input.TrimEnd()); }
public override void OnUpdate() { if (!JUtil.UserIsInPod(part)) { StopPlaying(); return; } if (needsElectricCharge) { soundCheckCountdown--; if (soundCheckCountdown <= 0) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); soundCheckCountdown = soundCheckRate; electricChargeReserve = (float)comp.ProcessVariable("SYSR_ELECTRICCHARGE"); if (electricChargeReserve < 0.01f) { StopPlaying(); return; } } } StartPlaying(); }
public static string ProcessString(string input, RPMVesselComputer comp, PersistenceAccessor persistence) { try { if (input.IndexOf(JUtil.VariableListSeparator[0], StringComparison.Ordinal) >= 0) { string[] tokens = input.Split(JUtil.VariableListSeparator, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length != 2) { return "FORMAT ERROR"; } else { string[] vars = tokens[1].Split(JUtil.VariableSeparator, StringSplitOptions.RemoveEmptyEntries); var variables = new object[vars.Length]; for (int i = 0; i < vars.Length; i++) { variables[i] = comp.ProcessVariable(vars[i], persistence); } string output = string.Format(fp, tokens[0], variables); return output.TrimEnd(); } } } catch (Exception e) { JUtil.LogMessage(comp, "Bad format on string {0}", input); throw e; } return input.TrimEnd(); }
/// <summary> /// Toggles thrust reversers /// </summary> /// <param name="state"></param> public void SetThrustReverser(bool state) { if (vessel != null) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); for (int i = 0; i < comp.availableThrustReverser.Count; ++i) { ModuleAnimateGeneric thrustReverser = comp.availableThrustReverser[i].thrustReverser; if (thrustReverser != null) { if (state) { if (thrustReverser.Progress < 0.5f && thrustReverser.CanMove && thrustReverser.aniState != ModuleAnimateGeneric.animationStates.MOVING) { thrustReverser.Toggle(); } } else { if (thrustReverser.Progress > 0.5f && thrustReverser.CanMove && thrustReverser.aniState != ModuleAnimateGeneric.animationStates.MOVING) { thrustReverser.Toggle(); } } } } } }
public void Update() { if (!JUtil.IsActiveVessel(vessel)) { return; } if (!JUtil.VesselIsInIVA(vessel)) { for (int unit = 0; unit < variableSets.Count; ++unit) { variableSets[unit].MuteSoundWhileOutOfIVA(); } } if ((!alwaysActive && !JUtil.VesselIsInIVA(vessel)) || !UpdateCheck()) { return; } RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); for (int unit = 0; unit < variableSets.Count; ++unit) { variableSets[unit].Update(comp, persistence); } }
/// <summary> /// Sets multi-mode engines to run in primary mode (true) or secondary /// mode (false). /// </summary> /// <param name="newstate"></param> public void SetEnginesPrimaryMode(bool newstate) { try { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); for (int i = 0; i < comp.availableMultiModeEngines.Count; ++i) { if (comp.availableMultiModeEngines[i].runningPrimary ^ newstate) { if (newstate) { comp.availableMultiModeEngines[i].SetPrimary(true); } else { comp.availableMultiModeEngines[i].SetSecondary(true); } // Revised implementation: //comp.availableMultiModeEngines[i].ModeEvent(); // original implementation: //var ev = comp.availableMultiModeEngines[i].Events["ModeEvent"]; //if (ev != null) //{ // ev.Invoke(); //} } } // Toggling modes changes which engines are enabled and which // are disabled. Force a reset here. comp.InvalidateModuleLists(); } catch { } }
private void CheckForElectricCharge() { if (needsElectricCharge) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); electricChargeReserve = comp.ProcessVariable(resourceName).MassageToFloat(); } }
override internal void Click(bool newState, Vessel vessel, RPMVesselComputer comp) { currentState = !currentState; comp.SetPersistentVariable(persistentVarName, currentState); SetInternalLights(currentState); }
public override void OnUpdate() { if (JUtil.RasterPropMonitorShouldUpdate(vessel) && UpdateCheck()) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); textObj.text.Text = StringProcessor.ProcessString(labelsEx[activeLabel].label, comp); } }
/// <summary> /// Allows enabling/disabling electric generators (and fuel cells) /// </summary> /// <param name="state"></param> public void ButtonEnableElectricGenerator(bool state) { if (vessel != null) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); comp.SetEnableGenerators(state); } }
/// <summary> /// Toggles engines on the current stage (on/off) /// </summary> /// <param name="state">"true" for on, "false" for off</param> public void ButtonEnableEngines(bool state) { if (vessel != null) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); comp.SetEnableEngines(state); } }
/// <summary> /// Toggles the state of deployable solar panels. /// </summary> /// <param name="state"></param> public void SetDeploySolarPanels(bool state) { if (vessel != null) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); comp.SetDeploySolarPanels(state); } }
private void CheckForElectricCharge() { if (needsElectricCharge) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); electricChargeReserve = (double)comp.ProcessVariable("SYSR_ELECTRICCHARGE", null); } }
/// <summary> /// Inverse of SolarPanelsDeployable for use with SetDeploySolarPanels /// </summary> /// <returns></returns> public bool GetDeploySolarPanels() { if (vessel != null) { RPMVesselComputer comp = RPMVesselComputer.Instance(vessel); return(comp.solarPanelsState); } return(true); }
public object Evaluate(RPMVesselComputer comp) { float lerp; if (sourceVariable.InverseLerp(comp, out lerp)) { return Mathf.Lerp(mappedRange.x, mappedRange.y, lerp); } else { return 0.0f; } }
public object Evaluate(RPMVesselComputer comp) { float lerp, extent1, extent2; if (sourceVariable.InverseLerp(comp, out lerp) && mappedExtent1.Get(out extent1, comp) && mappedExtent2.Get(out extent2, comp)) { return Mathf.Lerp(extent1, extent2, lerp); } else { return 0.0f; } }
public object Evaluate(RPMVesselComputer comp) { int i = 0; for (; i < sourceVariables.Count; ++i) { if (sourceVariables[i].IsInRange(comp) ^ reverse[i]) { break; } } float evaluant = 0.0f; result[i].Get(out evaluant, comp); return evaluant; }
public object Evaluate(RPMVesselComputer comp, PersistenceAccessor persistence) { // MOARdV TODO: Reevaluate (SWIDT?) this method if math expressions are added bool evaluation = sourceVariables[0].Evaluate(comp, persistence); for (int i = 1; i < sourceVariables.Count; ++i) { bool nextValue = sourceVariables[i].Evaluate(comp, persistence); switch (op) { case Operator.AND: case Operator.NAND: evaluation = (evaluation) && (nextValue); break; case Operator.OR: case Operator.NOR: evaluation = (evaluation) || (nextValue); break; case Operator.XOR: evaluation = (evaluation) ^ (nextValue); break; default: throw new ArgumentException("CustomVariable.Evaluate was called with an invalid operator?"); case Operator.NONE: break; } } if (op == Operator.NAND || op == Operator.NOR) { evaluation = !evaluation; } return evaluation.GetHashCode(); }
/// <summary> /// Update the compass / heading bar /// </summary> private void UpdateHeading(Quaternion rotationVesselSurface, RPMVesselComputer comp) { float heading = rotationVesselSurface.eulerAngles.y / 360.0f; MeshFilter meshFilter = headingMesh.GetComponent<MeshFilter>(); meshFilter.mesh.uv = new[] { new Vector2(heading - headingBarTextureWidth, 0.0f), new Vector2(heading + headingBarTextureWidth, 0.0f), new Vector2(heading - headingBarTextureWidth, 1.0f), new Vector2(heading + headingBarTextureWidth, 1.0f) }; if (progradeHeadingIcon != null) { float slipAngle = comp.Sideslip; float slipTC = JUtil.DualLerp(0f, 1f, 0f, 360f, rotationVesselSurface.eulerAngles.y + slipAngle); float slipIconX = JUtil.DualLerp(progradeHeadingIconOrigin - 0.5f * headingBarPosition.z, progradeHeadingIconOrigin + 0.5f * headingBarPosition.z, heading - headingBarTextureWidth, heading + headingBarTextureWidth, slipTC); Vector3 position = progradeHeadingIcon.transform.position; position.x = slipIconX; progradeHeadingIcon.transform.position = position; JUtil.ShowHide(true, progradeHeadingIcon); } }
public object Evaluate(RPMVesselComputer comp) { if (indexOperator) { int index = 0; float value = 0.0f; if (!sourceVariables[0].Get(out value, comp)) { return 0; } for (int i = 1; i < sourceVariables.Count; ++i) { float operand; if (!sourceVariables[i].Get(out operand, comp)) { return 0; } switch (op) { case Operator.MAXINDEX: if (operand > value) { index = i; value = operand; } break; case Operator.MININDEX: if (operand < value) { index = i; value = operand; } break; } } return index; } else { float value = 0.0f; if (!sourceVariables[0].Get(out value, comp)) { return 0.0f; } for (int i = 1; i < sourceVariables.Count; ++i) { float operand; if (!sourceVariables[i].Get(out operand, comp)) { return 0.0f; } switch (op) { case Operator.NONE: break; case Operator.ADD: value += operand; break; case Operator.SUBTRACT: value -= operand; break; case Operator.MULTIPLY: value *= operand; break; case Operator.DIVIDE: value /= operand; break; case Operator.MAX: value = Mathf.Max(value, operand); break; case Operator.MIN: value = Mathf.Min(value, operand); break; } } return value; } }
public bool Evaluate(RPMVesselComputer comp, PersistenceAccessor persistence) { return range.IsInRange(comp, persistence) ^ reverse; }
/// <summary> /// This intermediary will cache the results so that multiple variable /// requests within the frame would not result in duplicated code. /// </summary> /// <param name="input"></param> /// <returns></returns> public object ProcessVariable(string input, RPMVesselComputer comp) { input = input.Trim(); if (RPMGlobals.debugShowVariableCallCount) { debug_callCount[input] = debug_callCount[input] + 1; } if (comp == null) { comp = RPMVesselComputer.Instance(vid); } if (!variableCache.ContainsKey(input)) { AddVariable(input); } VariableCache vc = variableCache[input]; if (vc.cacheable) { return vc.value.Get(); } else { return vc.evaluator(input, comp); } }
internal void Update(RPMVesselComputer comp) { bool inRange = variable.IsInRange(comp); if (armed) { if (inRange) { if (!triggered) { JUtil.LogMessage(this, "Event {0} triggered", eventName); triggered = true; armed = oneShot; DoEvent(comp.vessel); } } } else if (!inRange) { JUtil.LogMessage(this, "Event {0} armed", eventName); armed = true; triggered = false; } }
public void RenderData(RenderTexture screen, RPMVesselComputer comp) { float leftVal, rightVal; if (!scale[0].Get(out leftVal, comp) || !scale[1].Get(out rightVal, comp)) { return; // bad values - can't render } float eval = comp.ProcessVariable(variableName).MassageToFloat(); if (float.IsInfinity(eval) || float.IsNaN(eval)) { return; // bad value - can't render } float ratio = Mathf.InverseLerp(leftVal, rightVal, eval); if (thresholdMode) { if (ratio >= threshold.x && ratio <= threshold.y) { if (flashingDelay > 0.0f) { if (lastStateChange + flashingDelay < Planetarium.GetUniversalTime()) { lastStateChange = Planetarium.GetUniversalTime(); lastState = 1.0f - lastState; } ratio = lastState; } else { ratio = 1.0f; } } else { ratio = 0.0f; } } if (reverse) { ratio = 1.0f - ratio; } switch (graphType) { case GraphType.VerticalDown: DrawVerticalDown(ratio); break; case GraphType.VerticalUp: DrawVerticalUp(ratio); break; case GraphType.VerticalSplit: DrawVerticalSplit(ratio); break; case GraphType.HorizontalLeft: DrawHorizontalLeft(ratio); break; case GraphType.HorizontalRight: DrawHorizontalRight(ratio); break; case GraphType.HorizontalSplit: DrawHorizontalSplit(ratio); break; case GraphType.Lamp: DrawLamp(ratio); break; default: throw new NotImplementedException("Unimplemented graphType " + graphType.ToString()); } }
internal object Evaluate(RPMVesselComputer comp) { // MOARdV TODO: Reevaluate (SWIDT?) this method if math expressions are added bool evaluation = sourceVariables[0].IsInRange(comp) ^ reverse[0]; // Use an optimization on evaluation to speed things up bool earlyExit; switch (op) { case Operator.AND: case Operator.NAND: earlyExit = !evaluation; break; case Operator.OR: case Operator.NOR: earlyExit = evaluation; break; case Operator.XOR: earlyExit = false; break; case Operator.NONE: earlyExit = true; break; default: throw new ArgumentException("CustomVariable.Evaluate was called with an invalid operator?"); } for (int i = 1; i < sourceVariables.Count && (earlyExit == false); ++i) { bool nextValue = sourceVariables[i].IsInRange(comp) ^ reverse[i]; switch (op) { case Operator.AND: case Operator.NAND: evaluation = (evaluation) && (nextValue); earlyExit = !evaluation; break; case Operator.OR: case Operator.NOR: evaluation = (evaluation) || (nextValue); earlyExit = evaluation; break; case Operator.XOR: evaluation = (evaluation) ^ (nextValue); break; case Operator.NONE: break; } } if (op == Operator.NAND || op == Operator.NOR) { evaluation = !evaluation; } return evaluation.GetHashCode(); }
/// <summary> /// Evaluate the variable, returning it in destination. /// </summary> /// <param name="destination"></param> /// <param name="comp"></param> /// <returns></returns> public bool Get(out float destination, RPMVesselComputer comp) { if (!string.IsNullOrEmpty(variableName)) { value = comp.ProcessVariable(variableName).MassageToFloat(); if (float.IsNaN(value) || float.IsInfinity(value)) { if (!warningMade) { JUtil.LogMessage(this, "Warning: {0} can fail to produce a usable number.", variableName); warningMade = true; } destination = value; return false; } } destination = value; return true; }
public void Update(RPMVesselComputer comp, double universalTime) { float scaledValue; if (!variable.InverseLerp(comp, out scaledValue)) { return; } float delta = Mathf.Abs(scaledValue - lastScaledValue); if (delta < float.Epsilon) { if (thresholdMode && flashingDelay > 0.0 && scaledValue >= threshold.x && scaledValue <= threshold.y) { // If we're blinking our lights, they need to keep blinking if (lastStateChange < universalTime - flashingDelay) { if (currentState) { TurnOff(universalTime); } else { TurnOn(universalTime); } } if (alarmActive && audioOutput != null) { audioOutput.audio.volume = alarmSoundVolume * GameSettings.SHIP_VOLUME; } } if (maxRateChange > 0.0f) { lastAnimUpdate = universalTime; } return; } if (maxRateChange > 0.0f && lastScaledValue >= 0.0f) { float maxDelta = (float)(universalTime - lastAnimUpdate) * maxRateChange; if (Mathf.Abs(lastScaledValue - scaledValue) > maxDelta) { if (scaledValue < lastScaledValue) { scaledValue = lastScaledValue - maxDelta; } else { scaledValue = lastScaledValue + maxDelta; } } } lastScaledValue = scaledValue; lastAnimUpdate = universalTime; if (thresholdMode) { if (scaledValue >= threshold.x && scaledValue <= threshold.y) { if (flashingDelay > 0) { if (lastStateChange < universalTime - flashingDelay) { if (currentState) { TurnOff(universalTime); } else { TurnOn(universalTime); } } } else { TurnOn(universalTime); } if (audioOutput != null && !alarmActive) { audioOutput.audio.Play(); alarmActive = true; } } else { TurnOff(universalTime); if (audioOutput != null && alarmActive) { if (!alarmMustPlayOnce) { audioOutput.audio.Stop(); } alarmActive = false; } } // Resetting the audio volume in case it was muted while the ship was out of IVA. if (alarmActive && audioOutput != null) { audioOutput.audio.volume = alarmSoundVolume * GameSettings.SHIP_VOLUME; } } else { switch (mode) { case Mode.Rotation: Quaternion newRotation = longPath ? Quaternion.Euler(Vector3.Lerp(vectorStart, vectorEnd, scaledValue)) : Quaternion.Slerp(rotationStart, rotationEnd, scaledValue); controlledTransform.localRotation = initialRotation * newRotation; break; case Mode.Translation: controlledTransform.localPosition = initialPosition + Vector3.Lerp(vectorStart, vectorEnd, scaledValue); break; case Mode.Scale: controlledTransform.localScale = initialScale + Vector3.Lerp(vectorStart, vectorEnd, scaledValue); break; case Mode.Color: affectedMaterial.SetColor(colorName, Color.Lerp(passiveColor, activeColor, scaledValue)); break; case Mode.TextureShift: for (int i = 0; i < textureLayer.Count; ++i) { affectedMaterial.SetTextureOffset(textureLayer[i], Vector2.Lerp(textureShiftStart, textureShiftEnd, scaledValue)); } break; case Mode.TextureScale: for (int i = 0; i < textureLayer.Count; ++i) { affectedMaterial.SetTextureScale(textureLayer[i], Vector2.Lerp(textureScaleStart, textureScaleEnd, scaledValue)); } break; case Mode.LoopingAnimation: // MOARdV TODO: Define what this actually does case Mode.Animation: float lerp = (reverse) ? (1.0f - scaledValue) : scaledValue; onAnim[animationName].normalizedTime = lerp; break; } } }
public bool InverseLerp(RPMVesselComputer comp, out float scaledValue) { float value; float low, high; if (!(sourceValue.Get(out value, comp) && lowerBound.Get(out low, comp) && upperBound.Get(out high, comp))) { scaledValue = 0.0f; return false; } else { scaledValue = Mathf.InverseLerp(low, high, value); return true; } }
/// <summary> /// Provides a simple boolean true/false for whether the named /// variable is in range. /// </summary> /// <param name="comp"></param> /// <param name="persistence"></param> /// <returns></returns> public bool IsInRange(RPMVesselComputer comp) { float value; float low, high; if(!(sourceValue.Get(out value, comp) && lowerBound.Get(out low, comp) && upperBound.Get(out high, comp))) { return false; } else if (high < low) { return (value >= high && value <= low); } else { return (value >= low && value <= high); } }
internal object Evaluate(RPMVesselComputer comp) { float value = 0.0f; if(!sourceVariables[0].Get(out value, comp)) { return 0.0f; } for (int i = 1; i < sourceVariables.Count; ++i) { float operand; if(!sourceVariables[i].Get(out operand, comp)) { return 0.0f; } switch(op) { case Operator.NONE: break; case Operator.ADD: value += operand; break; case Operator.SUBTRACT: value -= operand; break; case Operator.MULTIPLY: value *= operand; break; case Operator.DIVIDE: value /= operand; break; case Operator.MAX: value = Mathf.Max(value, operand); break; case Operator.MIN: value = Mathf.Min(value, operand); break; } } return value; }
/// <summary> /// Update the ladder's texture UVs so it's drawn correctly /// </summary> private void UpdateLadder(Quaternion rotationVesselSurface, RPMVesselComputer comp) { float pitch = 90.0f - Vector3.Angle(comp.Forward, comp.Up); float ladderMidpointCoord; if (use360horizon) { // Straight up is texture coord 0.75; // Straight down is TC 0.25; ladderMidpointCoord = JUtil.DualLerp(0.25f, 0.75f, -90f, 90f, pitch); } else { // Straight up is texture coord 1.0; // Straight down is TC 0.0; ladderMidpointCoord = JUtil.DualLerp(0.0f, 1.0f, -90f, 90f, pitch); } // MOARdV TODO: These can be done without manually editing the // mesh filter. I need to look up the game object texture stuff. MeshFilter meshFilter = ladderMesh.GetComponent<MeshFilter>(); meshFilter.mesh.uv = new[] { new Vector2(0.5f - horizonTextureSize.x, ladderMidpointCoord - horizonTextureSize.y), new Vector2(0.5f + horizonTextureSize.x, ladderMidpointCoord - horizonTextureSize.y), new Vector2(0.5f - horizonTextureSize.x, ladderMidpointCoord + horizonTextureSize.y), new Vector2(0.5f + horizonTextureSize.x, ladderMidpointCoord + horizonTextureSize.y) }; float roll = rotationVesselSurface.eulerAngles.z; ladderMesh.transform.Rotate(new Vector3(0.0f, 0.0f, 1.0f), lastRoll - roll); lastRoll = roll; if (progradeLadderIcon != null) { float AoA = comp.AbsoluteAoA; AoA = (float)JUtil.ClampDegrees180(AoA); if (float.IsNaN(AoA)) { AoA = 0.0f; } float AoATC; if (use360horizon) { // Straight up is texture coord 0.75; // Straight down is TC 0.25; AoATC = JUtil.DualLerp(0.25f, 0.75f, -90f, 90f, AoA); } else { // Straight up is texture coord 1.0; // Straight down is TC 0.0; AoATC = JUtil.DualLerp(0.0f, 1.0f, -90f, 90f, AoA); } float Ypos = JUtil.DualLerp( -horizonSize.y * 0.5f, horizonSize.y * 0.5f, ladderMidpointCoord - horizonTextureSize.y, ladderMidpointCoord + horizonTextureSize.y, AoATC); Vector3 position = progradeLadderIcon.transform.position; position.x = Ypos * Mathf.Sin(roll * Mathf.Deg2Rad); position.y = Ypos * Mathf.Cos(roll * Mathf.Deg2Rad); progradeLadderIcon.transform.position = position; JUtil.ShowHide(true, progradeLadderIcon); } }
public void Update(RPMVesselComputer comp) { float scaledValue; if (!variable.InverseLerp(comp, out scaledValue)) { return; } // MOARdV TODO: What's a good epsilon here? .001 may be too // precise. For an RGB lerp, 1/256 (or so) may be the finest // precision we can represent. if (Mathf.Abs(scaledValue - lastScaledValue) < epsilon) { if (thresholdMode && flashingDelay > 0.0 && scaledValue >= threshold.x && scaledValue <= threshold.y) { // If we're blinking our lights, they need to keep blinking if (lastStateChange < Planetarium.GetUniversalTime() - flashingDelay) { if (currentState) { TurnOff(); } else { TurnOn(); } } if (alarmActive && audioOutput != null) { audioOutput.audio.volume = alarmSoundVolume * GameSettings.SHIP_VOLUME; } } } lastScaledValue = scaledValue; if (thresholdMode) { if (scaledValue >= threshold.x && scaledValue <= threshold.y) { if (flashingDelay > 0) { if (lastStateChange < Planetarium.GetUniversalTime() - flashingDelay) { if (currentState) { TurnOff(); } else { TurnOn(); } } } else { TurnOn(); } if (audioOutput != null && !alarmActive) { audioOutput.audio.Play(); alarmActive = true; } } else { TurnOff(); if (audioOutput != null && alarmActive) { if (!alarmMustPlayOnce) { audioOutput.audio.Stop(); } alarmActive = false; } } // Resetting the audio volume in case it was muted while the ship was out of IVA. if (alarmActive && audioOutput != null) { audioOutput.audio.volume = alarmSoundVolume * GameSettings.SHIP_VOLUME; } } else { switch (mode) { case Mode.Rotation: Quaternion newRotation = longPath ? Quaternion.Euler(Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue)) : Quaternion.Slerp(reverse ? rotationEnd : rotationStart, reverse ? rotationStart : rotationEnd, scaledValue); controlledTransform.localRotation = initialRotation * newRotation; break; case Mode.Translation: controlledTransform.localPosition = initialPosition + Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue); break; case Mode.Scale: controlledTransform.localScale = initialScale + Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue); break; case Mode.Color: colorShiftRenderer.material.SetColor(colorName, Color.Lerp(reverse ? activeColor : passiveColor, reverse ? passiveColor : activeColor, scaledValue)); break; case Mode.TextureShift: foreach (string token in textureLayer.Split(',')) { affectedMaterial.SetTextureOffset(token.Trim(), Vector2.Lerp(reverse ? textureShiftEnd : textureShiftStart, reverse ? textureShiftStart : textureShiftEnd, scaledValue)); } break; case Mode.TextureScale: foreach (string token in textureLayer.Split(',')) { affectedMaterial.SetTextureScale(token.Trim(), Vector2.Lerp(reverse ? textureScaleEnd : textureScaleStart, reverse ? textureScaleStart : textureScaleEnd, scaledValue)); } break; case Mode.LoopingAnimation: // MOARdV TODO: Define what this actually does case Mode.Animation: float lerp = (reverse) ? (1.0f - scaledValue) : scaledValue; onAnim[animationName].normalizedTime = lerp; break; } } }
internal void Update(RPMVesselComputer comp, PersistenceAccessor persistence) { float value; if (enablingVariable != null) { if (!enablingVariable.IsInRange(comp, persistence)) { return; } } if (variable.Get(out value, comp, persistence)) { if (useLog10) { value = JUtil.PseudoLog10(value); } float yOffset = JUtil.DualLerp(textureLimit, scale, value); MeshFilter meshFilter = barObject.GetComponent<MeshFilter>(); meshFilter.mesh.uv = new[] { new Vector2(0.0f, yOffset - textureSize), new Vector2(1.0f, yOffset - textureSize), new Vector2(0.0f, yOffset + textureSize), new Vector2(1.0f, yOffset + textureSize) }; JUtil.ShowHide(true, barObject); } }
public void Update(double time, RPMVesselComputer comp, PersistenceAccessor persistence) { double value = isFlat ? flatValue : comp.ProcessVariable(variableName, persistence).MassageToDouble(); if (double.IsNaN(value) || double.IsInfinity(value)) { return; } points.Add(new Vector2d(time, value)); if (points.Count > maxPoints) { points.RemoveRange(0, points.Count - maxPoints); } }
public void Update(RPMVesselComputer comp, PersistenceAccessor persistence) { var scaleResults = new float[3]; for (int i = 0; i < 3; i++) { if (!scaleEnds[i].Get(out scaleResults[i], comp, persistence)) { return; } } float scaledValue = Mathf.InverseLerp(scaleResults[0], scaleResults[1], scaleResults[2]); if (thresholdMode) { if (scaledValue >= threshold.x && scaledValue <= threshold.y) { if (flashingDelay > 0) { if (lastStateChange < Planetarium.GetUniversalTime() - flashingDelay) { if (currentState) { TurnOff(); } else { TurnOn(); } } } else { TurnOn(); } if (audioOutput != null && !alarmActive) { audioOutput.audio.Play(); alarmActive = true; } } else { TurnOff(); if (audioOutput != null && alarmActive) { if (!alarmMustPlayOnce) { audioOutput.audio.Stop(); } alarmActive = false; } } // Resetting the audio volume in case it was muted while the ship was out of IVA. if (alarmActive && audioOutput != null) { audioOutput.audio.volume = alarmSoundVolume * GameSettings.SHIP_VOLUME; } } else { switch (mode) { case Mode.Rotation: Quaternion newRotation = longPath ? Quaternion.Euler(Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue)) : Quaternion.Slerp(reverse ? rotationEnd : rotationStart, reverse ? rotationStart : rotationEnd, scaledValue); controlledTransform.localRotation = initialRotation * newRotation; break; case Mode.Translation: controlledTransform.localPosition = initialPosition + Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue); break; case Mode.Scale: controlledTransform.localScale = initialScale + Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue); break; case Mode.Color: colorShiftRenderer.material.SetColor(colorName, Color.Lerp(reverse ? activeColor : passiveColor, reverse ? passiveColor : activeColor, scaledValue)); break; case Mode.TextureShift: foreach (string token in textureLayer.Split(',')) { affectedMaterial.SetTextureOffset(token.Trim(), Vector2.Lerp(reverse ? textureShiftEnd : textureShiftStart, reverse ? textureShiftStart : textureShiftEnd, scaledValue)); } break; case Mode.TextureScale: foreach (string token in textureLayer.Split(',')) { affectedMaterial.SetTextureScale(token.Trim(), Vector2.Lerp(reverse ? textureScaleEnd : textureScaleStart, reverse ? textureScaleStart : textureScaleEnd, scaledValue)); } break; case Mode.LoopingAnimation: // MOARdV TODO: Define what this actually does case Mode.Animation: float lerp = JUtil.DualLerp(reverse ? 1f : 0f, reverse ? 0f : 1f, scaleResults[0], scaleResults[1], scaleResults[2]); if (float.IsNaN(lerp) || float.IsInfinity(lerp)) { lerp = reverse ? 1f : 0f; } onAnim[animationName].normalizedTime = lerp; break; } } }
internal TriggeredEvent(TriggeredEventTemplate template, RPMVesselComputer comp) { eventName = template.eventName; if (string.IsNullOrEmpty(eventName)) { throw new Exception("TriggeredEvent: eventName not valid"); } string[] tokens = template.range.Split(','); if (string.IsNullOrEmpty(template.variableName)) { throw new Exception("TriggeredEvent: variableName not valid"); } if (tokens.Length != 2) { throw new Exception("TriggeredEvent: tokens not valid"); } variable = new VariableOrNumberRange(template.variableName, tokens[0], tokens[1]); if (JSIActionGroupSwitch.groupList.ContainsKey(template.triggerEvent)) { isPluginAction = false; action = JSIActionGroupSwitch.groupList[template.triggerEvent]; } else { isPluginAction = true; pluginAction = (Action<bool>)comp.GetInternalMethod(template.triggerEvent, typeof(Action<bool>)); if (pluginAction == null) { throw new Exception("TriggeredEvent: Unable to initialize pluginAction"); } } if (string.IsNullOrEmpty(template.triggerState)) { throw new Exception("TriggeredEvent: Unable to initialize triggerState"); } if (bool.TryParse(template.triggerState, out triggerState)) { toggleAction = false; } else if (template.triggerState.ToLower() == "toggle") { toggleAction = true; if (isPluginAction) { pluginState = (Func<bool>)comp.GetInternalMethod(template.eventState, typeof(Func<bool>)); if (pluginState == null) { throw new Exception("TriggeredEvent: Unable to initialize pluginState"); } } } else { throw new Exception("TriggeredEvent: Unable to determine triggerState"); } if (!string.IsNullOrEmpty(template.oneShot)) { if (!bool.TryParse(template.oneShot, out oneShot)) { oneShot = false; } } else { oneShot = false; } JUtil.LogMessage(this, "Triggered Event {0} created", eventName); }