public void UpdateFairingNodes() { ROLLog.log($"UpdateFairingNodes()"); foreach (ROLNodeFairingData data in fairingParts) { ROLLog.log($"fairingName: {fairingName}"); // Update the Nose Interstage Node if (fairingName == "Top Fairing") { Vector3 pos = new Vector3(0, data.topY, 0); ROLLog.log($"data.topY: {data.topY}"); ROLSelectableNodes.updateNodePosition(part, noseFairingNode, pos); if (part.FindAttachNode(noseFairingNode) is AttachNode noseInterstage) { ROLAttachNodeUtils.updateAttachNodePosition(part, noseInterstage, pos, Vector3.up, true, 2); } } // Update the Mount Interstage Node if (fairingName == "Bottom Fairing") { Vector3 pos = new Vector3(0, data.bottomY, 0); ROLSelectableNodes.updateNodePosition(part, data.mountNode, pos); if (part.FindAttachNode(mountFairingNode) is AttachNode mountInterstage) { ROLAttachNodeUtils.updateAttachNodePosition(part, mountInterstage, pos, Vector3.down, true, 2); } } } }
private void FindAnimations() { Animation[] componentsInChildren = part.transform.ROLFindRecursive("model").GetComponentsInChildren <Animation>(); foreach (Animation a in componentsInChildren) { if (a.GetClip(this.animationName) != null) { ROLLog.debug($"[AnimDebug] Animation: {a}"); this.anim = a; ROLLog.debug($"a.GetClip(this.animationName) this.anim: {this.anim}"); } } if (componentsInChildren.Length > 0 && this.anim == null) { this.anim = componentsInChildren[0]; ROLLog.debug($"componentsInChildren.Length > 0 - this.anim: {this.anim}"); } if (this.anim == null) { this.useAnimation = false; } else { this.useAnimation = true; } }
public void UpdateImpulseValues() { ROLLog.log("UpdateImpulseValues() called"); float nf = (float)Math.Min(100f * Math.Pow(modularPart.currentDiameter, diamExponent), maxImpulse); nf = (float)Math.Round(nf, 0); currentEjectionForce = decouple.ejectionForce = nf; }
private void UpdateAttachNodes(bool userInput) { coreModule.updateAttachNodeBody(coreNodeNames, userInput); AttachNode surfaceNode = part.srfAttachNode; ROLLog.debug($"part.srfAttachNode: {part.srfAttachNode}"); coreModule.updateSurfaceAttachNode(surfaceNode, panelLength, panelWidth, userInput); }
private void UpdateMassAndCost() { lengthWidth = coreModule.definition.lengthWidth; if (!lengthWidth) { ROLLog.debug($"UpdateMassAndCost() lengthWidth false"); area = coreModule.definition.panelArea * panelScale * panelScale; ROLLog.debug($"coreModule.definition.panelArea: {coreModule.definition.panelArea}"); ROLLog.debug($"panelScale: {panelScale}"); ROLLog.debug($"area: {area}"); } else { ROLLog.debug($"UpdateMassAndCost() lengthWidth true"); float lengthScale = panelLength / coreModule.definition.panelLength; float widthScale = panelWidth / coreModule.definition.panelWidth; area = coreModule.definition.panelArea * lengthScale * widthScale; ROLLog.debug($"coreModule.definition.panelArea: {coreModule.definition.panelArea}"); ROLLog.debug($"lengthScale: {lengthScale}"); ROLLog.debug($"widthScale: {widthScale}"); ROLLog.debug($"area: {area}"); } kgPerM2 = stl.kgPerM2; costPerM2 = stl.costPerM2; mass = area * kgPerM2; cost = area * costPerM2; switch (solarPanelType) { case "hinged": mass *= stl.massMultHinged; cost *= stl.costMultHinged; break; case "folded": mass *= stl.massMultFolded; cost *= stl.costMultFolded; break; case "tracking": mass *= stl.massMultTrack; cost *= stl.costMultTrack; break; default: break; } if (addMass > 0) { mass += addMass; } if (addCost > 0) { cost += addCost; } modifiedMass = mass = Math.Max(mass, 0.0001f); modifiedCost = cost = Math.Max(cost, 0.1f); }
/// <summary> /// Updates all dimensions for the PAW and tooling. /// </summary> public void UpdateDimensions() { float mountMaxDiam = currentMount.Contains("Mount") ? mountModule.moduleUpperDiameter : Math.Max(mountModule.moduleLowerDiameter, mountModule.moduleUpperDiameter); float noseMaxDiam = Math.Max(noseModule.moduleLowerDiameter, noseModule.moduleUpperDiameter); totalTankLength = GetTotalHeight(); largestDiameter = Math.Max(currentDiameter, Math.Max(noseMaxDiam, mountMaxDiam)); ROLLog.debug($"UpdateDimensions() currentMount: {currentMount} Largest Diameter: {largestDiameter}. Total Tank length: {totalTankLength}"); }
private bool FindDecoupler() { ROLLog.debug("Finding Decoupler..."); if (decouple == null) { decouple = part.Modules["ModuleDecouple"] as ModuleDecouple; } return(decouple != null); }
public ModelLayoutData getLayout(string name) { ModelLayoutData mld = layouts.ROLFind(m => m.name == name); if (mld == null) { ROLLog.error("ERROR: Could not locate layout for name: " + name); } return(mld); }
public readonly float gimbalFlightRange; //how far the gimbal may be actuated while in flight from the adjusted reference angle public ModelEngineTransformData(ConfigNode node) { thrustTransformName = node.ROLGetStringValue("thrustTransform"); if (string.IsNullOrEmpty(thrustTransformName)) { ROLLog.error("ERROR: THrust transform name was null for model def engine transform data"); } gimbalTransformName = node.ROLGetStringValue("gimbalTransform"); gimbalAdjustmentRange = node.ROLGetFloatValue("gimbalAdjustRange", 0); gimbalFlightRange = node.ROLGetFloatValue("gimbalFlightRange", 0); }
public override void OnLoad(ConfigNode node) { base.OnLoad(node); if (string.IsNullOrEmpty(configNodeData)) { ROLLog.debug($"{modName}: OnLoad loading configNodeData"); configNodeData = node.ToString(); ROLLog.debug($"{modName}: OnLoad() configNodeData: {configNodeData}"); } ROLLog.debug($"{modName}: OnLoad calling Initialize()"); Initialize(); }
public void SetCurrentDiameter(float f) { float oldDiameter = module.currentDiameter; module.currentDiameter = f; BaseField fld = module.Fields[nameof(module.currentDiameter)]; fld.uiControlEditor.onFieldChanged.Invoke(fld, oldDiameter); MonoUtilities.RefreshContextWindows(module.part); ROLLog.log("ModuleROTank - Diameter set to: " + f); }
private void SetupUICallbacks() { ROLLog.debug("Setting up UICallbacks..."); if (FindModularPart() is ModuleROTank p) { ROLLog.debug("p: " + p); ROLLog.debug("p.Fields[nameof(p.currentDiameter): " + p.Fields[nameof(p.currentDiameter)]); ROLLog.debug("p.Fields: " + p.Fields); UI_FloatEdit mp = p.Fields[nameof(p.currentDiameter)].uiControlEditor as UI_FloatEdit; mp.onFieldChanged += new Callback <BaseField, object>(OnDiameterChange); } }
public ModelDefinitionLayoutOptions(ROLModelDefinition def) { definition = def; if (definition == null) { ROLLog.error("Model definition was null when creating model layout options!"); } layouts = ROLModelLayout.findLayouts(new string[] { "default" }); if (this.layouts == null || this.layouts.Length < 1) { throw new InvalidOperationException("ERROR: No valid layout data specified."); } }
public static void Init(ConfigNode config) { ROLLog.debug($"{modTag}: Init() Started"); allTL.Clear(); foreach (ConfigNode node in config.GetNodes("ROS_TECH")) { SolarTechLimit obj = ConfigNode.CreateObjectFromConfig <SolarTechLimit>(node); ROLLog.debug($"{modTag}: Adding ROSTL {obj}"); allTL.Add(obj.level, obj); maxTL = Math.Max(maxTL, obj.level); } isInitialized = true; }
public ModelDefinitionLayoutOptions(ROLModelDefinition def, ModelLayoutData[] layouts) { this.definition = def; if (definition == null) { ROLLog.error("Model definition was null when creating model layout options!"); } this.layouts = layouts; if (this.layouts == null || this.layouts.Length < 1) { throw new InvalidOperationException("ERROR: No valid layout data specified."); } }
/// <summary> /// Create a group of model definition layout sets. Loads the model definitions + their supported layout configurations. /// </summary> /// <param name="nodes"></param> /// <returns></returns> public static ModelDefinitionLayoutOptions[] getModelDefinitions(ConfigNode[] nodes) { int len = nodes.Length; List <ModelDefinitionLayoutOptions> options = new List <ModelDefinitionLayoutOptions>(); List <ModelLayoutData> layoutDataList = new List <ModelLayoutData>(); ROLModelDefinition def; string[] groupedNames; string[] groupedLayouts; int len2; for (int i = 0; i < len; i++) { //because configNode.ToString() reverses the order of values, and model def layouts are always loaded from string-cached config nodes //we need to reverse the order of the model and layout names during parsing groupedNames = nodes[i].ROLGetStringValues("model"); groupedLayouts = nodes[i].ROLGetStringValues("layout", new string[] { "default" }); len2 = groupedNames.Length; for (int k = 0; k < len2; k++) { def = ROLModelData.getModelDefinition(groupedNames[k]); layoutDataList.AddRange(ROLModelLayout.findLayouts(groupedLayouts)); if (nodes[i].HasValue("position") || nodes[i].HasValue("rotation") || nodes[i].HasValue("scale")) { Vector3 pos = nodes[i].ROLGetVector3("position", Vector3.zero); Vector3 scale = nodes[i].ROLGetVector3("scale", Vector3.one); Vector3 rot = nodes[i].ROLGetVector3("rotation", Vector3.zero); ModelPositionData mpd = new ModelPositionData(pos, scale, rot); ModelLayoutData custom = new ModelLayoutData("default", new ModelPositionData[] { mpd }); if (layoutDataList.Exists(m => m.name == "default")) { ModelLayoutData del = layoutDataList.Find(m => m.name == "default"); layoutDataList.Remove(del); } layoutDataList.Add(custom); } if (def == null) { ROLLog.error("Model definition was null for name: " + groupedNames[k] + ". Skipping definition during loading of part"); } else { options.Add(new ModelDefinitionLayoutOptions(def, layoutDataList.ToArray())); } layoutDataList.Clear(); } } return(options.ToArray()); }
public static ModelLayoutData findLayout(string name) { if (!loaded) { load(); } ModelLayoutData mld; if (!layouts.TryGetValue(name, out mld)) { ROLLog.error("Could not find layout by name: " + name); } return(mld); }
public static void load() { ROLLog.log("Loading Model Layouts"); layouts.Clear(); ConfigNode[] layoutNodes = GameDatabase.Instance.GetConfigNodes("ROL_MODEL_LAYOUT"); int len = layoutNodes.Length; for (int i = 0; i < len; i++) { ModelLayoutData mld = new ModelLayoutData(layoutNodes[i]); layouts.Add(mld.name, mld); } loaded = true; ROLLog.log("Finished loading Model Layouts"); }
public override void OnStart(StartState state) { base.OnStart(state); if (!FindDecoupler()) { ROLLog.error("Unable to find any Decoupler modules"); isEnabled = enabled = false; return; } if (HighLogic.LoadedSceneIsFlight) { decouple.isOmniDecoupler = isOmniDecoupler; } }
/// <summary> /// Return the total height of this part in its current configuration. This will be the distance from the bottom attach node to the top attach node, and may not include any 'extra' structure. TOOLING /// </summary> /// <returns></returns> private float getTotalHeight() { float totalHeight = noseModule.moduleHeight; totalHeight += mountModule.moduleHeight; if (currentCore.Contains("Booster")) { ROLLog.debug("currentCore: " + currentCore); totalHeight += coreModule.moduleActualHeight; } else { totalHeight += coreModule.moduleHeight; } return(totalHeight); }
public void toggleNode() { AttachNode node = part.FindAttachNode(nodeName); ROLLog.debug("toggleNode() node: " + node); if (node == null) { currentlyEnabled = true; ROLAttachNodeUtils.createAttachNode(part, nodeName, nodeDefaultPosition, nodeDefaultOrientation, 2); } else if (node.attachedPart == null) { currentlyEnabled = false; ROLAttachNodeUtils.destroyAttachNode(part, node); } }
public static Vector3 ROLGetVector3(this ConfigNode node, String name, Vector3 defaultValue) { String value = node.GetValue(name); if (value == null) { return(defaultValue); } String[] vals = value.Split(','); if (vals.Length < 3) { ROLLog.error("ERROR parsing values for Vector3 from input: " + value + ". found less than 3 values, cannot create Vector3"); return(defaultValue); } return(new Vector3((float)ROLUtils.safeParseDouble(vals[0]), (float)ROLUtils.safeParseDouble(vals[1]), (float)ROLUtils.safeParseDouble(vals[2]))); }
private void WindowPre(int uid) { try { InputLockManager.RemoveControlLock("ROLWindowLock"); /* Block clicks through window onto ship or other editor UI */ if (this.backupPosition.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y))) { InputLockManager.SetControlLock(ControlTypes.EDITOR_LOCK, "ROLWindowLock"); } Window(uid); } catch (Exception e) { ROLLog.exc(e); } }
public override void OnStart(StartState state) { ROLLog.debug($"OnStart(state)"); base.OnStart(state); ROLLog.debug($"this.anim: {this.anim}"); ROLLog.debug("Anim loop"); foreach (Animation a in this.GetComponentsInChildren <Animation>()) { ROLLog.debug($"[AnimDebug] Animation: {a}"); } ROLLog.debug("Anim loop done"); SetMaxTechLevel(); ROLLog.debug($"{modName} OnStart calling Initialize()"); Initialize(); ROLLog.debug($"{modName} OnStart calling InitializeUI()"); InitializeUI(); }
/// <summary> /// Update the scale and position values for all currently configured models. Does no validation, only updates positions.<para/> /// After calling this method, all models will be scaled and positioned according to their internal position/scale values and the orientations/offsets defined in the models. /// </summary> public void updateModulePositions() { ROLLog.debug($"UpdateModulePositions()"); //scales for modules depend on the module above/below them //first set the scale for the core module -- this depends directly on the UI specified 'diameter' value. if (lengthWidth) { debug($"UpdateModulePositions(): setScaleForHeightAndDiameter"); coreModule.setScaleForHeightAndDiameter(currentLength, currentDiameter); } else { debug($"UpdateModulePositions(): setScaleForDiameter"); coreModule.setScaleForDiameter(currentDiameter, currentVScale); } ROLLog.debug($"UpdateModulePositions(): currentDiameter: {currentDiameter}, currentVScale: {currentVScale}"); //next, set nose scale values noseModule.setDiameterFromBelow(coreModule.moduleUpperDiameter, currentVScale); //finally, set mount scale values mountModule.setDiameterFromAbove(coreModule.moduleLowerDiameter, currentVScale); //total height of the part is determined by the sum of the heights of the modules at their current scale float totalHeight = noseModule.moduleHeight; totalHeight += coreModule.moduleHeight; totalHeight += mountModule.moduleHeight; //position of each module is set such that the vertical center of the models is at part origin/COM float pos = totalHeight * 0.5f; //abs top of model pos -= noseModule.moduleHeight; //bottom of nose model noseModule.setPosition(pos); pos -= coreModule.moduleHeight * 0.5f; //center of 'core' model coreModule.setPosition(pos); pos -= coreModule.moduleHeight * 0.5f; //bottom of 'core' model mountModule.setPosition(pos); //update actual model positions and scales noseModule.updateModelMeshes(); coreModule.updateModelMeshes(); mountModule.updateModelMeshes(); }
/// <summary> /// Create a group of model definition layout options by model definition name, with default (single position) layouts. /// </summary> /// <param name="names"></param> /// <returns></returns> public static ModelDefinitionLayoutOptions[] getModelDefinitionLayouts(string[] names) { List <ModelDefinitionLayoutOptions> defs = new List <ModelDefinitionLayoutOptions>(); int len = names.Length; for (int i = 0; i < len; i++) { ROLModelDefinition def = getModelDefinition(names[i]); if (def != null) { defs.Add(new ModelDefinitionLayoutOptions(def)); } else { ROLLog.error("Could not locate model defintion for name: " + names[i]); } } return(defs.ToArray()); }
public static T ROLFind <T>(this T[] array, Func <T, bool> predicate) { int len = array.Length; for (int i = 0; i < len; i++) { if (array[i] == null) { ROLLog.error("ERROR: Null value in array in Find method, at index: " + i); } if (predicate(array[i])) { return(array[i]); } } //return default in order to properly handle value types (structs) //should return either null for reference types or default value for structs return(default(T)); }
public override void OnStartFinished(StartState state) { base.OnStartFinished(state); ROLLog.debug("OnStartFinished()..."); if (!FindModularPart()) { ROLLog.error("Unable to find any Modular Part modules"); isEnabled = enabled = false; return; } SetupUICallbacks(); if (HighLogic.LoadedSceneIsEditor) { UpdateImpulseValues(); } }
public void SetCurrentDiameter(float f) { module.currentDiameter = f; module.updateModulePositions(); module.updateDimensions(); module.updateAttachNodes(true); module.updateAvailableVariants(); if (module.scaleMass) { module.updateMass(); } if (module.scaleCost) { module.updateCost(); } UpdatePartActionWindow(); ROLLog.log("ModuleROTank - Diameter set to: " + f); }
/// <summary> /// Updates all dimensions for the PAW and tooling. /// </summary> public void updateDimensions() { float noseMaxDiam, mountMaxDiam = 0.0f; noseMaxDiam = Math.Max(noseModule.moduleLowerDiameter, noseModule.moduleUpperDiameter); ROLLog.debug("currentMount: " + currentMount); if (currentMount.Contains("Mount")) { ROLLog.debug("currentMount: " + currentMount); mountMaxDiam = mountModule.moduleUpperDiameter; } else { mountMaxDiam = Math.Max(mountModule.moduleLowerDiameter, mountModule.moduleUpperDiameter); } totalTankLength = getTotalHeight(); ROLLog.debug("The Total Tank Length is: " + totalTankLength); largestDiameter = Math.Max(currentDiameter, Math.Max(noseMaxDiam, mountMaxDiam)); }