private void constructSingleModel(Transform parent, ModelOrientation orientation, bool reUse) { String modelName = modelDefinition.modelName; if (String.IsNullOrEmpty(modelName))//no model to setup { return; } if (reUse) { Transform tr = parent.transform.FindModel(modelDefinition.modelName); if (tr != null) { tr.name = modelDefinition.modelName; tr.gameObject.name = modelDefinition.modelName; } model = tr == null ? null : tr.gameObject; } if (!String.IsNullOrEmpty(modelName) && model == null) { model = SSTUUtils.cloneModel(modelName); } if (model != null) { model.transform.NestToParent(parent); if ((modelDefinition.invertForTop && orientation == ModelOrientation.TOP) || (modelDefinition.invertForBottom && orientation == ModelOrientation.BOTTOM)) { model.transform.Rotate(modelDefinition.invertAxis, 180, Space.Self); } } else { MonoBehaviour.print("ERROR: Could not locate model for name: " + modelName); } }
public void updateAttachNodes(Part part, String[] nodeNames, bool userInput, ModelOrientation orientation) { if (nodeNames.Length == 1 && nodeNames[0] == "NONE") { return; } Vector3 basePos = new Vector3(0, currentVerticalPosition, 0); AttachNode node = null; AttachNodeBaseData data; int nodeCount = modelDefinition.attachNodeData.Length; int len = nodeNames.Length; Vector3 pos = Vector3.zero; Vector3 orient = Vector3.up; int size = 2; bool invert = (orientation == ModelOrientation.BOTTOM && modelDefinition.invertForBottom) || (orientation == ModelOrientation.TOP && modelDefinition.invertForTop); for (int i = 0; i < len; i++) { node = part.findAttachNode(nodeNames[i]); if (i < nodeCount) { data = modelDefinition.attachNodeData[i]; size = data.size; pos = data.position * currentHeightScale; if (invert) { pos.y = -pos.y; pos.x = -pos.x; } pos.y += currentVerticalPosition; orient = data.orientation; if (invert) { orient = -orient; } if (node == null)//create it { SSTUAttachNodeUtils.createAttachNode(part, nodeNames[i], pos, orient, size); } else//update its position { SSTUAttachNodeUtils.updateAttachNodePosition(part, node, pos, orient, userInput); } } else//extra node, destroy { if (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight) { SSTUAttachNodeUtils.destroyAttachNode(part, node); } } } }
/// <summary> /// Updates the internal position reference for the input position /// Includes offsetting for the models offset; the input position should be the desired location /// of the bottom of the model. /// </summary> /// <param name="positionOfBottomOfModel"></param> public void setPosition(float positionOfBottomOfModel, ModelOrientation orientation = ModelOrientation.TOP) { float offset = getVerticalOffset(); if (orientation == ModelOrientation.BOTTOM) { offset = -offset; } currentVerticalPosition = positionOfBottomOfModel + offset; }
public ModelModule(Part part, PartModule partModule, Transform root, ModelOrientation orientation, string dataFieldName, string modelFieldName, string textureFieldName) { this.part = part; this.partModule = partModule; this.root = root; this.orientation = orientation; this.dataField = partModule.Fields[dataFieldName]; this.modelField = partModule.Fields[modelFieldName]; this.textureField = partModule.Fields[textureFieldName]; loadPersistentData(persistentData); }
/// <summary> /// Creates the transforms and meshes for the model using default positioning and orientation defined by the passed in ModelOrientation parameter /// </summary> /// <param name="parent"></param> /// <param name="orientation"></param> /// <param name="reUse"></param> public void setupModel(Transform parent, ModelOrientation orientation, bool reUse) { if (modelDefinition.subModelData.Length <= 0) { constructSingleModel(parent, orientation, reUse); } else { constructSubModels(parent, orientation, reUse); } }
private static void logException(string slot, Model a, ModelOrientation ao, bool aUpper, Model b, ModelOrientation bo, bool bUpper) { string[] aProf = aUpper ? a.getUpperProfiles(ao) : a.getLowerProfiles(ao); string[] aComp = aUpper ? a.getCompatibleLowerProfiles(ao) : a.getCompatibleUpperProfiles(ao); string[] bProf = bUpper ? b.getUpperProfiles(bo) : b.getLowerProfiles(bo); string[] bComp = bUpper ? b.getCompatibleLowerProfiles(bo) : b.getCompatibleUpperProfiles(bo); string apnf = ""; string bpnf = ""; int len = aProf.Length; for (int i = 0; i < len; i++) { if (!bComp.Contains(aProf[i])) { if (!string.IsNullOrEmpty(apnf)) { apnf += ","; } apnf += aProf[i]; } } len = bProf.Length; for (int i = 0; i < len; i++) { if (!aComp.Contains(bProf[i])) { if (!string.IsNullOrEmpty(bpnf)) { bpnf += ","; } bpnf += bProf[i]; } } string output = "Incomp Model Exception for slots: " + slot + " Models: " + a.name + " / " + b.name + " "; if (!string.IsNullOrEmpty(apnf)) { output += "apnf: " + apnf; if (!string.IsNullOrEmpty(bpnf)) { output += " : "; } } if (!string.IsNullOrEmpty(bpnf)) { output += "bpnf: " + bpnf; } incompExceptionStream.WriteLine(output); }
/// <summary> /// Updates the internal position reference for the input position /// Includes offsetting for the models offset; the input position should be the desired location /// of the bottom of the model. /// </summary> /// <param name="positionOfBottomOfModel"></param> public virtual void setPosition(float positionOfBottomOfModel, ModelOrientation orientation = ModelOrientation.TOP) { float offset = getVerticalOffset(); if (orientation == ModelOrientation.BOTTOM) { offset = -offset; } else if (orientation == ModelOrientation.CENTRAL) { offset += currentHeight * 0.5f; } currentVerticalPosition = positionOfBottomOfModel + offset; }
/// <summary> /// Returns the Y-coordinate of the bottom of the model for the given model orientation. /// </summary> /// <param name="orientation"></param> /// <returns></returns> public virtual float getPosition(ModelOrientation orientation = ModelOrientation.TOP) { float offset = getVerticalOffset(); if (orientation == ModelOrientation.BOTTOM) { offset = -offset; } else if (orientation == ModelOrientation.CENTRAL) { offset += currentHeight * 0.5f; } return(currentVerticalPosition - offset); }
public override void setupModel(Transform parent, ModelOrientation orientation) { model = new GameObject("MSCSolarRoot"); model.transform.NestToParent(parent); int len = positions == null? 0 : positions.Length; models = new GameObject[len]; for (int i = 0; i < len; i++) { models[i] = new GameObject("MSCSolar"); models[i].transform.NestToParent(model.transform); SSTUUtils.cloneModel(modelDefinition.modelName).transform.NestToParent(models[i].transform); models[i].transform.Rotate(positions[i].rotation, Space.Self); models[i].transform.localPosition = positions[i].position; models[i].transform.localScale = positions[i].scale; } }
public Model(ConfigNode node) { name = node.GetValue("name"); upperProfiles = node.GetValues("upperProfile"); lowerProfiles = node.GetValues("lowerProfile"); compatibleUpperProfiles = node.GetValues("compatibleUpperProfile"); compatibleLowerProfiles = node.GetValues("compatibleLowerProfile"); if (node.HasValue("orientation")) { orientation = (ModelOrientation)Enum.Parse(typeof(ModelOrientation), node.GetValue("orientation")); } else { System.Console.WriteLine("No orientation data parsed for model def: " + name); orientation = ModelOrientation.TOP; } }
public override void setupModel(Transform parent, ModelOrientation orientation) { if (model != null || models != null) { destroyCurrentModel(); } model = new GameObject(modelDefinition.name); model.transform.NestToParent(parent); models = new GameObject[4]; for (int i = 0; i < 4; i++) { models[i] = SSTUUtils.cloneModel(modelDefinition.modelName); } foreach (GameObject go in models) { go.transform.NestToParent(model.transform); } }
/// <summary> /// Creates the transforms and meshes for the model using default positioning and orientation defined by the passed in ModelOrientation parameter /// </summary> /// <param name="parent"></param> /// <param name="orientation"></param> public override void setupModel(Transform parent, ModelOrientation orientation) { setupModel(parent, orientation, false); }
/// <summary> /// Updates the attach nodes on the part for the input list of attach nodes and the current specified nodes for this model. /// Any 'extra' attach nodes from the part will be disabled. /// </summary> /// <param name="part"></param> /// <param name="nodeNames"></param> /// <param name="userInput"></param> /// <param name="orientation"></param> public void updateAttachNodes(Part part, String[] nodeNames, bool userInput, ModelOrientation orientation) { if (nodeNames == null || nodeNames.Length < 1) { return; } if (nodeNames.Length == 1 && (nodeNames[0] == "NONE" || nodeNames[0] == "none")) { return; } float currentVerticalPosition = this.currentVerticalPosition; float offset = getVerticalOffset(); if (orientation == ModelOrientation.BOTTOM) { offset = -offset; } currentVerticalPosition -= offset; AttachNode node = null; AttachNodeBaseData data; int nodeCount = modelDefinition.attachNodeData.Length; int len = nodeNames.Length; Vector3 pos = Vector3.zero; Vector3 orient = Vector3.up; int size = 4; bool invert = modelDefinition.shouldInvert(orientation); for (int i = 0; i < len; i++) { node = part.FindAttachNode(nodeNames[i]); if (i < nodeCount) { data = modelDefinition.attachNodeData[i]; size = Mathf.RoundToInt(data.size * currentDiameterScale); pos = data.position * currentHeightScale; if (invert) { pos.y = -pos.y; pos.x = -pos.x; } pos.y += currentVerticalPosition; orient = data.orientation; if (invert) { orient = -orient; orient.z = -orient.z; } if (node == null)//create it { SSTUAttachNodeUtils.createAttachNode(part, nodeNames[i], pos, orient, size); } else//update its position { SSTUAttachNodeUtils.updateAttachNodePosition(part, node, pos, orient, userInput); } } else//extra node, destroy { if (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight) { SSTUAttachNodeUtils.destroyAttachNode(part, node); } } } }
/// <summary> /// Creates the transforms and meshes for the model using default positioning and orientation defined by the passed in ModelOrientation parameter /// </summary> /// <param name="parent"></param> /// <param name="orientation"></param> public virtual void setupModel(Transform parent, ModelOrientation orientation) { throw new NotImplementedException(); }
public ModelDefinition(ConfigNode node) { configNode = node; name = node.GetStringValue("name", String.Empty); title = node.GetStringValue("title", name); description = node.GetStringValue("description", title); icon = node.GetStringValue("icon"); modelName = node.GetStringValue("modelName", String.Empty); upgradeUnlockName = node.GetStringValue("upgradeUnlock", upgradeUnlockName); height = node.GetFloatValue("height", height); volume = node.GetFloatValue("volume", volume); mass = node.GetFloatValue("mass", mass); cost = node.GetFloatValue("cost", cost); diameter = node.GetFloatValue("diameter", diameter); verticalOffset = node.GetFloatValue("verticalOffset", verticalOffset); if (node.GetBoolValue("invertForTop", false)) { orientation = ModelOrientation.BOTTOM; } else if (node.GetBoolValue("invertForBottom", false)) { orientation = ModelOrientation.TOP; } invertAxis = node.GetVector3("invertAxis", invertAxis); fairingDisabled = node.GetBoolValue("fairingDisabled", fairingDisabled); fairingTopOffset = node.GetFloatValue("fairingTopOffset", fairingTopOffset); rcsVerticalPosition = node.GetFloatValue("rcsVerticalPosition", rcsVerticalPosition); rcsHorizontalPosition = node.GetFloatValue("rcsHorizontalPosition", rcsHorizontalPosition); rcsVerticalRotation = node.GetFloatValue("rcsVerticalRotation", rcsVerticalRotation); rcsHorizontalRotation = node.GetFloatValue("rcsHorizontalRotation", rcsHorizontalRotation); ConfigNode[] subModelNodes = node.GetNodes("SUBMODEL"); int len = subModelNodes.Length; subModelData = new SubModelData[len]; for (int i = 0; i < len; i++) { subModelData[i] = new SubModelData(subModelNodes[i]); } defaultTextureSet = node.GetStringValue("defaultTextureSet"); String[] attachNodeStrings = node.GetValues("node"); len = attachNodeStrings.Length; attachNodeData = new AttachNodeBaseData[len]; for (int i = 0; i < len; i++) { attachNodeData[i] = new AttachNodeBaseData(attachNodeStrings[i]); } ConfigNode[] textureSetNodes = node.GetNodes("TEXTURESET"); len = textureSetNodes.Length; textureSets = new TextureSet[len]; for (int i = 0; i < len; i++) { textureSets[i] = new TextureSet(textureSetNodes[i]); } if (node.HasValue("surface")) { surfaceNode = new AttachNodeBaseData(node.GetStringValue("surface")); } else { String val = (diameter * 0.5f) + ",0,0,1,0,0,2"; surfaceNode = new AttachNodeBaseData(val); } if (node.HasNode("COMPOUNDMODEL")) { compoundModelData = new CompoundModelData(node.GetNode("COMPOUNDMODEL")); } if (node.HasNode("ANIMATION")) { animationData = ModelAnimationData.parseAnimationData(node.GetNodes("ANIMATION")); } else { animationData = new ModelAnimationData[0]; } if (node.HasNode("CONSTRAINT")) { constraintData = node.GetNode("CONSTRAINT"); } }
/// <summary> /// Sets the position of the model so that the origin of the model is at the input Y coordinate, for the input model orientation.<para/> /// TOP = Y == bottom<para/> /// CENTRAL = Y == center<para/> /// BOTTOM = Y == top<para/> /// </summary> /// <param name="yPos"></param> /// <param name="orientation"></param> public void setPosition(float yPos, ModelOrientation orientation = ModelOrientation.TOP) { model.setPosition(yPos, orientation); }
/// <summary> /// Construct the model definition from the data in the input ConfigNode.<para/> /// All data constructs MUST conform to the expected format (see documentation), or things will not load properly and the model will likely not work as expected. /// </summary> /// <param name="node"></param> public ROLModelDefinition(ConfigNode node) { //load basic model definition values -- data that pertains to every model definition regardless of end-use. configNode = node; name = node.ROLGetStringValue("name", String.Empty); if (string.IsNullOrEmpty(name)) { ROLLog.error("ERROR: Cannot load ROLModelDefinition with null or empty name. Full config:\n" + node.ToString()); } title = node.ROLGetStringValue("title", name); description = node.ROLGetStringValue("description", title); modelName = node.ROLGetStringValue("modelName", string.Empty); upgradeUnlock = node.ROLGetStringValue("upgradeUnlock", upgradeUnlock); height = node.ROLGetFloatValue("height", height); actualHeight = node.ROLGetFloatValue("actualHeight", actualHeight); volume = node.ROLGetFloatValue("volume", volume); mass = node.ROLGetFloatValue("mass", mass); cost = node.ROLGetFloatValue("cost", cost); diameter = node.ROLGetFloatValue("diameter", diameter); minVerticalScale = node.ROLGetFloatValue("minVerticalScale", minVerticalScale); maxVerticalScale = node.ROLGetFloatValue("maxVerticalScale", maxVerticalScale); upperDiameter = node.ROLGetFloatValue("upperDiameter", diameter); lowerDiameter = node.ROLGetFloatValue("lowerDiameter", diameter); panelLength = node.ROLGetFloatValue("panelLength", panelLength); panelWidth = node.ROLGetFloatValue("panelWidth", panelWidth); panelArea = node.ROLGetFloatValue("panelArea", panelArea); panelScale = node.ROLGetFloatValue("panelScale", panelScale); secondaryTransformName = node.ROLGetStringValue("secondaryTransformName", secondaryTransformName); pivotName = node.ROLGetStringValue("pivotName", pivotName); animationName = node.ROLGetStringValue("animationName", animationName); lengthWidth = node.ROLGetBoolValue("lengthWidth", lengthWidth); isTracking = node.ROLGetBoolValue("isTracking", isTracking); effectiveLength = node.ROLGetFloatValue("effectiveLength", effectiveLength); additionalVolume = node.ROLGetFloatValue("additionalVolume", additionalVolume); if (node.HasValue("verticalOffset")) { positionOffset = new Vector3(0, node.ROLGetFloatValue("verticalOffset"), 0); } else { positionOffset = node.ROLGetVector3("positionOffset", Vector3.zero); } rotationOffset = node.ROLGetVector3("rotationOffset", rotationOffset); scaleOffset = node.ROLGetVector3("scaleOffset", Vector3.one); orientation = (ModelOrientation)Enum.Parse(typeof(ModelOrientation), node.ROLGetStringValue("orientation", ModelOrientation.TOP.ToString())); invertAxis = node.ROLGetVector3("invertAxis", invertAxis); //load sub-model definitions ConfigNode[] subModelNodes = node.GetNodes("SUBMODEL"); int len = subModelNodes.Length; if (len == 0)//no defined submodel data, check for regular single model definition, if present, build a submodel definition for it. { if (!string.IsNullOrEmpty(modelName)) { SubModelData smd = new SubModelData(modelName, new string[0], string.Empty, positionOffset, rotationOffset, scaleOffset); subModelData = new SubModelData[] { smd }; } else//is an empty proxy model with no meshes { subModelData = new SubModelData[0]; } } else { subModelData = new SubModelData[len]; for (int i = 0; i < len; i++) { subModelData[i] = new SubModelData(subModelNodes[i]); } } if (node.HasNode("MERGEDMODELS")) { ConfigNode[] mergeNodes = node.GetNodes("MERGEDMODELS"); len = mergeNodes.Length; mergeData = new MeshMergeData[len]; for (int i = 0; i < len; i++) { mergeData[i] = new MeshMergeData(mergeNodes[i]); } } else { mergeData = new MeshMergeData[0]; } //Load texture set definitions. List <TextureSet> textureSetList = new List <TextureSet>(); foreach (string tsName in node.ROLGetStringValues("textureSet")) { if (TexturesUnlimitedLoader.getTextureSet(tsName) is TextureSet ts) { textureSetList.Add(ts); } } //then load any of the model-specific sets foreach (ConfigNode tsNode in node.GetNodes("KSP_TEXTURE_SET")) { textureSetList.Add(new TextureSet(tsNode)); } textureSets = textureSetList.ToArray(); //Load the default texture set specification defaultTextureSet = node.ROLGetStringValue("defaultTextureSet"); //if none is defined in the model def, but texture sets are present, set it to the name of the first defined texture set if (string.IsNullOrEmpty(defaultTextureSet) && textureSets.Length > 0) { defaultTextureSet = textureSets[0].name; } if (node.HasValue("topNode")) { topNodeData = new AttachNodeBaseData(node.ROLGetStringValue("topNode")); } else { float y = height; if (orientation == ModelOrientation.CENTRAL) { y *= 0.5f; } else if (orientation == ModelOrientation.BOTTOM) { y = 0; } topNodeData = new AttachNodeBaseData(0, y, 0, 0, 1, 0, diameter / 1.25f); } if (node.HasValue("bottomNode")) { bottomNodeData = new AttachNodeBaseData(node.ROLGetStringValue("bottomNode")); } else { float y = -height; if (orientation == ModelOrientation.CENTRAL) { y *= 0.5f; } else if (orientation == ModelOrientation.TOP) { y = 0; } bottomNodeData = new AttachNodeBaseData(0, y, 0, 0, -1, 0, diameter / 1.25f); } if (node.HasValue("bodyNode")) { string[] nodeData = node.ROLGetStringValues("bodyNode"); len = nodeData.Length; bodyNodeData = new AttachNodeBaseData[len]; for (int i = 0; i < len; i++) { bodyNodeData[i] = new AttachNodeBaseData(nodeData[i]); } } //load the surface attach node specifications, or create default if none are defined. if (node.HasValue("surface")) { surfaceNode = new AttachNodeBaseData(node.ROLGetStringValue("surface")); } else { surfaceNode = new AttachNodeBaseData($"{diameter / 2},0,0,1,0,0,2"); } if (node.HasNode("COMPOUNDMODEL")) { compoundModelData = new CompoundModelData(node.GetNode("COMPOUNDMODEL")); } if (node.HasNode("CONSTRAINT")) { constraintData = new ModelConstraintData(node.GetNode("CONSTRAINT")); } if (node.HasNode("RCSDATA")) { rcsModuleData = new ModelRCSModuleData(node.GetNode("RCSDATA")); } if (node.HasNode("RCSPOSITION")) { ConfigNode[] pns = node.GetNodes("RCSPOSITION"); len = pns.Length; rcsPositionData = new ModelAttachablePositionData[len]; for (int i = 0; i < len; i++) { rcsPositionData[i] = new ModelAttachablePositionData(pns[i]); } } if (node.HasNode("ENGINE_THRUST")) { engineThrustData = new ModelEngineThrustData(node.GetNode("ENGINE_THRUST")); } if (node.HasNode("ENGINE_TRANSFORM")) { engineTransformData = new ModelEngineTransformData(node.GetNode("ENGINE_TRANSFORM")); } }
/// <summary> /// Return if the input profiles are compatible with being mounted on the top of this model when this model is used in the input orientation.<para/> /// E.G. If model specified orientation==TOP, but being used for 'BOTTOM', will actually check the 'upper' profiles list (as that is the attach point that is at the bottom of the model when inverted) /// </summary> /// <param name="profiles"></param> /// <param name="orientation"></param> /// <returns></returns> internal bool isValidUpperProfile(string[] profiles, ModelOrientation orientation) { return(shouldInvert(orientation) ? canAttach(compatibleLowerProfiles, profiles) : canAttach(compatibleUpperProfiles, profiles)); }
public void SetHeightExplicit(ROLModelDefinition def, GameObject root, float dScale, float height, ModelOrientation orientation) { float vScale = height / def.height; SetHeightFromScale(def, root, dScale, vScale, orientation); }
public void SetHeightFromScale(ROLModelDefinition def, GameObject root, float dScale, float vScale, ModelOrientation orientation) { float desiredHeight = def.height * vScale; float staticHeight = GetStaticHeight() * dScale; float neededScaleHeight = desiredHeight - staticHeight; //iterate through scaleable transforms, calculate total height of scaleable transforms; use this height to determine 'percent share' of needed scale height for each transform float totalScaleableHeight = 0f; foreach (CompoundModelTransformData data in compoundTransformData) { totalScaleableHeight += data.canScaleHeight ? data.height : 0; } float pos = 0f; //pos starts at origin, is incremented according to transform height along 'dir' float dir = orientation == ModelOrientation.BOTTOM ? -1f : 1f; //set from model orientation, either +1 or -1 depending on if origin is at botom or top of model (ModelOrientation.TOP vs ModelOrientation.BOTTOM) float percent, scale, height; foreach (CompoundModelTransformData data in compoundTransformData) { percent = data.canScaleHeight ? data.height / totalScaleableHeight : 0f; height = percent * neededScaleHeight; scale = height / data.height; foreach (Transform tr in root.transform.ROLFindChildren(data.name)) { tr.localPosition = data.vScaleAxis * (pos + data.offset * dScale); float localVerticalScale = data.canScaleHeight ? scale : dScale; pos += dir * (data.canScaleHeight ? height : dScale * data.height); tr.localScale = GetScaleVector(dScale, localVerticalScale, data.vScaleAxis); } } }
/// <summary> /// Return true/false if this model should be inverted/rotated based on the input use-orientation and the models config-defined orientation.<para/> /// If specified model orientation == CENTER, model will never invert regardless of input value. /// </summary> /// <param name="orientation"></param> /// <returns></returns> internal bool shouldInvert(ModelOrientation orientation) { return((orientation == ModelOrientation.BOTTOM && this.orientation == ModelOrientation.TOP) || (orientation == ModelOrientation.TOP && this.orientation == ModelOrientation.BOTTOM)); }
public override void setupModel(Part part, Transform parent, ModelOrientation orientation) { models = new GameObject[4]; Transform[] trs = part.transform.FindChildren(modelDefinition.modelName); if (trs != null && trs.Length>0) { for (int i = 0; i < 4; i++) { models[i] = trs[i].gameObject; } } else { for (int i = 0; i < 4; i++) { models[i] = SSTUUtils.cloneModel(modelDefinition.modelName); } } foreach (GameObject go in models) { go.transform.NestToParent(parent); } }
private void constructSubModels(Transform parent, ModelOrientation orientation, bool reUse) { String modelName = modelDefinition.modelName; if (String.IsNullOrEmpty(modelName))//no model name given, log user-error for them to correct { MonoBehaviour.print("ERROR: Could not setup sub-models for ModelDefinition: " + modelDefinition.name + " as no modelName was specified to use as the root transform."); MonoBehaviour.print("Please add a modelName to this model definition to enable sub-model creation."); return; } //attempt to re-use the model if it is already present on the part if (reUse) { Transform tr = parent.transform.FindModel(modelDefinition.modelName); if (tr != null) { tr.name = modelDefinition.modelName; tr.gameObject.name = modelDefinition.modelName; } model = tr == null ? null : tr.gameObject; } //not re-used, recreate it entirely from the sub-model data if (model == null) { //create a new GO at 0,0,0 with default orientation and the given model name //this will be the 'parent' for sub-model creation model = new GameObject(modelName); SubModelData[] smds = modelDefinition.subModelData; SubModelData smd; GameObject clonedModel; Transform localParent; int len = smds.Length; //add sub-models to the base model transform for (int i = 0; i < len; i++) { smd = smds[i]; clonedModel = SSTUUtils.cloneModel(smd.modelURL); if (clonedModel == null) { continue; } //TODO log error clonedModel.transform.NestToParent(model.transform); clonedModel.transform.localRotation = Quaternion.Euler(smd.rotation); clonedModel.transform.localPosition = smd.position; clonedModel.transform.localScale = smd.scale; if (!string.IsNullOrEmpty(smd.parent)) { localParent = model.transform.FindRecursive(smd.parent); if (localParent != null) { clonedModel.transform.parent = localParent; } } //de-activate any non-active sub-model transforms //iterate through all transforms for the model and deactivate(destroy?) any not on the active mesh list if (smd.modelMeshes.Length > 0) { smd.setupSubmodel(clonedModel); } } } //regardless of if it was new or re-used, reset its position and orientation model.transform.NestToParent(parent); if ((modelDefinition.invertForTop && orientation == ModelOrientation.TOP) || (modelDefinition.invertForBottom && orientation == ModelOrientation.BOTTOM)) { model.transform.Rotate(modelDefinition.invertAxis, 180, Space.Self); } }
public virtual void setupModel(Part part, Transform parent, ModelOrientation orientation) { throw new NotImplementedException(); }
public override void setupModel(Part part, Transform parent, ModelOrientation orientation) { String modelName = modelDefinition.modelName; if (!String.IsNullOrEmpty(modelName)) { model = SSTUUtils.cloneModel(modelName); if (model != null) { model.transform.NestToParent(parent); if ((modelDefinition.invertForTop && orientation == ModelOrientation.TOP) || (modelDefinition.invertForBottom && orientation == ModelOrientation.BOTTOM)) { model.transform.Rotate(new Vector3(0, 0, 1), 180, Space.Self); } } else { MonoBehaviour.print("ERROR: Could not locate model for name: " + modelName); } } }
public void updateAttachNodes(Part part, String[] nodeNames, bool userInput, ModelOrientation orientation) { Vector3 basePos = new Vector3(0, currentVerticalPosition, 0); AttachNode node = null; AttachNodeBaseData data; int nodeCount = modelDefinition.attachNodeData.Length; int len = nodeNames.Length; Vector3 pos = Vector3.zero; Vector3 orient = Vector3.up; int size = 2; bool invert = (orientation == ModelOrientation.BOTTOM && modelDefinition.invertForBottom) || (orientation == ModelOrientation.TOP && modelDefinition.invertForTop); for (int i = 0; i < len; i++) { node = part.findAttachNode(nodeNames[i]); if (i < nodeCount) { data = modelDefinition.attachNodeData[i]; size = data.size; pos = data.position * currentHeightScale; if (invert) { pos.y = -pos.y; pos.x = -pos.x; } pos.y += currentVerticalPosition; orient = data.orientation; if (invert) { orient = -orient; } if (node == null)//create it { SSTUAttachNodeUtils.createAttachNode(part, nodeNames[i], pos, orient, size); } else//update its position { SSTUAttachNodeUtils.updateAttachNodePosition(part, node, pos, orient, userInput); } } else//extra node, destroy { if (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight) { SSTUAttachNodeUtils.destroyAttachNode(part, node); } } } }
public string[] getUpperProfiles(ModelOrientation orientation) { return(shouldInvert(orientation) ? lowerProfiles : upperProfiles); }
public string[] getCompatibleLowerProfiles(ModelOrientation orientation) { return(shouldInvert(orientation) ? compatibleUpperProfiles : compatibleLowerProfiles); }
/// <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); }
public void setHeightFromScale(ModelDefinition def, GameObject root, float dScale, float vScale, ModelOrientation orientation) { float desiredHeight = def.height * vScale; float staticHeight = getStaticHeight() * dScale; float neededScaleHeight = desiredHeight - staticHeight; //iterate through scaleable transforms, calculate total height of scaleable transforms; use this height to determine 'percent share' of needed scale height for each transform int len = compoundTransformData.Length; float totalScaleableHeight = 0f; for (int i = 0; i < len; i++) { totalScaleableHeight += compoundTransformData[i].canScaleHeight ? compoundTransformData[i].height : 0f; } float pos = 0f; //pos starts at origin, is incremented according to transform height along 'dir' float dir = orientation == ModelOrientation.BOTTOM ? -1f : 1f; //set from model orientation, either +1 or -1 depending on if origin is at botom or top of model (ModelOrientation.TOP vs ModelOrientation.BOTTOM) float localVerticalScale = 1f; Transform[] trs; int len2; float percent, scale, height; for (int i = 0; i < len; i++) { percent = compoundTransformData[i].canScaleHeight ? compoundTransformData[i].height / totalScaleableHeight : 0f; height = percent * neededScaleHeight; scale = height / compoundTransformData[i].height; trs = root.transform.FindChildren(compoundTransformData[i].name); len2 = trs.Length; for (int k = 0; k < len2; k++) { trs[k].localPosition = compoundTransformData[i].vScaleAxis * (pos + compoundTransformData[i].offset * dScale); if (compoundTransformData[i].canScaleHeight) { pos += dir * height; localVerticalScale = scale; } else { pos += dir * dScale * compoundTransformData[i].height; localVerticalScale = dScale; } trs[k].localScale = getScaleVector(dScale, localVerticalScale, compoundTransformData[i].vScaleAxis); } } }