From b14362745d6ba11b216a74094a1a2793cdd27c3b Mon Sep 17 00:00:00 2001 From: sirkut Date: Thu, 26 Jun 2014 08:06:54 -0400 Subject: [PATCH] 0.16.5 --- InfernalRobotics/InfernalRobotics/Toggle.cs | 1729 +++++++++++-------- 1 file changed, 1043 insertions(+), 686 deletions(-) diff --git a/InfernalRobotics/InfernalRobotics/Toggle.cs b/InfernalRobotics/InfernalRobotics/Toggle.cs index bee42e9..662be82 100644 --- a/InfernalRobotics/InfernalRobotics/Toggle.cs +++ b/InfernalRobotics/InfernalRobotics/Toggle.cs @@ -1,930 +1,1287 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using UnityEngine; -using MuMech; -using System.IO; -using InfernalRobotics; +using System.Linq; using KSPAPIExtensions; -using KSP.IO; - namespace MuMech { - [KSPAddon(KSPAddon.Startup.EveryScene, false)] - public class MuMechGUI : MonoBehaviour + public class MuMechToggle : PartModule { - public class Group + [KSPField(isPersistant = false)] + public bool toggle_drag = false; + [KSPField(isPersistant = false)] + public bool toggle_break = false; + [KSPField(isPersistant = false)] + public bool toggle_model = false; + [KSPField(isPersistant = false)] + public bool toggle_collision = false; + [KSPField(isPersistant = false)] + public float on_angularDrag = 2.0F; + [KSPField(isPersistant = false)] + public float on_maximum_drag = 0.2F; + [KSPField(isPersistant = false)] + public float on_minimum_drag = 0.2F; + [KSPField(isPersistant = false)] + public float on_crashTolerance = 9.0F; + [KSPField(isPersistant = false)] + public float on_breakingForce = 22.0F; + [KSPField(isPersistant = false)] + public float on_breakingTorque = 22.0F; + [KSPField(isPersistant = false)] + public float off_angularDrag = 2.0F; + [KSPField(isPersistant = false)] + public float off_maximum_drag = 0.2F; + [KSPField(isPersistant = false)] + public float off_minimum_drag = 0.2F; + [KSPField(isPersistant = false)] + public float off_crashTolerance = 9.0F; + [KSPField(isPersistant = false)] + public float off_breakingForce = 22.0F; + [KSPField(isPersistant = false)] + public float off_breakingTorque = 22.0F; + [KSPField(isPersistant = false)] + public string on_model = "on"; + [KSPField(isPersistant = false)] + public string off_model = "off"; + + [KSPField(isPersistant = true)] + public string servoName = ""; + [KSPField(isPersistant = true)] + public string groupName = ""; + [KSPField(isPersistant = true)] + public string forwardKey = ""; + [KSPField(isPersistant = true)] + public string reverseKey = ""; + + [KSPField(isPersistant = false)] + public string onKey = "p"; + [KSPField(isPersistant = false)] + public bool onActivate = true; + [KSPField(isPersistant = true)] + public bool on = false; + + [KSPField(isPersistant = true)] + public bool isMotionLock; + [KSPField(isPersistant = true)] + public float customSpeed = 1; + + [KSPField(isPersistant = false)] + public string rotate_model = "on"; + [KSPField(isPersistant = false)] + public Vector3 rotateAxis = Vector3.forward; + [KSPField(isPersistant = false)] + public Vector3 rotatePivot = Vector3.zero; + [KSPField(isPersistant = false)] + public float onRotateSpeed = 0; + [KSPField(isPersistant = false)] + public float keyRotateSpeed = 0; + [KSPField(isPersistant = true)] + public string rotateKey = ""; + [KSPField(isPersistant = true)] + public string revRotateKey = ""; + [KSPField(isPersistant = false)] + public bool rotateJoint = false; + [KSPField(isPersistant = true)] + public bool rotateLimits = false; + [KSPField(isPersistant = true)] + public float rotateMin = 0; + [KSPField(isPersistant = true)] + public float rotateMax = 360; + [KSPField(isPersistant = false)] + public bool rotateLimitsRevertOn = true; + [KSPField(isPersistant = false)] + public bool rotateLimitsRevertKey = false; + [KSPField(isPersistant = false)] + public bool rotateLimitsOff = false; + public float rotationLast = 0; + [KSPField(isPersistant = true)] + public bool reversedRotationOn = false; + [KSPField(isPersistant = true)] + public bool reversedRotationKey = false; + [KSPField(isPersistant = true)] + public float rotationDelta = 0; + [KSPField(isPersistant = true)] + public float rotation = 0; + + [KSPField(isPersistant = false)] + public string bottomNode = "bottom"; + [KSPField(isPersistant = false)] + public string fixedMesh = ""; + [KSPField(isPersistant = false)] + public float jointSpring = 0; + [KSPField(isPersistant = false)] + public float jointDamping = 0; + [KSPField(isPersistant = false)] + public bool invertSymmetry = true; + [KSPField(isPersistant = false)] + public float friction = 0.5F; + + [KSPField(isPersistant = false)] + public string translate_model = "on"; + [KSPField(isPersistant = false)] + public Vector3 translateAxis = Vector3.forward; + [KSPField(isPersistant = false)] + public float onTranslateSpeed = 0; + [KSPField(isPersistant = false)] + public float keyTranslateSpeed = 0; + [KSPField(isPersistant = false)] + public string translateKey = ""; + [KSPField(isPersistant = false)] + public string revTranslateKey = ""; + [KSPField(isPersistant = false)] + public bool translateJoint = false; + [KSPField(isPersistant = true)] + public bool translateLimits = false; + [KSPField(isPersistant = true)] + public float translateMin = 0; + [KSPField(isPersistant = true)] + public float translateMax = 3; + [KSPField(isPersistant = false)] + public bool translateLimitsRevertOn = true; + [KSPField(isPersistant = false)] + public bool translateLimitsRevertKey = false; + [KSPField(isPersistant = false)] + public bool translateLimitsOff = false; + [KSPField(isPersistant = true)] + public bool reversedTranslationOn = false; + [KSPField(isPersistant = true)] + public bool reversedTranslationKey = false; + [KSPField(isPersistant = true)] + public float translationDelta = 0; + [KSPField(isPersistant = true)] + public float translation = 0; + [KSPField(isPersistant = false)] + public bool showGUI = false; + [KSPField(isPersistant = true)] + public bool freeMoving = false; + + [KSPField(isPersistant = true)] + public string minRange = ""; + [KSPField(isPersistant = true)] + public string maxRange = ""; + + [KSPField(isPersistant = false)] + public bool debugColliders = false; + + [KSPField(isPersistant = false)] + public string motorSndPath = ""; + public FXGroup fxSndMotor; + public bool isPlaying = false; + + [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Min Range", guiFormat = "F2", guiUnits = ""), + UI_FloatEdit(minValue = -360f, maxValue = 360f, incrementSlide = 0.01f, scene = UI_Scene.All)] + public float minTweak = 0; + + [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Max Range", guiFormat = "F2", guiUnits = ""), + UI_FloatEdit(minValue = -360f, maxValue = 360f, incrementSlide = 0.01f, scene = UI_Scene.All)] + public float maxTweak = 360; + + [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Step Increment"), + UI_ChooseOption(options = new string[] { "0.01", "0.1", "1.0" })] + public string stepIncrement = "0.1"; + + [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Coarse Speed"), UI_FloatRange(minValue = .1f, maxValue = 5f, stepIncrement = 0.1f)] + public float speedTweak = 1; + + [KSPField(isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Fine Speed"), UI_FloatRange(minValue = -0.1f, maxValue = 0.1f, stepIncrement = 0.01f)] + public float speedTweakFine = 0; + + [KSPField(isPersistant = true)] + public bool limitTweakable = false; + [KSPField(isPersistant = true)] + public bool limitTweakableFlag = false; + [KSPEvent(guiActive = true, guiActiveEditor = true, guiName = "Rotate Limits Off", active = false)] + public void limitTweakableToggle() { - public string name; - public List servos; - public string forwardKey; - public string reverseKey; - public string speed; - public bool showGUI; - - public Group(MuMechToggle servo) + limitTweakableFlag = !limitTweakableFlag; + if (limitTweakableFlag) { - this.name = servo.groupName; - forwardKey = servo.forwardKey; - reverseKey = servo.reverseKey; - speed = servo.customSpeed.ToString("g"); - servos = new List(); - showGUI = servo.showGUI; - servos.Add(servo); + this.Events["limitTweakableToggle"].guiName = "Rotate Limits On"; } - - public Group() + else { - this.name = "New Group"; - forwardKey = ""; - reverseKey = ""; - speed = "1"; - showGUI = true; - servos = new List(); + + this.Events["limitTweakableToggle"].guiName = "Rotate Limits Off"; } } - protected static Rect controlWinPos; - protected static Rect editorWinPos; - protected static Rect groupEditorWinPos; - protected static Rect tweakWinPos; - protected static bool resetWin = false; - protected static Vector2 editorScroll; - List servo_groups; - protected static MuMechGUI gui_controller; - bool guiEnabled = false; - public static MuMechGUI gui + [KSPField(isPersistant = true)] + public bool invertAxis = false; + [KSPEvent(guiActive = true, guiActiveEditor = true, guiName = "Invert Axis Off")] + public void InvertAxisOff() { - get { return gui_controller; } + invertAxis = !invertAxis; + this.Events["InvertAxisOn"].active = true; + this.Events["InvertAxisOff"].active = false; } - static void move_servo(Group from, Group to, MuMechToggle servo) + [KSPEvent(guiActive = true, guiActiveEditor = true, guiName = "Invert Axis On", active = false)] + public void InvertAxisOn() { - to.servos.Add(servo); - from.servos.Remove(servo); - servo.groupName = to.name; - servo.forwardKey = to.forwardKey; - servo.reverseKey = to.reverseKey; + invertAxis = !invertAxis; + this.Events["InvertAxisOn"].active = false; + this.Events["InvertAxisOff"].active = true; } - public static void add_servo(MuMechToggle servo) + protected Vector3 origTranslation; + protected bool gotOrig = false; + + protected List mobileColliders = new List(); + protected int rotationChanged = 0; + protected int translationChanged = 0; + + static Material debug_material; + + protected Transform model_transform; + protected Transform on_model_transform; + protected Transform off_model_transform; + protected Transform rotate_model_transform; + protected Transform translate_model_transform; + + protected bool loaded; + + public int moveFlags = 0; + + private static int s_creationOrder = 0; + public int creationOrder = 0; + + public bool isSymmMaster() { - if (!gui) - return; - gui.enabled = true; - if (servo.part.customPartData != null - && servo.part.customPartData != "") + for (int i = 0; i < part.symmetryCounterparts.Count; i++) { - servo.ParseCData(); - } - if (gui.servo_groups == null) - gui.servo_groups = new List(); - Group group = null; - if (servo.groupName != null && servo.groupName != "") - { - for (int i = 0; i < gui.servo_groups.Count; i++) + if (((MuMechToggle)part.symmetryCounterparts[i].Modules["MuMechToggle"]).creationOrder < creationOrder) { - if (servo.groupName == gui.servo_groups[i].name) - { - group = gui.servo_groups[i]; - break; - } - } - if (group == null) - { - gui.servo_groups.Add(new Group(servo)); - return; + return false; } } - if (group == null) + return true; + } + + //credit for sound support goes to the creators of the Kerbal Attachment + //System + public static bool createFXSound(Part part, FXGroup group, string sndPath, + bool loop, float maxDistance) + { + maxDistance = 10f; + if (sndPath == "") { - if (gui.servo_groups.Count < 1) - { - gui.servo_groups.Add(new Group()); - } - group = gui.servo_groups[gui.servo_groups.Count - 1]; + group.audio = null; + return false; } - - group.servos.Add(servo); - servo.groupName = group.name; - servo.forwardKey = group.forwardKey; - servo.reverseKey = group.reverseKey; + Debug.Log("Loading sounds : " + sndPath); + if (!GameDatabase.Instance.ExistsAudioClip(sndPath)) + { + Debug.Log("Sound not found in the game database!"); + //ScreenMessages.PostScreenMessage("Sound file : " + sndPath + " as not been found, please check your Infernal Robotics installation!", 10, ScreenMessageStyle.UPPER_CENTER); + group.audio = null; + return false; + } + group.audio = part.gameObject.AddComponent(); + group.audio.volume = GameSettings.SHIP_VOLUME; + group.audio.rolloffMode = AudioRolloffMode.Logarithmic; + group.audio.dopplerLevel = 0f; + group.audio.panLevel = 1f; + group.audio.maxDistance = maxDistance; + group.audio.loop = loop; + group.audio.playOnAwake = false; + group.audio.clip = GameDatabase.Instance.GetAudioClip(sndPath); + Debug.Log("Sound successfully loaded."); + return true; } - public static void remove_servo(MuMechToggle servo) + private void playAudio() { - if (!gui) - return; - if (gui.servo_groups == null) - return; - int num = 0; - foreach (var group in gui.servo_groups) + if (!isPlaying && fxSndMotor.audio) { - if (group.name == servo.groupName) - { - group.servos.Remove(servo); - } - num += group.servos.Count; + fxSndMotor.audio.Play(); + isPlaying = true; } - gui.enabled = num > 0; } - void onVesselChange(Vessel v) + + private T configValue(string name, T defaultValue) { - Debug.Log(String.Format("[IR GUI] vessel {0}", v.name)); - servo_groups = null; - guiTweakEnabled = false; - resetWin = true; + try + { + return (T)Convert.ChangeType(name, typeof(T)); + } + catch (InvalidCastException) + { + print("Failed to convert string value \"" + name + "\" to type " + typeof(T).Name); + return defaultValue; + } + } + - var groups = new List(); - var group_map = new Dictionary(); - foreach (Part p in v.Parts) + public void updateState() + { + if (on) { - foreach (var servo in p.Modules.OfType()) + if (toggle_model) { - if (servo.part.customPartData != null - && servo.part.customPartData != "") - { - servo.ParseCData(); - } - if (!group_map.ContainsKey(servo.groupName)) - { - groups.Add(new Group(servo)); - group_map[servo.groupName] = groups.Count - 1; - } - else - { - Group g = groups[group_map[servo.groupName]]; - g.servos.Add(servo); - } + on_model_transform.renderer.enabled = true; + off_model_transform.renderer.enabled = false; } - } - Debug.Log(String.Format("[IR GUI] {0} groups", groups.Count)); - - if (groups.Count == 0) - { - if (ToolbarManager.ToolbarAvailable) + if (toggle_drag) { - IRMinimizeButton.Visible = false; - IRMinimizeGroupButton.Visible = false; + part.angularDrag = on_angularDrag; + part.minimum_drag = on_minimum_drag; + part.maximum_drag = on_maximum_drag; } - } - if (groups.Count > 0) - { - servo_groups = groups; - if (ToolbarManager.ToolbarAvailable) + if (toggle_break) { - IRMinimizeButton.Visible = true; - IRMinimizeGroupButton.Visible = true; + part.crashTolerance = on_crashTolerance; + part.breakingForce = on_breakingForce; + part.breakingTorque = on_breakingTorque; } } - - foreach (Part p in v.Parts) + else { - foreach (var servo in p.Modules.OfType()) + if (toggle_model) + { + on_model_transform.renderer.enabled = false; + off_model_transform.renderer.enabled = true; + } + if (toggle_drag) { - servo.setupJoints(); + part.angularDrag = off_angularDrag; + part.minimum_drag = off_minimum_drag; + part.maximum_drag = off_maximum_drag; } + if (toggle_break) + { + part.crashTolerance = off_crashTolerance; + part.breakingForce = off_breakingForce; + part.breakingTorque = off_breakingTorque; + } + } + if (toggle_collision) + { + part.collider.enabled = on; + part.collisionEnhancer.enabled = on; + part.terrainCollider.enabled = on; } } - int partCounter = 0; - void onPartAttach(GameEvents.HostTargetAction host_target) + protected void colliderizeChilds(Transform obj) { - //Part p = host_target.host; - //foreach (var servo in p.Modules.OfType()) { - // add_servo(servo); - //} - //EditorLogic.fetch.ship.Parts.Count - if ((EditorLogic.fetch.ship.parts.Count >= partCounter) && (EditorLogic.fetch.ship.parts.Count != partCounter)) + if (obj.name.StartsWith("node_collider") + || obj.name.StartsWith("fixed_node_collider") + || obj.name.StartsWith("mobile_node_collider")) { - Part part = host_target.host; - if ((partCounter != 1) && (EditorLogic.fetch.ship.parts.Count != 1)) + print("Toggle: converting collider " + obj.name); + + if (!obj.GetComponent()) { - foreach (var p in part.GetComponentsInChildren()) + print("Collider has no MeshFilter (yet?): skipping Colliderize"); + } + else + { + Mesh sharedMesh = UnityEngine.Object.Instantiate(obj.GetComponent().mesh) as Mesh; + UnityEngine.Object.Destroy(obj.GetComponent()); + UnityEngine.Object.Destroy(obj.GetComponent()); + MeshCollider meshCollider = obj.gameObject.AddComponent(); + meshCollider.sharedMesh = sharedMesh; + meshCollider.convex = true; + obj.parent = part.transform; + + if (obj.name.StartsWith("mobile_node_collider")) { - add_servo(p); + mobileColliders.Add(obj); } - partCounter = EditorLogic.fetch.ship.parts.Count; } } - if ((EditorLogic.fetch.ship.parts.Count == 0) && (partCounter == 0)) + for (int i = 0; i < obj.childCount; i++) + { + colliderizeChilds(obj.GetChild(i)); + } + } + + public override void OnAwake() + { + FindTransforms(); + colliderizeChilds(model_transform); + if (rotateJoint) { - Part part = host_target.host; - if ((partCounter != 1) && (EditorLogic.fetch.ship.parts.Count != 1)) + minTweak = rotateMin; + maxTweak = rotateMax; + if (limitTweakable) { - foreach (var p in part.GetComponentsInChildren()) - { - add_servo(p); - } - partCounter = EditorLogic.fetch.ship.parts.Count; + this.Events["limitTweakableToggle"].active = true; } + + if (freeMoving) + { + this.Events["InvertAxisOn"].active = false; + this.Events["InvertAxisOff"].active = false; + this.Fields["minTweak"].guiActive = false; + this.Fields["minTweak"].guiActiveEditor = false; + this.Fields["maxTweak"].guiActive = false; + this.Fields["maxTweak"].guiActiveEditor = false; + this.Fields["speedTweak"].guiActive = false; + this.Fields["speedTweak"].guiActiveEditor = false; + this.Fields["speedTweakFine"].guiActive = false; + this.Fields["speedTweakFine"].guiActiveEditor = false; + this.Events["Activate"].active = false; + this.Events["Deactivate"].active = false; + this.Fields["stepIncrement"].guiActiveEditor = false; + this.Fields["stepIncrement"].guiActive = false; + } + + } + else if (translateJoint) + { + minTweak = translateMin; + maxTweak = translateMax; + this.Events["limitTweakableToggle"].active = false; + this.Events["limitTweakableToggle"].active = false; + } + var scene = HighLogic.LoadedScene; + if (scene == GameScenes.EDITOR || scene == GameScenes.SPH) + { + if (rotateJoint) + parseMinMaxTweaks(rotateMin, rotateMax); + else if (translateJoint) + parseMinMaxTweaks(translateMin, translateMax); } + } + public override void OnSave(ConfigNode node) + { + base.OnSave(node); + if (rotateJoint) + parseMinMaxTweaks(rotateMin, rotateMax); + else if (translateJoint) + parseMinMaxTweaks(translateMin, translateMax); } - void onPartRemove(GameEvents.HostTargetAction host_target) + public void refreshKeys() { - //Part p = host_target.target; - //foreach (var servo in p.Modules.OfType()) { - // remove_servo(servo); - //} - Part part = host_target.target; - foreach (var p in part.GetComponentsInChildren()) - { - remove_servo(p); - } - if (EditorLogic.fetch.ship.parts.Count == 1) - partCounter = 0; - else - partCounter = EditorLogic.fetch.ship.parts.Count; + translateKey = forwardKey; + revTranslateKey = reverseKey; + rotateKey = forwardKey; + revRotateKey = reverseKey; } - bool update14to15 = false; - IButton IRMinimizeButton; - IButton IRMinimizeGroupButton; - bool groupEditorEnabled = false; - void Awake() + public override void OnLoad(ConfigNode config) { + loaded = true; + FindTransforms(); + colliderizeChilds(model_transform); + //maybe??? + rotationDelta = rotationLast = rotation; + translationDelta = translation; + translateKey = forwardKey; + revTranslateKey = reverseKey; + rotateKey = forwardKey; + revRotateKey = reverseKey; + + if (rotateJoint) + parseMinMaxTweaks(rotateMin, rotateMax); + else if (translateJoint) + parseMinMaxTweaks(translateMin, translateMax); + parseMinMax(); + } - loadConfigXML(); - Debug.Log("[IR GUI] awake"); - //enabled = false; - guiEnabled = false; - groupEditorEnabled = false; - var scene = HighLogic.LoadedScene; - if (scene == GameScenes.FLIGHT) + private void parseMinMaxTweaks(float movementMinimum, float movementMaximum) + { + UI_FloatEdit rangeMinF = (UI_FloatEdit)this.Fields["minTweak"].uiControlFlight; + UI_FloatEdit rangeMinE = (UI_FloatEdit)this.Fields["minTweak"].uiControlEditor; + rangeMinE.minValue = movementMinimum; + rangeMinE.maxValue = movementMaximum; + rangeMinE.incrementSlide = float.Parse(stepIncrement); + rangeMinF.minValue = movementMinimum; + rangeMinF.maxValue = movementMaximum; + rangeMinF.incrementSlide = float.Parse(stepIncrement); + UI_FloatEdit rangeMaxF = (UI_FloatEdit)this.Fields["maxTweak"].uiControlFlight; + UI_FloatEdit rangeMaxE = (UI_FloatEdit)this.Fields["maxTweak"].uiControlEditor; + rangeMaxE.minValue = movementMinimum; + rangeMaxE.maxValue = movementMaximum; + rangeMaxE.incrementSlide = float.Parse(stepIncrement); + rangeMaxF.minValue = movementMinimum; + rangeMaxF.maxValue = movementMaximum; + rangeMaxF.incrementSlide = float.Parse(stepIncrement); + + if (rotateJoint) { - GameEvents.onVesselChange.Add(onVesselChange); - GameEvents.onVesselWasModified.Add(this.onVesselWasModified); - gui_controller = this; + this.Fields["minTweak"].guiName = "Min Rotate"; + this.Fields["maxTweak"].guiName = "Max Rotate"; } - else if (scene == GameScenes.EDITOR || scene == GameScenes.SPH) + else if (translateJoint) { - //partCounter = EditorLogic.fetch.ship.parts.Count; - //onEditorAttach - GameEvents.onPartAttach.Add(onPartAttach); - GameEvents.onPartRemove.Add(onPartRemove); - gui_controller = this; + this.Fields["minTweak"].guiName = "Min Translate"; + this.Fields["maxTweak"].guiName = "Max Translate"; } - else + } + + protected void parseMinMax() + { + // mrblaq - prepare variables for comparison. + // assigning to temp so I can handle empty setting strings on GUI. Defaulting to +/-200 so items' default motion are uninhibited + try { - gui_controller = null; + minTweak = float.Parse(minRange); } - - if (System.IO.File.Exists(KSPUtil.ApplicationRootPath + @"GameData/MagicSmokeIndustries/Plugins/14to15.txt")) + catch (FormatException) { - Debug.Log("debug found!"); - update14to15 = true; + //Debug.Log("Minimum Range Value is not a number"); } - if (ToolbarManager.ToolbarAvailable) + try { - IRMinimizeButton = ToolbarManager.Instance.add("sirkut", "IREditorButton"); - IRMinimizeButton.TexturePath = "MagicSmokeIndustries/Textures/icon_button"; - IRMinimizeButton.ToolTip = "Infernal Robotics"; - IRMinimizeButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.SPH, GameScenes.FLIGHT); - IRMinimizeButton.OnClick += (e) => guiEnabled = !guiEnabled; - - IRMinimizeGroupButton = ToolbarManager.Instance.add("sirkut2", "IREditorGroupButton"); - IRMinimizeGroupButton.TexturePath = "MagicSmokeIndustries/Textures/icon_buttonGROUP"; - IRMinimizeGroupButton.ToolTip = "Infernal Robotics Group Editor"; - IRMinimizeGroupButton.Visibility = new GameScenesVisibility(GameScenes.FLIGHT); - IRMinimizeGroupButton.OnClick += (e) => groupEditorEnabled = !groupEditorEnabled; + maxTweak = float.Parse(maxRange); } - else + catch (FormatException) { - //enabled = true; - guiEnabled = true; - groupEditorEnabled = true; + //Debug.Log("Maximum Range Value is not a number"); } } - - - - void onVesselWasModified(Vessel v) + protected void DebugCollider(MeshCollider collider) { - if (v == FlightGlobals.ActiveVessel) + if (debug_material == null) + { + debug_material = new Material(Shader.Find("Self-Illumin/Specular")); + debug_material.color = Color.red; + } + MeshFilter mf = collider.gameObject.GetComponent(); + if (mf == null) { - servo_groups = null; - onVesselChange(v); + mf = collider.gameObject.AddComponent(); } + mf.sharedMesh = collider.sharedMesh; + MeshRenderer mr = collider.gameObject.GetComponent(); + if (mr == null) + { + mr = collider.gameObject.AddComponent(); + } + mr.sharedMaterial = debug_material; } - void OnDestroy() + protected void AttachToParent(Transform obj) { - Debug.Log("[IR GUI] destroy"); - GameEvents.onVesselChange.Remove(onVesselChange); - GameEvents.onPartAttach.Remove(onPartAttach); - GameEvents.onPartRemove.Remove(onPartRemove); - GameEvents.onVesselWasModified.Remove(this.onVesselWasModified); - if (ToolbarManager.ToolbarAvailable) + Transform fix = transform.FindChild("model").FindChild(fixedMesh); + if (rotateJoint) { - IRMinimizeButton.Destroy(); - IRMinimizeGroupButton.Destroy(); + var pivot = part.transform.TransformPoint(rotatePivot); + var raxis = part.transform.TransformDirection(rotateAxis); + + float sign = 1; + if (invertSymmetry) + { + //FIXME is this actually desired? + sign = ((isSymmMaster() || (part.symmetryCounterparts.Count != 1)) ? 1 : -1); + } + //obj.RotateAround(pivot, raxis, sign * rotation); + fix.RotateAround(transform.TransformPoint(rotatePivot), transform.TransformDirection(rotateAxis), (invertSymmetry ? ((isSymmMaster() || (part.symmetryCounterparts.Count != 1)) ? -1 : 1) : -1) * rotation); } - saveConfigXML(); + else if (translateJoint) + { + //var taxis = part.transform.TransformDirection(translateAxis.normalized); + //obj.Translate(taxis * -(translation - translateMin), Space.Self);//XXX double check sign! + fix.Translate(transform.TransformDirection(translateAxis.normalized) * translation, Space.World); + } + fix.parent = part.parent.transform; } - private void ControlWindow(int windowID) + protected void reparentFriction(Transform obj) { - GUILayout.BeginVertical(); - foreach (Group g in servo_groups) + for (int i = 0; i < obj.childCount; i++) { - if (g.servos.Count() > 0) + var child = obj.GetChild(i); + MeshCollider tmp = child.GetComponent(); + if (tmp != null) { - GUILayout.BeginHorizontal(); - GUILayout.Label(g.name, GUILayout.ExpandWidth(true)); - - int forceFlags = 0; - var width20 = GUILayout.Width(20); - var width40 = GUILayout.Width(40); - forceFlags |= GUILayout.RepeatButton("<", width20) ? 1 : 0; - forceFlags |= GUILayout.RepeatButton("O", width20) ? 4 : 0; - forceFlags |= GUILayout.RepeatButton(">", width20) ? 2 : 0; - - g.speed = GUILayout.TextField(g.speed, width40); - float speed; - bool speed_ok = float.TryParse(g.speed, out speed); - foreach (MuMechToggle servo in g.servos) + tmp.material.dynamicFriction = tmp.material.staticFriction = friction; + tmp.material.frictionCombine = PhysicMaterialCombine.Maximum; + if (debugColliders) { - servo.reverseKey = g.reverseKey; - servo.forwardKey = g.forwardKey; - if (speed_ok) - { - servo.customSpeed = speed; - } - servo.moveFlags &= ~7; - servo.moveFlags |= forceFlags; + DebugCollider(tmp); } + } + if (child.name.StartsWith("fixed_node_collider") && (part.parent != null)) + { + print("Toggle: reparenting collider " + child.name); + AttachToParent(child); + } + } + if ((mobileColliders.Count > 0) && (rotate_model_transform != null)) + { + foreach (Transform c in mobileColliders) + { + c.parent = rotate_model_transform; + } + } + } - GUILayout.EndHorizontal(); + public void BuildAttachments() + { + if (part.findAttachNodeByPart(part.parent).id.Contains(bottomNode) + || part.attachMode == AttachModes.SRF_ATTACH) + { + if (fixedMesh != "") + { + Transform fix = model_transform.FindChild(fixedMesh); + if ((fix != null) && (part.parent != null)) + { + AttachToParent(fix); + } } } - if (ToolbarManager.ToolbarAvailable) + else { - if (GUILayout.Button("Close")) + foreach (Transform t in model_transform) { - saveConfigXML(); - guiEnabled = false; + if (t.name != fixedMesh) + { + AttachToParent(t); + } } + if (translateJoint) + translateAxis *= -1; } - GUILayout.EndVertical(); + reparentFriction(part.transform); + } - GUI.DragWindow(); + protected void FindTransforms() + { + model_transform = part.transform.FindChild("model"); + on_model_transform = model_transform.FindChild(on_model); + off_model_transform = model_transform.FindChild(off_model); + rotate_model_transform = model_transform.FindChild(rotate_model); + translate_model_transform = model_transform.FindChild(translate_model); + } + + public void ParseCData() + { + Debug.Log(String.Format("[IR] not 'loaded': checking cData")); + string customPartData = part.customPartData; + if (customPartData != null && customPartData != "") + { + Debug.Log(String.Format("[IR] old cData found")); + var settings = (Dictionary)KSP.IO.IOUtils.DeserializeFromBinary(Convert.FromBase64String(customPartData.Replace("*", "=").Replace("|", "/"))); + servoName = (string)settings["name"]; + groupName = (string)settings["group"]; + forwardKey = (string)settings["key"]; + reverseKey = (string)settings["revkey"]; + + rotation = (float)settings["rot"]; + translation = (float)settings["trans"]; + invertAxis = (bool)settings["invertAxis"]; + minRange = (string)settings["minRange"]; + maxRange = (string)settings["maxRange"]; + + parseMinMax(); + part.customPartData = ""; + } } - void EditorWindow(int windowID) + private void onEditorAttach() { - var expand = GUILayout.ExpandWidth(true); - var width20 = GUILayout.Width(20); - var width40 = GUILayout.Width(40); - var width60 = GUILayout.Width(60); - var maxHeight = GUILayout.MaxHeight(Screen.height / 2); - Vector2 mousePos = Input.mousePosition; - mousePos.y = Screen.height - mousePos.y; + } - editorScroll = GUILayout.BeginScrollView(editorScroll, false, - false, maxHeight); + // mrblaq return an int to multiply by rotation direction based on GUI "invert" checkbox bool + protected int getAxisInversion() + { + return (invertAxis ? 1 : -1); + } - GUILayout.BeginVertical(); + public override void OnStart(PartModule.StartState state) + { + BaseField field = Fields["stepIncrement"]; + UI_ChooseOption optionsEditor = (UI_ChooseOption)field.uiControlEditor; + UI_ChooseOption optionsFlight = (UI_ChooseOption)field.uiControlFlight; - GUILayout.BeginHorizontal(); - GUILayout.Label("Group Name", expand); - GUILayout.Label("Keys", width40); - if (servo_groups.Count > 1) + if (translateJoint) { - GUILayout.Space(60); + optionsEditor.options = new string[] { "0.01", "0.1", "1.0" }; + optionsFlight.options = new string[] { "0.01", "0.1", "1.0" }; } - GUILayout.EndHorizontal(); - - for (int i = 0; i < servo_groups.Count; i++) + else if (rotateJoint) { - Group grp = servo_groups[i]; - - GUILayout.BeginHorizontal(); - string tmp = GUILayout.TextField(grp.name, expand); - - if (grp.name != tmp) - { - grp.name = tmp; - } + optionsEditor.options = new string[] { "0.1", "1", "10" }; + optionsFlight.options = new string[] { "0.1", "1", "10" }; + } - tmp = GUILayout.TextField(grp.forwardKey, width20); - if (grp.forwardKey != tmp) + part.stackIcon.SetIcon(DefaultIcons.STRUT); + if (vessel == null) + { + return; + } + if (!loaded) + { + loaded = true; + ParseCData(); + on = false; + } + createFXSound(part, fxSndMotor, motorSndPath, true, 10f); + creationOrder = s_creationOrder++; + FindTransforms(); + BuildAttachments(); + updateState(); + if (rotateJoint) + { + parseMinMaxTweaks(rotateMin, rotateMax); + if (limitTweakable) { - grp.forwardKey = tmp; + this.Events["limitTweakableToggle"].active = true; } - tmp = GUILayout.TextField(grp.reverseKey, width20); - if (grp.reverseKey != tmp) + } + else if (translateJoint) + { + parseMinMaxTweaks(translateMin, translateMax); + if (limitTweakable) { - grp.reverseKey = tmp; + this.Events["limitTweakableToggle"].active = false; } + } + } - if (i > 0) + + + private ConfigurableJoint joint; + public bool setupJoints() + { + if (!gotOrig) + { + print("setupJoints - !gotOrig"); + if (rotate_model_transform != null) { - if (GUILayout.Button("Remove", width60)) - { - foreach (var servo in grp.servos) - { - move_servo(grp, servo_groups[i - 1], servo); - } - servo_groups.RemoveAt(i); - resetWin = true; - return; - } + //sr 4/27 + //origRotation = rotate_model_transform.localRotation; } - else + else if (translate_model_transform != null) { - if (servo_groups.Count > 1) - { - GUILayout.Space(60); - } + //sr 4/27 + //origTranslation = translate_model_transform.localPosition; } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - - GUILayout.Space(20); - - GUILayout.BeginVertical(); - - GUILayout.BeginHorizontal(); - GUILayout.Label("Servo Name", expand); - - GUILayout.Label("Rotate", width40); - - if (servo_groups.Count > 1) + if (translateJoint) { - GUILayout.Label("Group", width40); + //sr 4/27 + //origTranslation = part.transform.localPosition; } - GUILayout.EndHorizontal(); - foreach (var servo in grp.servos) + if (rotateJoint || translateJoint) { - if (!servo.freeMoving) + if (part.attachJoint != null) { - GUILayout.BeginHorizontal(); - - if (GUILayout.Button("[]", GUILayout.Width(30))) + // Catch reversed joint + // Maybe there is a best way to do it? + if (transform.position != part.attachJoint.Joint.connectedBody.transform.position) { - tmpMin = servo.minTweak.ToString(); - tmpMax = servo.maxTweak.ToString(); - servoTweak = servo; - guiTweakEnabled = true; + joint = part.attachJoint.Joint.connectedBody.gameObject.AddComponent(); + joint.connectedBody = part.attachJoint.Joint.rigidbody; } - - servo.servoName = GUILayout.TextField(servo.servoName, - expand); - servo.groupName = grp.name; - servo.reverseKey = grp.reverseKey; - servo.forwardKey = grp.forwardKey; - servo.refreshKeys(); - if (editorWinPos.Contains(mousePos)) + else { - var last = GUILayoutUtility.GetLastRect(); - var pos = Event.current.mousePosition; - bool highlight = last.Contains(pos); - servo.part.SetHighlight(highlight); + joint = part.attachJoint.Joint.rigidbody.gameObject.AddComponent(); + joint.connectedBody = part.attachJoint.Joint.connectedBody; } - if (GUILayout.Button("<", width20)) - { - servo.transform.Rotate(0, 45f, 0, Space.Self); - - } - if (GUILayout.Button(">", width20)) + joint.breakForce = 1e15f; + joint.breakTorque = 1e15f; + // And to default joint + part.attachJoint.Joint.breakForce = 1e15f; + part.attachJoint.Joint.breakTorque = 1e15f; + part.attachJoint.SetBreakingForces(1e15f, 1e15f); + + // lock all movement by default + joint.xMotion = ConfigurableJointMotion.Locked; + joint.yMotion = ConfigurableJointMotion.Locked; + joint.zMotion = ConfigurableJointMotion.Locked; + joint.angularXMotion = ConfigurableJointMotion.Locked; + joint.angularYMotion = ConfigurableJointMotion.Locked; + joint.angularZMotion = ConfigurableJointMotion.Locked; + + joint.projectionDistance = 0f; + joint.projectionAngle = 0f; + joint.projectionMode = JointProjectionMode.PositionAndRotation; + + // Copy drives + joint.linearLimit = part.attachJoint.Joint.linearLimit; + joint.lowAngularXLimit = part.attachJoint.Joint.lowAngularXLimit; + joint.highAngularXLimit = part.attachJoint.Joint.highAngularXLimit; + joint.angularXDrive = part.attachJoint.Joint.angularXDrive; + joint.angularYZDrive = part.attachJoint.Joint.angularYZDrive; + joint.xDrive = part.attachJoint.Joint.xDrive; + joint.yDrive = part.attachJoint.Joint.yDrive; + joint.zDrive = part.attachJoint.Joint.zDrive; + + // Set anchor position + joint.anchor = joint.rigidbody.transform.InverseTransformPoint(joint.connectedBody.transform.position); + joint.connectedAnchor = Vector3.zero; + + // Set correct axis + joint.axis = joint.rigidbody.transform.InverseTransformDirection(joint.connectedBody.transform.right); + joint.secondaryAxis = joint.rigidbody.transform.InverseTransformDirection(joint.connectedBody.transform.up); + + + if (translateJoint) { - servo.transform.Rotate(0, -45f, 0, Space.Self); + joint.xMotion = ConfigurableJointMotion.Free; + joint.yMotion = ConfigurableJointMotion.Free; + joint.zMotion = ConfigurableJointMotion.Free; } - if (servo_groups.Count > 1) + if (rotateJoint) { - if (i > 0) + //Docking washer is broken currently? + joint.rotationDriveMode = RotationDriveMode.XYAndZ; + joint.angularXMotion = ConfigurableJointMotion.Free; + joint.angularYMotion = ConfigurableJointMotion.Free; + joint.angularZMotion = ConfigurableJointMotion.Free; + + // Docking washer test + if (jointSpring > 0) { - if (GUILayout.Button("/\\", width20)) + if (rotateAxis == Vector3.right || rotateAxis == Vector3.left) { - move_servo(grp, servo_groups[i - 1], servo); + JointDrive drv = joint.angularXDrive; + drv.positionSpring = jointSpring; + joint.angularXDrive = drv; + + joint.angularYMotion = ConfigurableJointMotion.Locked; + joint.angularZMotion = ConfigurableJointMotion.Locked; } - } - else - { - GUILayout.Space(20); - } - if (i < (servo_groups.Count - 1)) - { - if (GUILayout.Button("\\/", width20)) + else { - move_servo(grp, servo_groups[i + 1], servo); + JointDrive drv = joint.angularYZDrive; + drv.positionSpring = jointSpring; + joint.angularYZDrive = drv; + + joint.angularXMotion = ConfigurableJointMotion.Locked; + joint.angularZMotion = ConfigurableJointMotion.Locked; } } - else - { - GUILayout.Space(20); - } } - GUILayout.EndHorizontal(); + + // Reset default joint drives + JointDrive resetDrv = new JointDrive(); + resetDrv.mode = JointDriveMode.PositionAndVelocity; + resetDrv.positionSpring = 0; + resetDrv.positionDamper = 0; + resetDrv.maximumForce = 0; + + part.attachJoint.Joint.angularXDrive = resetDrv; + part.attachJoint.Joint.angularYZDrive = resetDrv; + part.attachJoint.Joint.xDrive = resetDrv; + part.attachJoint.Joint.yDrive = resetDrv; + part.attachJoint.Joint.zDrive = resetDrv; + + gotOrig = true; + return true; } } - - GUILayout.EndVertical(); - - GUILayout.EndHorizontal(); + else + { + gotOrig = true; + return true; + } } + return false; + } - if (GUILayout.Button("Add new Group")) + public override void OnActive() + { + if (onActivate) { - Group temp = new Group(); - temp.name = "New Group" + (servo_groups.Count + 1).ToString(); - servo_groups.Add(temp); + on = true; + updateState(); } + } + /* + protected override void onJointDisable() + { + rotationDelta = rotationLast = rotation; + translationDelta = translation; + gotOrig = false; + } + */ + protected void updateRotation(float speed, bool reverse, int mask) + { + speed *= (speedTweak + speedTweakFine) * customSpeed * (reverse ? -1 : 1); + rotation += getAxisInversion() * TimeWarp.fixedDeltaTime * speed; + rotationChanged |= mask; + playAudio(); + } - GUILayout.EndVertical(); - - GUILayout.EndScrollView(); + protected void updateTranslation(float speed, bool reverse, int mask) + { + speed *= (speedTweak + speedTweakFine) * customSpeed * (reverse ? -1 : 1); + translation += getAxisInversion() * TimeWarp.fixedDeltaTime * speed; + translationChanged |= mask; + playAudio(); + } - GUI.DragWindow(); + protected bool keyPressed(string key) + { + return (key != "" && vessel == FlightGlobals.ActiveVessel + && InputLockManager.IsUnlocked(ControlTypes.LINEAR) + && Input.GetKey(key)); } - void GroupEditorWindow(int windowID) + protected float HomeSpeed(float offset, float maxSpeed) { - var expand = GUILayout.ExpandWidth(true); - var width20 = GUILayout.Width(20); - var width40 = GUILayout.Width(40); - var width60 = GUILayout.Width(60); - var maxHeight = GUILayout.MaxHeight(Screen.height / 2); + float speed = Math.Abs(offset) / TimeWarp.deltaTime; + if (speed > maxSpeed) + { + speed = maxSpeed; + } + return -speed * Mathf.Sign(offset) * getAxisInversion(); + } - Vector2 mousePos = Input.mousePosition; - mousePos.y = Screen.height - mousePos.y; - editorScroll = GUILayout.BeginScrollView(editorScroll, false, - false, maxHeight); + protected void checkInputs() + { + if (part.isConnected && keyPressed(onKey)) + { + on = !on; + updateState(); + } - GUILayout.BeginVertical(); - if (ToolbarManager.ToolbarAvailable) + if (on && (onRotateSpeed != 0)) { - if (GUILayout.Button("Close")) - { - saveConfigXML(); - groupEditorEnabled = false; - } + updateRotation(+onRotateSpeed, reversedRotationOn, 1); + } + if (on && (onTranslateSpeed != 0)) + { + updateTranslation(+onTranslateSpeed, reversedTranslationOn, 1); } - GUILayout.BeginHorizontal(); - GUILayout.Label("Group Name", expand); - GUILayout.Label("Keys", width40); - if (servo_groups.Count > 1) + if ((moveFlags & 0x101) != 0 || keyPressed(rotateKey)) + { + updateRotation(+keyRotateSpeed, reversedRotationKey, 2); + } + if ((moveFlags & 0x202) != 0 || keyPressed(revRotateKey)) { - GUILayout.Space(60); + updateRotation(-keyRotateSpeed, reversedRotationKey, 2); + } + //FIXME Hmm, these moveFlag checks clash with rotation. Is rotation and translation in the same part not intended? + if ((moveFlags & 0x101) != 0 || keyPressed(translateKey)) + { + updateTranslation(+keyTranslateSpeed, reversedTranslationKey, 2); + } + if ((moveFlags & 0x202) != 0 || keyPressed(revTranslateKey)) + { + updateTranslation(-keyTranslateSpeed, reversedTranslationKey, 2); } - GUILayout.EndHorizontal(); - for (int i = 0; i < servo_groups.Count; i++) + if (((moveFlags & 0x404) != 0) && (rotationChanged == 0) && (translationChanged == 0)) { - Group grp = servo_groups[i]; + float speed; + speed = HomeSpeed(rotation, keyRotateSpeed); + updateRotation(speed, false, 2); + speed = HomeSpeed(translation, keyTranslateSpeed); + updateTranslation(speed, false, 2); + } - GUILayout.BeginHorizontal(); - string tmp = GUILayout.TextField(grp.name, expand); + if (moveFlags == 0 && !on && fxSndMotor.audio != null) + { + fxSndMotor.audio.Stop(); + isPlaying = false; + } + } - if (grp.name != tmp) + protected void checkRotationLimits() + { + if (rotateLimits || limitTweakableFlag) + { + + if (rotation < minTweak || rotation > maxTweak) { - grp.name = tmp; + rotation = Mathf.Clamp(rotation, minTweak, maxTweak); + if (rotateLimitsRevertOn && ((rotationChanged & 1) > 0)) + { + reversedRotationOn = !reversedRotationOn; + } + if (rotateLimitsRevertKey && ((rotationChanged & 2) > 0)) + { + reversedRotationKey = !reversedRotationKey; + } + if (rotateLimitsOff) + { + on = false; + updateState(); + } } - - tmp = GUILayout.TextField(grp.forwardKey, width20); - if (grp.forwardKey != tmp) + } + else + { + if (rotation >= 180) { - grp.forwardKey = tmp; + rotation -= 360; + rotationDelta -= 360; } - tmp = GUILayout.TextField(grp.reverseKey, width20); - if (grp.reverseKey != tmp) + if (rotation < -180) { - grp.reverseKey = tmp; + rotation += 360; + rotationDelta += 360; } + } + } - if (i > 0) + protected void checkTranslationLimits() + { + if (translateLimits) + { + if (translation < minTweak || translation > maxTweak) { - if (GUILayout.Button("Remove", width60)) + translation = Mathf.Clamp(translation, minTweak, maxTweak); + if (translateLimitsRevertOn && ((translationChanged & 1) > 0)) { - foreach (var servo in grp.servos) - { - move_servo(grp, servo_groups[i - 1], servo); - } - servo_groups.RemoveAt(i); - resetWin = true; - return; + reversedTranslationOn = !reversedTranslationOn; } - } - else - { - if (servo_groups.Count > 1) + if (translateLimitsRevertKey && ((translationChanged & 2) > 0)) { - GUILayout.Space(60); + reversedTranslationKey = !reversedTranslationKey; + } + if (translateLimitsOff) + { + on = false; + updateState(); } } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - - GUILayout.Space(20); - - GUILayout.BeginVertical(); - - GUILayout.BeginHorizontal(); - GUILayout.Label("Servo Name", expand); - if (update14to15) - GUILayout.Label("Rotation", expand); + } + } - if (servo_groups.Count > 1) + protected void doRotation() + { + if ((rotationChanged != 0) && (rotateJoint || rotate_model_transform != null)) + { + if (rotateJoint) { - GUILayout.Label("Group", width40); + joint.targetRotation = Quaternion.AngleAxis((invertSymmetry ? ((isSymmMaster() || (part.symmetryCounterparts.Count != 1)) ? 1 : -1) : 1) * (rotation - rotationDelta), rotateAxis); + rotationLast = rotation; } - GUILayout.EndHorizontal(); - - foreach (var servo in grp.servos) + else { - if (!servo.freeMoving) - { - GUILayout.BeginHorizontal(); - - if (GUILayout.Button("[]", GUILayout.Width(30))) - { - tmpMin = servo.minTweak.ToString(); - tmpMax = servo.maxTweak.ToString(); - servoTweak = servo; - guiTweakEnabled = true; - } - - servo.servoName = GUILayout.TextField(servo.servoName, - expand); - //0.14 to 0.15 fix - if (update14to15) - { - string tempRot = GUILayout.TextField(servo.rotation.ToString(), - expand); - servo.rotation = float.Parse(tempRot); - } - //0.14 to 0.15 fix - servo.groupName = grp.name; - servo.reverseKey = grp.reverseKey; - servo.forwardKey = grp.forwardKey; - - if (groupEditorWinPos.Contains(mousePos)) - { - var last = GUILayoutUtility.GetLastRect(); - var pos = Event.current.mousePosition; - bool highlight = last.Contains(pos); - servo.part.SetHighlight(highlight); - } - - if (servo_groups.Count > 1) - { - if (i > 0) - { - if (GUILayout.Button("/\\", width20)) - { - move_servo(grp, servo_groups[i - 1], servo); - } - } - else - { - GUILayout.Space(20); - } - if (i < (servo_groups.Count - 1)) - { - if (GUILayout.Button("\\/", width20)) - { - move_servo(grp, servo_groups[i + 1], servo); - } - } - else - { - GUILayout.Space(20); - } - } - GUILayout.EndHorizontal(); - } + Quaternion curRot = Quaternion.AngleAxis((invertSymmetry ? ((isSymmMaster() || (part.symmetryCounterparts.Count != 1)) ? 1 : -1) : 1) * rotation, rotateAxis); + transform.FindChild("model").FindChild(rotate_model).localRotation = curRot; } - - GUILayout.EndVertical(); - - GUILayout.EndHorizontal(); } + } - if (GUILayout.Button("Add new Group")) + protected void doTranslation() + { + if ((translationChanged != 0) && (translateJoint || translate_model_transform != null)) { - Group temp = new Group(); - temp.name = "New Group" + (servo_groups.Count + 1).ToString(); - servo_groups.Add(temp); + if (translateJoint) + { + joint.targetPosition = -translateAxis * (translation - translationDelta); + } + else + { + joint.targetPosition = origTranslation - translateAxis.normalized * (translation - translationDelta); + } } - - GUILayout.EndVertical(); - - GUILayout.EndScrollView(); - - GUI.DragWindow(); } - string tmpMin = ""; - string tmpMax = ""; - MuMechToggle servoTweak; - void tweakWindow(int windowID) + protected bool actionUIUpdate; + public UIPartActionWindow tweakWindow; + public void resized() { - var expand = GUILayout.ExpandWidth(true); - var width20 = GUILayout.Width(20); - var width40 = GUILayout.Width(40); - var width60 = GUILayout.Width(60); - var maxHeight = GUILayout.MaxHeight(Screen.height / 2); - - Vector2 mousePos = Input.mousePosition; - mousePos.y = Screen.height - mousePos.y; - - - - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(); - GUILayout.EndHorizontal(); - - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(); - GUILayout.Label("Min"); - tmpMin = GUILayout.TextField(tmpMin, width60); - if (servoTweak.rotateJoint) - GUILayout.Label(servoTweak.rotateMin.ToString()); - else if (servoTweak.translateJoint) - GUILayout.Label(servoTweak.translateMin.ToString()); - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(); - GUILayout.Label("Max"); - tmpMax = GUILayout.TextField(tmpMax, width60); - if (servoTweak.rotateJoint) - GUILayout.Label(servoTweak.rotateMax.ToString()); - else if (servoTweak.translateJoint) - GUILayout.Label(servoTweak.translateMax.ToString()); - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Save", GUILayout.Width(50))) + UIPartActionWindow[] actionWindows = MonoBehaviour.FindObjectsOfType(); + if (actionWindows.Length > 0) { - if (HighLogic.LoadedScene != GameScenes.FLIGHT) + foreach (UIPartActionWindow actionWindow in actionWindows) { - if (servoTweak.part.symmetryCounterparts.Count > 1) + if (actionWindow.part == this.part) { - for (int i = 0; i < servoTweak.part.symmetryCounterparts.Count; i++) - { - float.TryParse(tmpMin, out ((MuMechToggle)servoTweak.part.symmetryCounterparts[i].Modules["MuMechToggle"]).minTweak); - float.TryParse(tmpMax, out ((MuMechToggle)servoTweak.part.symmetryCounterparts[i].Modules["MuMechToggle"]).maxTweak); - } + this.tweakWindow = actionWindow; + tweakIsDirty = true; } } - float.TryParse(tmpMin, out servoTweak.minTweak); - float.TryParse(tmpMax, out servoTweak.maxTweak); } - if (GUILayout.Button("Close", GUILayout.Width(50))) + else { - saveConfigXML(); - guiTweakEnabled = false; + this.tweakWindow = null; } - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - GUI.DragWindow(); } - void refreshKeysFromGUI() + public bool tweakIsDirty = false; + public void refreshTweakUI() { - foreach (Group g in servo_groups) + if (HighLogic.LoadedScene == GameScenes.EDITOR || HighLogic.LoadedScene == GameScenes.SPH) { - if (g.servos.Count() > 0) + if (this.tweakWindow != null) { - foreach (MuMechToggle servo in g.servos) + if (translateJoint) { - servo.reverseKey = g.reverseKey; - servo.forwardKey = g.forwardKey; - servo.refreshKeys(); + UI_FloatEdit rangeMinF = (UI_FloatEdit)this.Fields["minTweak"].uiControlEditor; + rangeMinF.minValue = this.translateMin; + rangeMinF.maxValue = this.translateMax; + rangeMinF.incrementSlide = float.Parse(stepIncrement); ; + minTweak = this.translateMin; + UI_FloatEdit rangeMaxF = (UI_FloatEdit)this.Fields["maxTweak"].uiControlEditor; + rangeMaxF.minValue = this.translateMin; + rangeMaxF.maxValue = this.translateMax; + rangeMaxF.incrementSlide = float.Parse(stepIncrement); ; + maxTweak = this.translateMax; + } + else if (rotateJoint) + { + UI_FloatEdit rangeMinF = (UI_FloatEdit)this.Fields["minTweak"].uiControlEditor; + rangeMinF.minValue = this.rotateMin; + rangeMinF.maxValue = this.rotateMax; + rangeMinF.incrementSlide = float.Parse(stepIncrement); ; + minTweak = this.rotateMin; + UI_FloatEdit rangeMaxF = (UI_FloatEdit)this.Fields["maxTweak"].uiControlEditor; + rangeMaxF.minValue = this.rotateMin; + rangeMaxF.maxValue = this.rotateMax; + rangeMaxF.incrementSlide = float.Parse(stepIncrement); ; + maxTweak = this.rotateMax; + } + + if (part.symmetryCounterparts.Count > 1) + { + for (int i = 0; i < part.symmetryCounterparts.Count; i++) + { + ((MuMechToggle)part.symmetryCounterparts[i].Modules["MuMechToggle"]).rotateMin = this.rotateMin; + ((MuMechToggle)part.symmetryCounterparts[i].Modules["MuMechToggle"]).rotateMax = this.rotateMax; + ((MuMechToggle)part.symmetryCounterparts[i].Modules["MuMechToggle"]).stepIncrement = this.stepIncrement; + ((MuMechToggle)part.symmetryCounterparts[i].Modules["MuMechToggle"]).minTweak = this.rotateMin; + ((MuMechToggle)part.symmetryCounterparts[i].Modules["MuMechToggle"]).maxTweak = this.maxTweak; + } } } } - } - - - - bool guiTweakEnabled = false; - void OnGUI() + UI_FloatEdit rangeMinF; + UI_FloatEdit rangeMinE; + UI_FloatEdit rangeMaxF; + UI_FloatEdit rangeMaxE; + public void FixedUpdate() { - // This particular test isn't needed due to the GUI being enabled - // and disabled as appropriate, but it saves potential NREs. - if (servo_groups == null) - return; - if (InputLockManager.IsLocked(ControlTypes.LINEAR)) - return; - if (controlWinPos.x == 0 && controlWinPos.y == 0) + rangeMinF = (UI_FloatEdit)this.Fields["minTweak"].uiControlFlight; + rangeMinE = (UI_FloatEdit)this.Fields["minTweak"].uiControlEditor; + rangeMinE.incrementSlide = float.Parse(stepIncrement); + rangeMinF.incrementSlide = float.Parse(stepIncrement); + rangeMaxF = (UI_FloatEdit)this.Fields["maxTweak"].uiControlFlight; + rangeMaxE = (UI_FloatEdit)this.Fields["maxTweak"].uiControlEditor; + rangeMaxE.incrementSlide = float.Parse(stepIncrement); + rangeMaxF.incrementSlide = float.Parse(stepIncrement); + + if (HighLogic.LoadedScene == GameScenes.SPH || HighLogic.LoadedScene == GameScenes.EDITOR) { - controlWinPos = new Rect(Screen.width - 510, 70, 10, 10); - } - if (editorWinPos.x == 0 && editorWinPos.y == 0) - { - editorWinPos = new Rect(Screen.width - 260, 50, 10, 10); + if (this.tweakWindow != null && tweakIsDirty) + { + refreshTweakUI(); + this.tweakWindow.UpdateWindow(); + tweakIsDirty = false; + } } - - if (groupEditorWinPos.x == 0 && groupEditorWinPos.y == 0) + if (HighLogic.LoadedScene != GameScenes.FLIGHT) + return; + if (isMotionLock || part.State == PartStates.DEAD) { - groupEditorWinPos = new Rect(Screen.width - 260, 50, 10, 10); + return; } - if (tweakWinPos.x == 0 && tweakWinPos.y == 0) + if (setupJoints()) { - tweakWinPos = new Rect(Screen.width - 410, 220, 145, 130); + rotationChanged = 4; + translationChanged = 4; } - if (resetWin) - { - controlWinPos = new Rect(controlWinPos.x, controlWinPos.y, - 10, 10); - editorWinPos = new Rect(editorWinPos.x, editorWinPos.y, - 10, 10); - groupEditorWinPos = new Rect(groupEditorWinPos.x, groupEditorWinPos.y, - 10, 10); + checkInputs(); + checkRotationLimits(); + checkTranslationLimits(); - tweakWinPos = new Rect(tweakWinPos.x, tweakWinPos.y, - 10, 10); - resetWin = false; - } - GUI.skin = MuUtils.DefaultSkin; - var scene = HighLogic.LoadedScene; + doRotation(); + doTranslation(); - if (scene == GameScenes.FLIGHT) - { - var height = GUILayout.Height(Screen.height / 2); - if (guiEnabled) - controlWinPos = GUILayout.Window(956, controlWinPos, - ControlWindow, - "Servo Control", - GUILayout.Width(250), - GUILayout.Height(80)); - if (groupEditorEnabled) - groupEditorWinPos = GUILayout.Window(958, groupEditorWinPos, - GroupEditorWindow, - "Servo Group Editor", - GUILayout.Width(250), - height); - if (guiTweakEnabled) - tweakWinPos = GUILayout.Window(959, tweakWinPos, - tweakWindow, - servoTweak.servoName, - GUILayout.Width(100), - GUILayout.Height(80)); + rotationChanged = 0; + translationChanged = 0; - refreshKeysFromGUI(); - } - else if (scene == GameScenes.EDITOR || scene == GameScenes.SPH) + if (vessel != null) { - var height = GUILayout.Height(Screen.height / 2); - if (guiEnabled) - editorWinPos = GUILayout.Window(957, editorWinPos, - EditorWindow, - "Servo Configuration", - GUILayout.Width(250), - height); - - if (guiTweakEnabled) + part.UpdateOrgPosAndRot(vessel.rootPart); + foreach (Part child in part.FindChildParts(true)) { - tweakWinPos = GUILayout.Window(959, tweakWinPos, - tweakWindow, - servoTweak.servoName, - GUILayout.Width(100), - GUILayout.Height(80)); + child.UpdateOrgPosAndRot(vessel.rootPart); } } + + } + + + + public override void OnInactive() + { + on = false; + updateState(); + } + + public void SetLock(bool locked) + { + isMotionLock = locked; + Events["Activate"].active = !isMotionLock; + Events["Deactivate"].active = isMotionLock; + } + + [KSPEvent(guiActive = true, guiName = "Engage Lock")] + public void Activate() + { + SetLock(true); + } + + [KSPEvent(guiActive = true, guiName = "Disengage Lock", active = false)] + public void Deactivate() + { + SetLock(false); } - public void loadConfigXML() + [KSPAction("Engage Lock")] + public void LockToggle(KSPActionParam param) { - PluginConfiguration config = PluginConfiguration.CreateForType(); - config.load(); - editorWinPos = config.GetValue("editorWinPos"); - tweakWinPos = config.GetValue("tweakWinPos"); - controlWinPos = config.GetValue("controlWinPos"); - groupEditorWinPos = config.GetValue("groupEditorWinPos"); + SetLock(!isMotionLock); + } + [KSPAction("Move +")] + public void MovePlusAction(KSPActionParam param) + { + switch (param.type) + { + case KSPActionType.Activate: + moveFlags |= 0x100; + break; + case KSPActionType.Deactivate: + moveFlags &= ~0x100; + break; + } } - public void saveConfigXML() + [KSPAction("Move -")] + public void MoveMinusAction(KSPActionParam param) { - PluginConfiguration config = PluginConfiguration.CreateForType(); - config.SetValue("editorWinPos", editorWinPos); - config.SetValue("tweakWinPos", tweakWinPos); - config.SetValue("controlWinPos", controlWinPos); - config.SetValue("groupEditorWinPos", groupEditorWinPos); - config.save(); + switch (param.type) + { + case KSPActionType.Activate: + moveFlags |= 0x200; + break; + case KSPActionType.Deactivate: + moveFlags &= ~0x200; + break; + } + } + + [KSPAction("Move Center")] + public void MoveCenterAction(KSPActionParam param) + { + switch (param.type) + { + case KSPActionType.Activate: + moveFlags |= 0x400; + break; + case KSPActionType.Deactivate: + moveFlags &= ~0x400; + break; + } } } }