public void FixedUpdate() { if (comp != null) { // This module could be called before MASFlightComputer is initialized, // so we need to wait for comp.isInitialized before creating our actions. // This does create a race condition, but I'd be surprised if someone could // get the menu open and clicked within about 1 FixedUpdate. if (!initialized && comp.initialized) { if (!string.IsNullOrEmpty(activateAction)) { onActivate = comp.GetAction(activateAction, null); if (onActivate == null) { Utility.LogError(this, "Failed to initialize action '{1}' for {0}", menuName, activateAction); } } if (!string.IsNullOrEmpty(deactivateAction)) { onDeactivate = comp.GetAction(deactivateAction, null); if (onDeactivate == null) { Utility.LogError(this, "Failed to initialize action '{1}' for {0}", menuName, deactivateAction); } } initialized = true; } if (lastState != actionState) { if (actionState && onActivate != null) { onActivate(); } else if (onDeactivate != null) { onDeactivate(); } lastState = actionState; menuName = (lastState) ? deactivateText : activateText; } } }
internal MASComponentTriggerEvent(ConfigNode config, InternalProp prop, MASFlightComputer comp) : base(config, prop, comp) { string variableName = string.Empty; if (!config.TryGetValue("variable", ref variableName) || string.IsNullOrEmpty(variableName)) { throw new ArgumentException("Invalid or missing 'variable' in TRIGGER_EVENT " + name); } variableName = variableName.Trim(); if (!config.TryGetValue("autoRepeat", ref autoRepeat)) { autoRepeat = false; } string triggerEventName = string.Empty; config.TryGetValue("event", ref triggerEventName); if (string.IsNullOrEmpty(triggerEventName)) { throw new ArgumentException("Invalid or missing 'event' in TRIGGER_EVENT " + name); } triggerEvent = comp.GetAction(triggerEventName, prop); if (triggerEvent == null) { throw new ArgumentException("Unable to create event '" + triggerEventName + "' in TRIGGER_EVENT " + name); } triggerEventName = string.Empty; if (config.TryGetValue("exitEvent", ref triggerEventName)) { exitEvent = comp.GetAction(triggerEventName, prop); if (exitEvent == null) { throw new ArgumentException("Unable to create event '" + triggerEventName + "' in TRIGGER_EVENT " + name); } } this.comp = comp; callbackVariable = comp.RegisterVariableChangeCallback(variableName, prop, VariableCallback); }
/// <summary> /// Call the startupScript, if it exists. /// </summary> /// <param name="comp">The MASFlightComputer for this prop.</param> /// <returns>true if a script exists, false otherwise.</returns> internal bool RunStartupScript(MASFlightComputer comp) { if (!string.IsNullOrEmpty(startupScript)) { Action startup = comp.GetAction(startupScript, internalProp); startup(); return(true); } else { return(false); } }
/// <summary> /// Startup, initialize, configure, etc. /// </summary> public void Start() { if (HighLogic.LoadedSceneIsFlight) { try { MASFlightComputer comp = MASFlightComputer.Instance(internalProp.part); if (comp == null) { throw new ArgumentNullException("Failed to find MASFlightComputer initializing MASMonitor"); } variableRegistrar = new VariableRegistrar(comp, internalProp); if (string.IsNullOrEmpty(screenTransform)) { throw new ArgumentException("Missing 'transform' in MASMonitor"); } if (string.IsNullOrEmpty(layer)) { throw new ArgumentException("Missing 'layer' in MASMonitor"); } if (string.IsNullOrEmpty(font)) { throw new ArgumentException("Missing 'font' in MASMonitor"); } if (string.IsNullOrEmpty(textColor)) { throw new ArgumentException("Missing 'textColor' in MASMonitor"); } else { textColor_ = Utility.ParseColor32(textColor, comp); } if (string.IsNullOrEmpty(backgroundColor)) { throw new ArgumentException("Missing 'backgroundColor' in MASMonitor"); } else { backgroundColor_ = Utility.ParseColor32(backgroundColor, comp); } if (screenSize.x <= 0.0f || screenSize.y <= 0.0f) { throw new ArgumentException("Invalid 'screenSize' in MASMonitor"); } if (fontSize.x <= 0.0f || fontSize.y <= 0.0f) { throw new ArgumentException("Invalid 'fontSize' in MASMonitor"); } screenWidth = (int)screenSize.x; screenHeight = (int)screenSize.y; screenSpace = new GameObject(); screenSpace.name = Utility.ComposeObjectName(internalProp.propName, this.GetType().Name, screenSpace.GetInstanceID()); screenSpace.layer = drawingLayer; screenSpace.transform.position = Vector3.zero; screenSpace.SetActive(true); screen = new RenderTexture(screenWidth, screenHeight, 24, RenderTextureFormat.ARGB32); if (screen == null) { throw new ArgumentNullException("Failed to find create " + screenWidth + " x " + screenHeight + " render texture initializing MASMonitor"); } if (!screen.IsCreated()) { screen.Create(); screen.DiscardContents(); } Camera.onPreCull += EnablePage; Camera.onPostRender += DisablePage; screenCamera = screenSpace.AddComponent <Camera>(); screenCamera.enabled = true; // Enable = "auto-draw" screenCamera.orthographic = true; screenCamera.aspect = screenSize.x / screenSize.y; screenCamera.eventMask = 0; screenCamera.farClipPlane = 1.0f + depthDelta; screenCamera.nearClipPlane = depthDelta; screenCamera.orthographicSize = screenSize.y * 0.5f; screenCamera.cullingMask = 1 << drawingLayer; screenCamera.transparencySortMode = TransparencySortMode.Orthographic; screenCamera.transform.position = Vector3.zero; screenCamera.transform.LookAt(new Vector3(0.0f, 0.0f, maxDepth), Vector3.up); screenCamera.backgroundColor = backgroundColor_; screenCamera.clearFlags = CameraClearFlags.SolidColor; screenCamera.targetTexture = screen; Transform screenTransformLoc = internalProp.FindModelTransform(screenTransform); if (screenTransformLoc == null) { throw new ArgumentNullException("Failed to find screenTransform \"" + screenTransform + "\" initializing MASMonitor"); } Material screenMat = screenTransformLoc.GetComponent <Renderer>().material; string[] layers = layer.Split(); for (int i = layers.Length - 1; i >= 0; --i) { screenMat.SetTexture(layers[i].Trim(), screen); } defaultFont = MASLoader.GetFont(font.Trim()); if (!string.IsNullOrEmpty(style)) { defaultStyle = MdVTextMesh.FontStyle(style.Trim()); } ConfigNode moduleConfig = Utility.GetPropModuleConfigNode(internalProp.propName, ClassName); if (moduleConfig == null) { throw new ArgumentNullException("No ConfigNode found for MASMonitor in " + internalProp.propName + "!"); } // If an initialization script was supplied, call it. if (!string.IsNullOrEmpty(startupScript)) { Action startup = comp.GetAction(startupScript, internalProp); startup(); } string[] pages = moduleConfig.GetValues("page"); int numPages = pages.Length; for (int i = 0; i < numPages; ++i) { pages[i] = pages[i].Trim(); ConfigNode pageConfig = Utility.GetPageConfigNode(pages[i]); if (pageConfig == null) { throw new ArgumentException("No ConfigNode found for page " + pages[i] + " in MASMonitor in " + internalProp.propName + "!"); } // Parse the page node MASPage newPage = new MASPage(pageConfig, internalProp, comp, this, screenSpace.transform); if (i == 0) { // Select the default page as the current page currentPage = newPage; } newPage.SetPageActive(false); page.Add(pages[i], newPage); //Utility.LogMessage(this, "Page = {0}", pages[i]); } //HackWalkTransforms(screenSpace.transform, 0); if (!string.IsNullOrEmpty(monitorID)) { string variableName = "fc.GetPersistent(\"" + monitorID.Trim() + "\")"; pageSelector = variableRegistrar.RegisterVariableChangeCallback(variableName, PageChanged, false); // See if we have a saved page to restore. if (!string.IsNullOrEmpty(pageSelector.AsString()) && page.ContainsKey(pageSelector.AsString())) { currentPage = page[pageSelector.AsString()]; } comp.RegisterMonitor(monitorID, internalProp, this); } currentPage.SetPageActive(true); initialized = true; Utility.LogMessage(this, "Configuration complete in prop #{0} ({1}) with {2} pages", internalProp.propID, internalProp.propName, numPages); } catch (Exception e) { Utility.ComplainLoudly("MASMonitor configuration failed."); Utility.LogError(this, "Failed to configure prop #{0} ({1})", internalProp.propID, internalProp.propName); Utility.LogError(this, e.ToString()); } } }
internal MASComponentColliderEvent(ConfigNode config, InternalProp internalProp, MASFlightComputer comp) : base(config, internalProp, comp) { string collider = string.Empty; if (!config.TryGetValue("collider", ref collider)) { throw new ArgumentException("Missing 'collider' in COLLIDER_EVENT " + name); } string clickEvent = string.Empty, releaseEvent = string.Empty, dragEventX = string.Empty, dragEventY = string.Empty; config.TryGetValue("onClick", ref clickEvent); config.TryGetValue("onRelease", ref releaseEvent); config.TryGetValue("onDragX", ref dragEventX); config.TryGetValue("onDragY", ref dragEventY); if (string.IsNullOrEmpty(clickEvent) && string.IsNullOrEmpty(releaseEvent) && string.IsNullOrEmpty(dragEventX) && string.IsNullOrEmpty(dragEventY)) { throw new ArgumentException("None of 'onClick', 'onRelease', 'onDragX', nor 'onDragY' found in COLLIDER_EVENT " + name); } Transform tr = internalProp.FindModelTransform(collider.Trim()); if (tr == null) { throw new ArgumentException("Unable to find transform '" + collider + "' in prop for COLLIDER_EVENT " + name); } float autoRepeat = 0.0f; if (!config.TryGetValue("autoRepeat", ref autoRepeat)) { autoRepeat = 0.0f; } float volume = -1.0f; if (config.TryGetValue("volume", ref volume)) { volume = Mathf.Clamp01(volume); } else { volume = -1.0f; } string sound = string.Empty; if (!config.TryGetValue("sound", ref sound) || string.IsNullOrEmpty(sound)) { sound = string.Empty; } AudioClip clip = null; if (string.IsNullOrEmpty(sound) == (volume >= 0.0f)) { throw new ArgumentException("Only one of 'sound' or 'volume' found in COLLIDER_EVENT " + name); } if (volume >= 0.0f) { //Try Load audio clip = GameDatabase.Instance.GetAudioClip(sound); if (clip == null) { throw new ArgumentException("Unable to load 'sound' " + sound + " in COLLIDER_EVENT " + name); } } buttonObject = tr.gameObject.AddComponent <ButtonObject>(); buttonObject.parent = this; buttonObject.autoRepeat = (autoRepeat > 0.0f); buttonObject.repeatRate = autoRepeat; string variableName = string.Empty; if (config.TryGetValue("variable", ref variableName)) { variableName = variableName.Trim(); buttonObject.colliderEnabled = false; comp.RegisterVariableChangeCallback(variableName, internalProp, VariableCallback); } if (clip != null) { AudioSource audioSource = tr.gameObject.AddComponent <AudioSource>(); audioSource.clip = clip; audioSource.Stop(); audioSource.volume = GameSettings.SHIP_VOLUME * volume; audioSource.rolloffMode = AudioRolloffMode.Logarithmic; audioSource.maxDistance = 8.0f; audioSource.minDistance = 2.0f; audioSource.dopplerLevel = 0.0f; audioSource.panStereo = 0.0f; audioSource.playOnAwake = false; audioSource.loop = false; audioSource.pitch = 1.0f; buttonObject.audioSource = audioSource; } if (!string.IsNullOrEmpty(clickEvent)) { buttonObject.onClick = comp.GetAction(clickEvent, internalProp); } if (!string.IsNullOrEmpty(releaseEvent)) { buttonObject.onRelease = comp.GetAction(releaseEvent, internalProp); } if (!string.IsNullOrEmpty(dragEventX)) { buttonObject.onDragX = comp.GetDragAction(dragEventX, name, internalProp); if (buttonObject.onDragX != null) { buttonObject.drag = true; float dragSensitivity = 1.0f; if (!config.TryGetValue("dragSensitivity", ref dragSensitivity)) { dragSensitivity = 1.0f; } buttonObject.normalizationScalar = 0.01f * dragSensitivity; } else { throw new ArgumentException("Unable to create 'onDragX' event for COLLIDER_EVENT " + name); } } if (!string.IsNullOrEmpty(dragEventY)) { buttonObject.onDragY = comp.GetDragAction(dragEventY, name, internalProp); if (buttonObject.onDragY != null) { buttonObject.drag = true; float dragSensitivity = 1.0f; if (!config.TryGetValue("dragSensitivity", ref dragSensitivity)) { dragSensitivity = 1.0f; } buttonObject.normalizationScalar = 0.01f * dragSensitivity; } else { throw new ArgumentException("Unable to create 'onDragY' event for COLLIDER_EVENT " + name); } } if (buttonObject.onDragX != null && buttonObject.onDragY != null) { config.TryGetValue("singleAxisDrag", ref buttonObject.singleAxisDrag); } }
internal MASPage(ConfigNode config, InternalProp prop, MASFlightComputer comp, MASMonitor monitor, Transform rootTransform) { if (!config.TryGetValue("name", ref name)) { throw new ArgumentException("Invalid or missing 'name' in MASPage"); } variableRegistrar = new VariableRegistrar(comp, prop); string[] softkeys = config.GetValues("softkey"); int numSoftkeys = softkeys.Length; for (int i = 0; i < numSoftkeys; ++i) { string[] pair = Utility.SplitVariableList(softkeys[i]); if (pair.Length == 2) { int id; if (int.TryParse(pair[0], out id)) { Action action = comp.GetAction(pair[1], prop); if (action != null) { softkeyAction[id] = action; } } } } ConfigNode[] hitboxes = config.GetNodes("hitbox"); int numHitboxes = hitboxes.Length; for (int i = 0; i < numHitboxes; ++i) { HitBox hb = InitHitBox(i, hitboxes[i], prop, comp); if (hb != null) { hitboxActions.Add(hb); } } string entryMethod = string.Empty; if (config.TryGetValue("onEntry", ref entryMethod)) { onEntry = comp.GetAction(entryMethod, prop); } string exitMethod = string.Empty; if (config.TryGetValue("onExit", ref exitMethod)) { onExit = comp.GetAction(exitMethod, prop); } pageRoot = new GameObject(); pageRoot.name = Utility.ComposeObjectName(this.GetType().Name, name, prop.propID); pageRoot.layer = rootTransform.gameObject.layer; pageRoot.transform.parent = rootTransform; pageRoot.transform.Translate(0.0f, 0.0f, 1.0f); float depth = 0.0f; ConfigNode[] components = config.GetNodes(); int numComponents = components.Length; if (Array.Exists(components, x => x.name == "SUB_PAGE")) { // Need to collate List <ConfigNode> newComponents = new List <ConfigNode>(); for (int i = 0; i < numComponents; ++i) { ConfigNode node = components[i]; if (node.name == "SUB_PAGE") { newComponents.AddRange(ResolveSubPage(node, monitor.fontSize)); } else { newComponents.Add(node); } } components = newComponents.ToArray(); numComponents = components.Length; } for (int i = 0; i < numComponents; ++i) { try { var pageComponent = CreatePageComponent(components[i], prop, comp, monitor, pageRoot.transform, depth); if (pageComponent != null) { component.Add(pageComponent); depth -= MASMonitor.depthDelta; } } catch (Exception e) { string componentName = string.Empty; if (!components[i].TryGetValue("name", ref componentName)) { componentName = "anonymous"; } string error = string.Format("Error configuring MASPage " + name + " " + config.name + " " + componentName + ":"); Utility.LogError(this, error); Utility.LogError(this, "{0}", e.ToString()); Utility.ComplainLoudly(error); } } if (numComponents > 256) { Utility.LogWarning(this, "{0} elements were used in MASPage {1}. This may exceed the number of supported elements.", numComponents, name); } }
/// <summary> /// Configure this module and its children. /// </summary> public void Start() { if (HighLogic.LoadedSceneIsEditor) { return; } try { MASFlightComputer comp = MASFlightComputer.Instance(internalProp.part); if (comp == null) { throw new ArgumentNullException("Unable to find MASFlightComputer in part - please check part configs"); } ConfigNode moduleConfig = Utility.GetPropModuleConfigNode(internalProp.propName, ClassName); if (moduleConfig == null) { throw new ArgumentNullException("No ConfigNode found!"); } int nodeCount = 0; ConfigNode[] actionNodes = moduleConfig.GetNodes(); for (int i = 0; i < actionNodes.Length; ++i) { try { IMASSubComponent action = CreateAction(actionNodes[i], internalProp, comp); if (action != null) { ++nodeCount; actions.Add(action); } } catch (Exception e) { string componentName = string.Empty; if (!actionNodes[i].TryGetValue("name", ref componentName)) { componentName = "anonymous"; } string message = string.Format("Error configuring prop #{0} ({1})", internalProp.propID, internalProp.propName); Utility.LogError(this, message); Utility.LogError(this, "Error in " + actionNodes[i].name + " " + componentName + ":"); Utility.LogError(this, "{0}", e.ToString()); Utility.ComplainLoudly(message); } } // If an initialization script was supplied, call it. if (!string.IsNullOrEmpty(startupScript)) { Action startup = comp.GetAction(startupScript, internalProp); startup(); } Utility.LogMessage(this, "Configuration complete in prop #{0} ({1}): {2} nodes created", internalProp.propID, internalProp.propName, nodeCount); } catch (Exception e) { string message = string.Format("Failed to configure prop #{0} ({1})", internalProp.propID, internalProp.propName); Utility.ComplainLoudly(message); Utility.LogError(this, message); Utility.LogError(this, e.ToString()); } }
internal MASPageMenu(ConfigNode config, InternalProp prop, MASFlightComputer comp, MASMonitor monitor, Transform pageRoot, float depth) : base(config, prop, comp) { this.prop = prop; this.comp = comp; if (!config.TryGetValue("maxLines", ref maxLines)) { maxLines = int.MaxValue; } if (maxLines < 1) { throw new ArgumentException("'maxLines' must be greater than zero in MENU " + name); } int itemPositionShift = 0; if (!config.TryGetValue("itemPositionShift", ref itemPositionShift)) { itemPositionShift = 0; } if (!config.TryGetValue("cursorPersistentName", ref cursorPersistentName)) { throw new ArgumentException("Missing 'cursorPersistentName' in MENU " + name); } config.TryGetValue("upSoftkey", ref upSoftkey); config.TryGetValue("downSoftkey", ref downSoftkey); config.TryGetValue("enterSoftkey", ref enterSoftkey); config.TryGetValue("homeSoftkey", ref homeSoftkey); config.TryGetValue("endSoftkey", ref endSoftkey); string localFonts = string.Empty; if (!config.TryGetValue("font", ref localFonts)) { localFonts = string.Empty; } string styleStr = string.Empty; style = FontStyle.Normal; if (config.TryGetValue("style", ref styleStr)) { style = MdVTextMesh.FontStyle(styleStr); } else { style = monitor.defaultStyle; } fontSize = Vector2.zero; if (!config.TryGetValue("fontSize", ref fontSize) || fontSize.x < 0.0f || fontSize.y < 0.0f) { fontSize = monitor.fontSize; } charAdvance = fontSize.x * itemPositionShift; lineAdvance = fontSize.y; defaultColor = monitor.textColor_; Color32 cursorColor; string cursorColorStr = string.Empty; if (!config.TryGetValue("cursorColor", ref cursorColorStr) || string.IsNullOrEmpty(cursorColorStr)) { cursorColor = monitor.textColor_; } else { cursorColor = Utility.ParseColor32(cursorColorStr, comp); } // Set up our text. textOrigin = pageRoot.position + new Vector3(monitor.screenSize.x * -0.5f, monitor.screenSize.y * 0.5f, depth); rootObject = new GameObject(); rootObject.name = Utility.ComposeObjectName(pageRoot.gameObject.name, this.GetType().Name, name, (int)(-depth / MASMonitor.depthDelta)); rootObject.layer = pageRoot.gameObject.layer; rootObject.transform.parent = pageRoot; rootObject.transform.position = textOrigin; string positionString = string.Empty; if (config.TryGetValue("position", ref positionString)) { string[] positions = Utility.SplitVariableList(positionString); if (positions.Length != 2) { throw new ArgumentException("position does not contain 2 values in MENU " + name); } variableRegistrar.RegisterVariableChangeCallback(positions[0], (double newValue) => { position.x = (float)newValue * monitor.fontSize.x; rootObject.transform.position = textOrigin + new Vector3(position.x, -position.y, 0.0f); updateMenu = true; }); variableRegistrar.RegisterVariableChangeCallback(positions[1], (double newValue) => { position.y = (float)newValue * monitor.fontSize.y; rootObject.transform.position = textOrigin + new Vector3(position.x, -position.y, 0.0f); updateMenu = true; }); } if (string.IsNullOrEmpty(localFonts)) { font = monitor.defaultFont; } else { font = MASLoader.GetFont(localFonts.Trim()); } cursorObject = new GameObject(); cursorObject.name = rootObject.name + "_cursor"; cursorObject.layer = rootObject.layer; cursorObject.transform.parent = rootObject.transform; cursorObject.transform.position = textOrigin; cursorText = cursorObject.AddComponent <MdVTextMesh>(); cursorText.material = new Material(MASLoader.shaders["MOARdV/TextMonitor"]); cursorText.SetFont(font, fontSize); cursorText.SetColor(cursorColor); cursorText.material.SetFloat(Shader.PropertyToID("_EmissiveFactor"), 1.0f); cursorText.fontStyle = style; string cursorPrompt = string.Empty; config.TryGetValue("cursor", ref cursorPrompt); // text, immutable, preserveWhitespace, comp, prop cursorText.SetText(cursorPrompt, false, true, comp, prop); string itemCountStr = string.Empty; config.TryGetValue("itemCount", ref itemCountStr); List <MenuItem> itemNodes = new List <MenuItem>(); ConfigNode[] menuItemConfigNodes = config.GetNodes("ITEM"); foreach (ConfigNode itemNode in menuItemConfigNodes) { try { MenuItem cpt = new MenuItem(itemNode, rootObject, font, fontSize, style, defaultColor, comp, prop, variableRegistrar, itemNodes.Count); itemNodes.Add(cpt); } catch (Exception e) { Utility.LogError(this, "Exception creating ITEM in MENU " + name); Utility.LogError(this, e.ToString()); } } if (itemNodes.Count == 0) { throw new ArgumentException("No valid ITEM nodes in MENU " + name); } menuItems = itemNodes.ToArray(); if (string.IsNullOrEmpty(itemCountStr)) { numMenuItems = menuItems.Length; softkeyUpAction = comp.GetAction(string.Format("fc.AddPersistentWrapped(\"{0}\", -1, 0, {1})", cursorPersistentName, numMenuItems), prop); softkeyDownAction = comp.GetAction(string.Format("fc.AddPersistentWrapped(\"{0}\", 1, 0, {1})", cursorPersistentName, numMenuItems), prop); softkeyEndAction = comp.GetAction(string.Format("fc.SetPersistent(\"{0}\", {1})", cursorPersistentName, numMenuItems - 1), prop); } else if (itemNodes.Count > 1) { throw new ArgumentException("Only one valid ITEM node may be used in dynamic MENU " + name); } else { dynamicMenuTemplate = menuItemConfigNodes[0].CreateCopy(); } variableRegistrar.RegisterVariableChangeCallback(string.Format("fc.GetPersistentAsNumber(\"{0}\")", cursorPersistentName), CursorMovedCallback); softkeyHomeAction = comp.GetAction(string.Format("fc.SetPersistent(\"{0}\", 0)", cursorPersistentName), prop); if (!string.IsNullOrEmpty(itemCountStr)) { variableRegistrar.RegisterVariableChangeCallback(itemCountStr, MenuCountCallback); } string masterVariableName = string.Empty; if (config.TryGetValue("variable", ref masterVariableName)) { rootObject.SetActive(false); variableRegistrar.RegisterVariableChangeCallback(masterVariableName, VariableCallback); } else { currentState = true; rootObject.SetActive(true); } RenderPage(false); }
internal MenuItem(ConfigNode itemNode, GameObject rootObject, Font font, Vector2 fontSize, FontStyle style, Color32 defaultColor, MASFlightComputer comp, InternalProp prop, VariableRegistrar variableRegistrar, int itemId) { string itemIdStr = itemId.ToString(); if (!itemNode.TryGetValue("name", ref name)) { name = "anonymous"; } string selectEventStr = string.Empty; if (itemNode.TryGetValue("selectEvent", ref selectEventStr)) { selectEventStr = selectEventStr.Replace("%ITEMID%", itemIdStr); selectEvent = comp.GetAction(selectEventStr, prop); } enabled = true; string activeColorStr = string.Empty; if (!itemNode.TryGetValue("activeColor", ref activeColorStr) || string.IsNullOrEmpty(activeColorStr)) { activeColor = defaultColor; } else { activeColor = Utility.ParseColor32(activeColorStr, comp); } string activeTextStr = string.Empty; if (!itemNode.TryGetValue("activeText", ref activeTextStr)) { throw new ArgumentException("Missing 'activeText' in ITEM " + name); } activeTextStr = activeTextStr.Replace("%ITEMID%", itemIdStr); activeObject = new GameObject(); activeObject.name = rootObject.name + "_activeitem_" + name; activeObject.layer = rootObject.layer; activeObject.transform.parent = rootObject.transform; activeObject.transform.position = rootObject.transform.position; activeText = activeObject.AddComponent <MdVTextMesh>(); activeText.material = new Material(MASLoader.shaders["MOARdV/TextMonitor"]); activeText.SetFont(font, fontSize); activeText.SetColor(activeColor); activeText.material.SetFloat(Shader.PropertyToID("_EmissiveFactor"), 1.0f); activeText.fontStyle = style; activeText.SetText(activeTextStr, false, true, comp, prop); activeText.SetRenderEnabled(false); string passiveColorStr = string.Empty; if (!itemNode.TryGetValue("passiveColor", ref passiveColorStr) || string.IsNullOrEmpty(passiveColorStr)) { passiveColor = activeColor; } else { passiveColor = Utility.ParseColor32(passiveColorStr, comp); } string passiveTextStr = string.Empty; if (!itemNode.TryGetValue("passiveText", ref passiveTextStr)) { passiveObject = activeObject; passiveText = activeText; } else { passiveTextStr = passiveTextStr.Replace("%ITEMID%", itemIdStr); passiveObject = new GameObject(); passiveObject.name = rootObject.name + "_passiveitem_" + name; passiveObject.layer = rootObject.layer; passiveObject.transform.parent = rootObject.transform; passiveObject.transform.position = rootObject.transform.position; passiveText = passiveObject.AddComponent <MdVTextMesh>(); passiveText.material = new Material(MASLoader.shaders["MOARdV/TextMonitor"]); passiveText.SetFont(font, fontSize); passiveText.SetColor(passiveColor); passiveText.material.SetFloat(Shader.PropertyToID("_EmissiveFactor"), 1.0f); passiveText.fontStyle = style; passiveText.SetText(passiveTextStr, false, true, comp, prop); passiveText.SetRenderEnabled(false); } string activeVariableStr = string.Empty; if (itemNode.TryGetValue("activeVariable", ref activeVariableStr)) { active = false; activeVariableStr = activeVariableStr.Replace("%ITEMID%", itemIdStr); variableRegistrar.RegisterVariableChangeCallback(activeVariableStr, (double newValue) => active = (newValue > 0.0)); } else { active = true; } string enabledVariableStr = string.Empty; if (itemNode.TryGetValue("enabledVariable", ref enabledVariableStr)) { usesDisabled = true; enabled = false; enabledVariableStr = enabledVariableStr.Replace("%ITEMID%", itemIdStr); variableRegistrar.RegisterVariableChangeCallback(enabledVariableStr, (double newValue) => enabled = (newValue > 0.0)); string disabledTextStr = string.Empty; if (!itemNode.TryGetValue("disabledText", ref disabledTextStr)) { throw new ArgumentException("Missing 'disabledText' in ITEM " + name); } disabledTextStr = disabledTextStr.Replace("%ITEMID%", itemIdStr); Color32 disabledColor; string disabledColorStr = string.Empty; if (!itemNode.TryGetValue("disabledColor", ref disabledColorStr) || string.IsNullOrEmpty(disabledColorStr)) { disabledColor = defaultColor; } else { disabledColor = Utility.ParseColor32(disabledColorStr, comp); } disabledObject = new GameObject(); disabledObject.name = rootObject.name + "_disableditem_" + name; disabledObject.layer = rootObject.layer; disabledObject.transform.parent = rootObject.transform; disabledObject.transform.position = rootObject.transform.position; disabledText = disabledObject.AddComponent <MdVTextMesh>(); disabledText.material = new Material(MASLoader.shaders["MOARdV/TextMonitor"]); disabledText.SetFont(font, fontSize); disabledText.SetColor(disabledColor); disabledText.material.SetFloat(Shader.PropertyToID("_EmissiveFactor"), 1.0f); disabledText.fontStyle = style; disabledText.SetText(disabledTextStr, false, true, comp, prop); disabledText.SetRenderEnabled(false); } else { enabled = true; usesDisabled = false; } }
internal MASPage(ConfigNode config, InternalProp prop, MASFlightComputer comp, MASMonitor monitor, Transform rootTransform) { if (!config.TryGetValue("name", ref name)) { throw new ArgumentException("Invalid or missing 'name' in MASPage"); } string[] softkeys = config.GetValues("softkey"); int numSoftkeys = softkeys.Length; for (int i = 0; i < numSoftkeys; ++i) { string[] pair = Utility.SplitVariableList(softkeys[i]); if (pair.Length == 2) { int id; if (int.TryParse(pair[0], out id)) { Action action = comp.GetAction(pair[1], prop); if (action != null) { softkeyAction[id] = action; } } } } string entryMethod = string.Empty; if (config.TryGetValue("onEntry", ref entryMethod)) { onEntry = comp.GetAction(entryMethod, prop); } string exitMethod = string.Empty; if (config.TryGetValue("onExit", ref exitMethod)) { onExit = comp.GetAction(exitMethod, prop); } pageRoot = new GameObject(); pageRoot.name = Utility.ComposeObjectName(this.GetType().Name, name, prop.propID); pageRoot.layer = rootTransform.gameObject.layer; pageRoot.transform.parent = rootTransform; pageRoot.transform.Translate(0.0f, 0.0f, 1.0f); float depth = 0.0f; ConfigNode[] components = config.GetNodes(); int numComponents = components.Length; if (Array.Exists(components, x => x.name == "SUB_PAGE")) { // Need to collate List <ConfigNode> newComponents = new List <ConfigNode>(); for (int i = 0; i < numComponents; ++i) { ConfigNode node = components[i]; if (node.name == "SUB_PAGE") { string subPageName = string.Empty; // Test for 'name' if (!node.TryGetValue("name", ref subPageName)) { throw new ArgumentException("No 'name' field in SUB_PAGE found in MASPage " + name); } // Test for 'variable' string variableString = string.Empty; bool editVariable = (node.TryGetValue("variable", ref variableString)); // Test for 'position' bool editPosition = false; string[] position = new string[0]; string positionString = string.Empty; if (node.TryGetValue("position", ref positionString)) { position = Utility.SplitVariableList(positionString); if (position.Length != 2) { throw new ArgumentException("Invalid number of entries in 'position' for SUB_PAGE '" + subPageName + "' in MASPage " + name); } editPosition = true; } // Find the sub page. List <ConfigNode> subPageNodes; if (!MASLoader.subPages.TryGetValue(subPageName, out subPageNodes)) { throw new ArgumentException("Unable to find MAS_SUB_PAGE '" + subPageName + "' for SUB_PAGE found in MASPage " + name); } if (editVariable || editPosition) { for (int subPageNodeIdx = 0; subPageNodeIdx < subPageNodes.Count; ++subPageNodeIdx) { ConfigNode subNode = subPageNodes[subPageNodeIdx].CreateCopy(); string subNodeName = string.Empty; if (!subNode.TryGetValue("name", ref subNodeName)) { subNodeName = "anonymous"; } if (editVariable) { string currentVariable = string.Empty; if (subNode.TryGetValue("variable", ref currentVariable)) { subNode.SetValue("variable", string.Format("({0}) and ({1})", variableString, currentVariable)); } else { subNode.SetValue("variable", variableString, true); } } if (editPosition) { string currentPositionString = string.Empty; if (subNode.TryGetValue("position", ref currentPositionString)) { string[] currentPosition = Utility.SplitVariableList(currentPositionString); if (currentPosition.Length != 2) { throw new ArgumentException("Invalid number of values in 'position' for node '" + subNodeName + "' in MAS_SUB_PAGE " + subPageName); } if (IsTextNode(subNode)) { subNode.SetValue("position", string.Format("{4} * ({0}) + ({1}), {5} * ({2}) + ({3})", position[0], currentPosition[0], position[1], currentPosition[1], 1.0f / monitor.fontSize.x, 1.0f / monitor.fontSize.y)); } else { subNode.SetValue("position", string.Format("({0}) + ({1}), ({2}) + ({3})", position[0], currentPosition[0], position[1], currentPosition[1])); } } else { if (IsTextNode(subNode)) { subNode.SetValue("position", string.Format("{2} * {0}, {3} * {1}", position[0], position[1], 1.0f / monitor.fontSize.x, 1.0f / monitor.fontSize.y), true); } else { subNode.SetValue("position", string.Format("{0}, {1}", position[0], position[1]), true); } } } newComponents.Add(subNode); } } else { // Simple and fast case: no edits required. newComponents.AddRange(subPageNodes); } } else { newComponents.Add(node); } } components = newComponents.ToArray(); numComponents = components.Length; } for (int i = 0; i < numComponents; ++i) { try { var pageComponent = CreatePageComponent(components[i], prop, comp, monitor, pageRoot.transform, depth); if (pageComponent != null) { component.Add(pageComponent); depth -= MASMonitor.depthDelta; } } catch (Exception e) { string componentName = string.Empty; if (!components[i].TryGetValue("name", ref componentName)) { componentName = "anonymous"; } string error = string.Format("Error configuring MASPage " + name + " " + config.name + " " + componentName + ":"); Utility.LogError(this, error); Utility.LogError(this, "{0}", e.ToString()); Utility.ComplainLoudly(error); } } if (numComponents > 256) { Utility.LogWarning(this, "{0} elements were used in MASPage {1}. This may exceed the number of supported elements.", numComponents, name); } }