public ModelGUISelection(ModelData data, float size) { modelName = data.name; description = data.modelDefinition.title + " - " + data.modelDefinition.description; float m = data.mass; float c = data.cost; float v = data.volume; float scale = size / data.modelDefinition.diameter == 0 ? 1 : data.modelDefinition.diameter; float pow = Mathf.Pow(scale, 3); m *= pow; c *= pow; v *= pow; string suffix; suffix = m < 1 ? "kg" : m < 1000 ? "t" : "kt"; m = m < 1 ? m * 1000 : m < 1000 ? m : m * 0.001f; mass = m.ToString("N1")+suffix; suffix = c < 1000 ? "" : "k"; c = c > 1000 ? c * 0.001f : c; cost = c.ToString("N1")+suffix; suffix = v < 1 ? "l" : v < 1000 ? "kl" : "Ml"; v = v < 1 ? v * 1000 : v < 1000 ? v : v * 0.001f; volume = v.ToString("N1")+suffix; if (String.IsNullOrEmpty(data.modelDefinition.icon) || (texture = GameDatabase.Instance.GetTexture(data.modelDefinition.icon, false))==null) { //TODO do textures need to be destroyed when no longer in use? Can call unity asset-cleanup on GUI close? texture = GameDatabase.Instance.GetTexture("Squad/PartList/SimpleIcons/RDicon_propulsionSystems", false); } }
public static ModelGUISelection[] createFromModelData(ModelData[] data, float diameter) { int len = data.Length; ModelGUISelection[] selections = new ModelGUISelection[len]; for (int i = 0; i < len; i++) { selections[i] = new ModelGUISelection(data[i], diameter); } return selections; }
private void initialize() { if (initialized) { return; } initialized = true; ConfigNode node = SSTUConfigNodeUtils.parseConfigNode(configNodeData); Transform root = part.transform.FindRecursive("model").FindOrCreate(rootTransformName); models = new ModelModule <PositionedModelData, SSTUModelSwitch2>(part, this, root, ModelOrientation.TOP, nameof(modelPersistentData), nameof(currentModel), nameof(currentTexture)); models.getSymmetryModule = m => m.models; models.setupModelList(ModelData.parseModels <PositionedModelData>(node.GetNodes("MODEL"), m => new PositionedModelData(m))); models.setupModel(); models.model.updateScale(currentScale); models.updateModel(); updateMassAndCost(); updateAttachNodes(false); }
public ModelGUISelection(ModelData data, float size) { modelName = data.name; description = data.modelDefinition.title + " - " + data.modelDefinition.description; float m = data.mass; float c = data.cost; float v = data.volume; float scale = size / data.modelDefinition.diameter == 0 ? 1 : data.modelDefinition.diameter; float pow = Mathf.Pow(scale, 3); m *= pow; c *= pow; v *= pow; string suffix; suffix = m < 1 ? "kg" : m < 1000 ? "t" : "kt"; m = m < 1 ? m * 1000 : m < 1000 ? m : m * 0.001f; mass = m.ToString("N1") + suffix; suffix = c < 1000 ? "" : "k"; c = c > 1000 ? c * 0.001f : c; cost = c.ToString("N1") + suffix; suffix = v < 1 ? "l" : v < 1000 ? "kl" : "Ml"; v = v < 1 ? v * 1000 : v < 1000 ? v : v * 0.001f; volume = v.ToString("N1") + suffix; if (String.IsNullOrEmpty(data.modelDefinition.icon) || (texture = GameDatabase.Instance.GetTexture(data.modelDefinition.icon, false)) == null) { //TODO do textures need to be destroyed when no longer in use? Can call unity asset-cleanup on GUI close? texture = GameDatabase.Instance.GetTexture("Squad/PartList/SimpleIcons/RDicon_propulsionSystems", false); } }
/// <summary> /// Finds the model for the given part, if it currently exists; else it clones it /// </summary> /// <param name="model"></param> /// <returns></returns> private void setupModel(ModelData model, Transform parent, ModelOrientation orientation) { model.setupModel(part, parent, orientation); }
/// <summary> /// Removes the current model of the passed in upper-stage part; used when switching mounts or intertank parts /// </summary> /// <param name="usPart"></param> private void removeCurrentModel(ModelData usPart) { usPart.destroyCurrentModel(); }
/// <summary> /// Restores ModelData instances from config node data, and populates the 'currentModule' instances with the currently enabled modules. /// </summary> private void loadConfigData() { ConfigNode node = SSTUConfigNodeUtils.parseConfigNode(configNodeData); ConfigNode[] tankSetsNodes = node.GetNodes("TANKSET"); ConfigNode[] tankNodes = node.GetNodes("TANK"); ConfigNode[] mountNodes = node.GetNodes("CAP"); ConfigNode[] limitNodes = node.GetNodes("TECHLIMIT"); tankSets = TankSet.parseSets(tankSetsNodes); //if no sets exist, initialize a default set to add all models to if (tankSets.Length == 0) { tankSets = new TankSet[1]; ConfigNode defaultSetNode = new ConfigNode("TANKSET"); defaultSetNode.AddValue("name", "default"); tankSets[0] = new TankSet(defaultSetNode); } mainTankModules = ModelData.parseModels <TankModelData>(tankNodes, m => new TankModelData(m)); int len = mainTankModules.Length; TankSet set; for (int i = 0; i < len; i++) { set = Array.Find(tankSets, m => m.name == mainTankModules[i].setName); //if set is not found by name, add it to the first set which is guaranteed to exist due to the default-set-adding code above. if (set == null) { set = tankSets[0]; } set.addModel(mainTankModules[i]); } len = mountNodes.Length; ConfigNode mountNode; List <SingleModelData> noses = new List <SingleModelData>(); List <SingleModelData> mounts = new List <SingleModelData>(); for (int i = 0; i < len; i++) { mountNode = mountNodes[i]; if (mountNode.GetBoolValue("useForNose", true)) { mountNode.SetValue("nose", "true"); noses.Add(new SingleModelData(mountNode)); } if (mountNode.GetBoolValue("useForMount", true)) { mountNode.SetValue("nose", "false"); mounts.Add(new SingleModelData(mountNode)); } } mountModules = mounts.ToArray(); noseModules = noses.ToArray(); topNodeNames = SSTUUtils.parseCSV(topManagedNodeNames); bottomNodeNames = SSTUUtils.parseCSV(bottomManagedNodeNames); currentMainTankModule = Array.Find(mainTankModules, m => m.name == currentTankType); if (currentMainTankModule == null) { MonoBehaviour.print("ERROR: Could not locate tank type for: " + currentTankType + ". reverting to first available tank type."); currentMainTankModule = mainTankModules[0]; currentTankType = currentMainTankModule.name; } currentTankSetModule = Array.Find(tankSets, m => m.name == currentMainTankModule.setName); currentTankSet = currentTankSetModule.name; lastSelectedVariant = currentMainTankModule.variantName; currentNoseModule = Array.Find(noseModules, m => m.name == currentNoseType); if (currentNoseModule == null) { MonoBehaviour.print("ERROR: Could not locate nose type for: " + currentNoseType + ". reverting to first available nose type."); currentNoseModule = noseModules[0]; currentNoseType = currentNoseModule.name; } currentMountModule = Array.Find(mountModules, m => m.name == currentMountType); if (currentMountModule == null) { MonoBehaviour.print("ERROR: Could not locate mount type for: " + currentMountType + ". reverting to first available mount type."); currentMountModule = mountModules[0]; currentMountType = currentMountModule.name; } if (!currentMainTankModule.isValidTextureSet(currentTankTexture)) { currentTankTexture = currentMainTankModule.getDefaultTextureSet(); } if (!currentNoseModule.isValidTextureSet(currentNoseTexture)) { currentNoseTexture = currentNoseModule.getDefaultTextureSet(); } if (!currentMountModule.isValidTextureSet(currentMountTexture)) { currentMountTexture = currentMountModule.getDefaultTextureSet(); } }
public void selectMountEvent() { ModuleSelectionGUI.openGUI(ModelData.getValidSelections(part, mountModules, bottomNodeNames), currentTankDiameter, setMountModuleFromEditor); }
public void selectNoseEvent() { ModuleSelectionGUI.openGUI(ModelData.getValidSelections(part, noseModules, topNodeNames), currentTankDiameter, setNoseModuleFromEditor); }
private void initialize(bool start) { if (initialized) { return; } initialized = true; topNodeNames = SSTUUtils.parseCSV(topManagedNodes); bottomNodeNames = SSTUUtils.parseCSV(bottomManagedNodes); ConfigNode node = SSTUConfigNodeUtils.parseConfigNode(configNodeData); coreModule = new ModelModule <ServiceModuleCoreModel, SSTUModularServiceModule>(part, this, getRootTransform("MSC-CORE", true), ModelOrientation.TOP, nameof(coreModulePersistentData), nameof(currentCore), nameof(currentCoreTexture)); coreModule.getSymmetryModule = m => m.coreModule; coreModule.setupModelList(ModelData.parseModels(node.GetNodes("CORE"), m => new ServiceModuleCoreModel(m))); topModule = new ModelModule <SingleModelData, SSTUModularServiceModule>(part, this, getRootTransform("MSC-TOP", true), ModelOrientation.TOP, nameof(topModulePersistentData), nameof(currentTop), nameof(currentTopTexture)); topModule.getSymmetryModule = m => m.topModule; topModule.getValidSelections = m => topModule.models.FindAll(s => s.canSwitchTo(part, topNodeNames)); bottomModule = new ModelModule <SingleModelData, SSTUModularServiceModule>(part, this, getRootTransform("MSC-BOTTOM", true), ModelOrientation.BOTTOM, nameof(bottomModulePersistentData), nameof(currentBottom), nameof(currentBottomTexture)); bottomModule.getSymmetryModule = m => m.bottomModule; bottomModule.getValidSelections = m => bottomModule.models.FindAll(s => s.canSwitchTo(part, bottomNodeNames)); solarModule = new ModelModule <SolarData, SSTUModularServiceModule>(part, this, getRootTransform("MSC-Solar", true), ModelOrientation.CENTRAL, null, nameof(currentSolar), null); solarModule.getSymmetryModule = m => m.solarModule; solarModule.setupModelList(ModelData.parseModels(node.GetNodes("SOLAR"), m => new SolarData(m))); solarModule.getValidSelections = delegate(IEnumerable <SolarData> all) { //System.Linq.Enumerable.Where(all, s => s.isAvailable(upgradesApplied)); float scale = coreModule.model.currentDiameterScale; //find all solar panels that are unlocked via upgrades/tech-tree List <SolarData> unlocked = solarModule.models.FindAll(s => s.isAvailable(upgradesApplied)); //filter those to find only the ones available for the current List <SolarData> availableByScale = unlocked.FindAll(s => coreModule.model.isValidSolarOption(s.name, scale)); return(availableByScale); }; solarModule.preModelSetup = delegate(SolarData d) { d.positions = coreModule.model.getPanelConfiguration(d.name).getScaledPositions(coreModule.model.currentDiameterScale); }; rcsModule = new ModelModule <ServiceModuleRCSModelData, SSTUModularServiceModule>(part, this, getRootTransform("MSC-Rcs", true), ModelOrientation.CENTRAL, null, nameof(currentRCS), null); rcsModule.getSymmetryModule = m => m.rcsModule; rcsModule.setupModelList(ModelData.parseModels(node.GetNodes("RCS"), m => new ServiceModuleRCSModelData(m))); rcsModule.getValidSelections = m => rcsModule.models.FindAll(s => s.isAvailable(upgradesApplied)); List <ConfigNode> tops = new List <ConfigNode>(); List <ConfigNode> bottoms = new List <ConfigNode>(); ConfigNode[] mNodes = node.GetNodes("CAP"); ConfigNode mNode; int len = mNodes.Length; for (int i = 0; i < len; i++) { mNode = mNodes[i]; if (mNode.GetBoolValue("useForTop", true)) { tops.Add(mNode); } if (mNode.GetBoolValue("useForBottom", true)) { bottoms.Add(mNode); } } topModule.setupModelList(SingleModelData.parseModels(tops.ToArray())); bottomModule.setupModelList(SingleModelData.parseModels(bottoms.ToArray())); tops.Clear(); bottoms.Clear(); topModule.setupModel(); coreModule.setupModel(); coreModule.model.updateScaleForDiameter(currentDiameter); bottomModule.setupModel(); solarModule.setupModel(); rcsModule.setupModel(); rcsModule.model.renameThrustTransforms(rcsThrustTransformName); updateModulePositions(); updateMassAndCost(); updateAttachNodes(false); SSTUStockInterop.updatePartHighlighting(part); }
/// <summary> /// Restores ModelData instances from config node data, and populates the 'currentModule' instances with the currently enabled modules. /// </summary> private void loadConfigData() { ConfigNode node = SSTUConfigNodeUtils.parseConfigNode(configNodeData); ConfigNode[] tankSetsNodes = node.GetNodes("TANKSET"); ConfigNode[] tankNodes = node.GetNodes("TANK"); ConfigNode[] mountNodes = node.GetNodes("CAP"); variantData = TankVariant.parseVariants(node.GetNodes("VARIANT")); tankSets = TankSet.parseSets(tankSetsNodes); //if no sets exist, initialize a default set to add all models to if (tankSets.Length == 0) { tankSets = new TankSet[1]; ConfigNode defaultSetNode = new ConfigNode("TANKSET"); defaultSetNode.AddValue("name", "default"); tankSets[0] = new TankSet(defaultSetNode); } TankModelData[] mainTankModules = ModelData.parseModels <TankModelData>(tankNodes, m => new TankModelData(m)); int len = mainTankModules.Length; TankSet set; for (int i = 0; i < len; i++) { set = Array.Find(tankSets, m => m.name == mainTankModules[i].setName); //if set is not found by name, add it to the first set which is guaranteed to exist due to the default-set-adding code above. if (set == null) { set = tankSets[0]; } set.addModel(mainTankModules[i]); } topNodeNames = SSTUUtils.parseCSV(topManagedNodeNames); bottomNodeNames = SSTUUtils.parseCSV(bottomManagedNodeNames); tankModule = new ModelModule <TankModelData, SSTUModularFuelTank>(part, this, getRootTransform(rootTransformName, true), ModelOrientation.CENTRAL, nameof(bodyModuleData), nameof(currentTankType), nameof(currentTankTexture)); tankModule.getSymmetryModule = m => m.tankModule; tankModule.getDisplayNames = m => SSTUUtils.getNames(m, s => s.variantName); tankModule.setupModelList(mainTankModules); currentTankSetModule = Array.Find(tankSets, m => m.name == tankModule.model.setName); currentTankSet = currentTankSetModule.name; lastSelectedVariant = tankModule.model.variantName; tankModule.getValidSelections = delegate(IEnumerable <TankModelData> data) { return(System.Linq.Enumerable.Where(data, s => s.setName == currentTankSet)); }; tankModule.updateSelections(); tankModule.setupModel(); len = mountNodes.Length; ConfigNode mountNode; List <SingleModelData> noses = new List <SingleModelData>(); List <SingleModelData> mounts = new List <SingleModelData>(); for (int i = 0; i < len; i++) { mountNode = mountNodes[i]; if (mountNode.GetBoolValue("useForNose", true)) { mountNode.SetValue("nose", "true"); noses.Add(new SingleModelData(mountNode)); } if (mountNode.GetBoolValue("useForMount", true)) { mountNode.SetValue("nose", "false"); mounts.Add(new SingleModelData(mountNode)); } } noseModule = new ModelModule <SingleModelData, SSTUModularFuelTank>(part, this, getRootTransform(rootNoseTransformName, true), ModelOrientation.TOP, nameof(noseModuleData), nameof(currentNoseType), nameof(currentNoseTexture)); noseModule.getSymmetryModule = m => m.noseModule; noseModule.getValidSelections = delegate(IEnumerable <SingleModelData> data) { return(System.Linq.Enumerable.Where(data, m => m.canSwitchTo(part, topNodeNames) && TankVariant.isValidNose(m.name, tankModule.model.variantName, variantData))); }; noseModule.setupModelList(noses); noseModule.setupModel(); mountModule = new ModelModule <SingleModelData, SSTUModularFuelTank>(part, this, getRootTransform(rootMountTransformName, true), ModelOrientation.BOTTOM, nameof(mountModuleData), nameof(currentMountType), nameof(currentMountTexture)); mountModule.getSymmetryModule = m => m.mountModule; mountModule.getValidSelections = delegate(IEnumerable <SingleModelData> data) { return(System.Linq.Enumerable.Where(data, m => m.canSwitchTo(part, bottomNodeNames) && TankVariant.isValidMount(m.name, tankModule.model.variantName, variantData))); }; mountModule.setupModelList(mounts); mountModule.setupModel(); }
/// <summary> /// Finds the model for the given part, if it currently exists; else it clones it /// </summary> /// <param name="model"></param> /// <returns></returns> private void setupModel(ModelData model, Transform parent) { model.setupModel(part, parent); }
/// <summary> /// Should be called by the PartModule to open the GUI. /// </summary> /// <param name="models"></param> public static void openGUI(ModelData[] models, float diameter, Action<String, bool> modelSelectedCB) { if (guiOpen) { throw new NotSupportedException("Cannot open a GUI when it is already open!"); } EditorLogic editor = EditorLogic.fetch; if (editor != null) { editor.Lock(true, true, true, "SSTUModelSelectLock"); } adapters = ModelGUISelection.createFromModelData(models, diameter); modelSelectedCallback = modelSelectedCB; guiOpen = true; shouldClose = false; UIPartActionController.Instance.Deactivate(); }