public MonitorPage(int idNum, ConfigNode node, RasterPropMonitor thatMonitor) { ourMonitor = thatMonitor; screenWidth = ourMonitor.screenWidth; screenHeight = ourMonitor.screenHeight; cameraAspect = ourMonitor.cameraAspect; cameraObject = thatMonitor.cameraStructure; defaultColor = ourMonitor.defaultFontTintValue; screenXMin = 0; screenYMin = 0; pageNumber = idNum; isMutable = false; if (!node.HasData) { throw new ArgumentException("Empty page?"); } if (node.HasValue("name")) { string value = node.GetValue("name").Trim(); if (!IsValidPageName(value)) { JUtil.LogMessage(ourMonitor, "Warning, name given for page #{0} is invalid, ignoring.", pageNumber); } else { name = value; } } else { JUtil.LogMessage(ourMonitor, "Warning, page #{0} has no name. It's much better if it does.", pageNumber); } isDefault |= node.HasValue("default"); if (node.HasValue("button")) { SmarterButton.CreateButton(thatMonitor.internalProp, node.GetValue("button"), this, thatMonitor.PageButtonClick); } // Page locking system -- simple locking: simpleLockingPage |= node.HasValue("lockingPage"); // and name-based locking. if (node.HasValue("disableSwitchingTo")) { string[] tokens = node.GetValue("disableSwitchingTo").Split(','); foreach (string token in tokens) { disableSwitchingTo.Add(token.Trim()); } } unlocker |= node.HasValue("unlockerPage"); if (node.HasValue("localMargins")) { Vector4 margindata = ConfigNode.ParseVector4(node.GetValue("localMargins")); screenXMin = (int)margindata.x; screenYMin = (int)margindata.y; screenWidth = screenWidth - (int)margindata.z - screenXMin; screenHeight = screenHeight - (int)margindata.w - screenYMin; } pageFont = node.GetInt("defaultFontNumber") ?? 0; if (node.HasValue("defaultFontTint")) { defaultColor = ConfigNode.ParseColor32(node.GetValue("defaultFontTint")); } if (node.HasValue("techsRequired")) { techsRequired = node.GetValue("techsRequired").Split(new[] { ' ', ',', ';', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList(); } if (node.HasValue("fallbackOnNoTech")) { fallbackPageName = node.GetValue("fallbackOnNoTech").Trim(); } if (node.HasNode("CONTEXTREDIRECT")) { foreach (string content in node.GetNode("CONTEXTREDIRECT").GetValues("redirect")) { string[] tokens = content.Split(','); if (tokens.Length > 2 || !IsValidPageName(tokens[0].Trim()) || !IsValidPageName(tokens[1].Trim())) { JUtil.LogMessage(ourMonitor, "Warning, invalid page redirect statement on page #{0}.", pageNumber); continue; } redirectPages[tokens[0].Trim()] = tokens[1].Trim(); } const string valueError = "Warning, invalid global button redirect statement on page #{0}: {1}"; foreach (string content in node.GetNode("CONTEXTREDIRECT").GetValues("renumber")) { string[] tokens = content.Split(','); if (tokens.Length > 2) { JUtil.LogMessage(ourMonitor, valueError, pageNumber, "requires two arguments."); continue; } int from, to; if (!int.TryParse(tokens[0], out from) || !int.TryParse(tokens[1], out to)) { JUtil.LogMessage(ourMonitor, valueError, pageNumber, "something isn't a number."); continue; } redirectGlobals[from] = to; } JUtil.LogMessage(this, "Page '{2}' (#{0}) registers {1} page redirects and {3} global button redirects.", idNum, redirectPages.Count, name, redirectGlobals.Count); } foreach (ConfigNode handlerNode in node.GetNodes("PAGEHANDLER")) { MonoBehaviour handlerModule; HandlerSupportMethods supportMethods; MethodInfo handlerMethod = InstantiateHandler(handlerNode, ourMonitor, out handlerModule, out supportMethods); if (handlerMethod != null && handlerModule != null) { try { pageHandlerMethod = (Func<int, int, string>)Delegate.CreateDelegate(typeof(Func<int, int, string>), handlerModule, handlerMethod); } catch { JUtil.LogErrorMessage(ourMonitor, "Incorrect signature for the page handler method {0}", handlerModule.name); break; } pageHandlerS = supportMethods; isMutable = true; pageHandlerModule = handlerModule; break; } } if (pageHandlerMethod == null) { if (node.HasValue("text")) { text = JUtil.LoadPageDefinition(node.GetValue("text")); isMutable |= text.IndexOf("$&$", StringComparison.Ordinal) != -1; } } if (node.HasValue("textOverlay")) { textOverlayBuffer = JUtil.LoadPageDefinition(node.GetValue("textOverlay")).Split(JUtil.LineSeparator, StringSplitOptions.None); } foreach (ConfigNode handlerNode in node.GetNodes("BACKGROUNDHANDLER")) { MonoBehaviour handlerModule; HandlerSupportMethods supportMethods; MethodInfo handlerMethod = InstantiateHandler(handlerNode, ourMonitor, out handlerModule, out supportMethods); if (handlerMethod != null && handlerModule != null) { try { backgroundHandlerMethod = (Func<RenderTexture, float, bool>)Delegate.CreateDelegate(typeof(Func<RenderTexture, float, bool>), handlerModule, handlerMethod); } catch { JUtil.LogErrorMessage(ourMonitor, "Incorrect signature for the background handler method {0}", handlerModule.name); break; } backgroundHandlerS = supportMethods; isMutable = true; showNoSignal = node.HasValue("showNoSignal"); background = BackgroundType.Handler; backgroundHandlerModule = handlerModule; break; } } if (background == BackgroundType.None) { if (node.HasValue("cameraTransform")) { isMutable = true; background = BackgroundType.Camera; camera = node.GetValue("cameraTransform"); cameraFOV = defaultFOV; cameraFlickerChance = node.GetFloat("flickerChance") ?? 0; cameraFlickerRange = node.GetInt("flickerRange") ?? 0; if (node.HasValue("fov")) { float fov; cameraFOV = float.TryParse(node.GetValue("fov"), out fov) ? fov : defaultFOV; } else if (node.HasValue("zoomFov") && node.HasValue("zoomButtons")) { Vector3 zoomFov = ConfigNode.ParseVector3(node.GetValue("zoomFov")); Vector2 zoomButtons = ConfigNode.ParseVector2(node.GetValue("zoomButtons")); if ((int)zoomFov.z != 0 && ((int)zoomButtons.x != (int)zoomButtons.y)) { maxFOV = Math.Max(zoomFov.x, zoomFov.y); minFOV = Math.Min(zoomFov.x, zoomFov.y); zoomSteps = (int)zoomFov.z; zoomUpButton = (int)zoomButtons.x; zoomDownButton = (int)zoomButtons.y; zoomSkip = (maxFOV - minFOV) / zoomSteps; currentZoom = 0; cameraFOV = maxFOV; } else { JUtil.LogMessage(ourMonitor, "Ignored invalid camera zoom settings on page {0}.", pageNumber); } } } } if (background == BackgroundType.None) { if (node.HasValue("textureURL")) { string textureURL = node.GetValue("textureURL").EnforceSlashes(); if (GameDatabase.Instance.ExistsTexture(textureURL)) { backgroundTexture = GameDatabase.Instance.GetTexture(textureURL, false); background = BackgroundType.Texture; } } } if (node.HasValue("textureInterlayURL")) { string textureURL = node.GetValue("textureInterlayURL").EnforceSlashes(); if (GameDatabase.Instance.ExistsTexture(textureURL)) { interlayTexture = GameDatabase.Instance.GetTexture(textureURL, false); } else { JUtil.LogErrorMessage(ourMonitor, "Interlay texture could not be loaded."); } } if (node.HasValue("textureOverlayURL")) { string textureURL = node.GetValue("textureOverlayURL").EnforceSlashes(); if (GameDatabase.Instance.ExistsTexture(textureURL)) { overlayTexture = GameDatabase.Instance.GetTexture(textureURL, false); } else { JUtil.LogErrorMessage(ourMonitor, "Overlay texture {0} could not be loaded.", textureURL); } } }
private static MethodInfo InstantiateHandler(ConfigNode node, RasterPropMonitor ourMonitor, out MonoBehaviour moduleInstance, out HandlerSupportMethods support) { moduleInstance = null; support.activate = null; support.buttonClick = null; support.buttonRelease = null; support.getHandlerReferences = null; if (node.HasValue("name") && node.HasValue("method")) { string moduleName = node.GetValue("name"); string methodName = node.GetValue("method"); var handlerConfiguration = new ConfigNode("MODULE"); node.CopyTo(handlerConfiguration); MonoBehaviour thatModule = null; // Part modules are different in that they remain instantiated when you switch vessels, while the IVA doesn't. // Because of this RPM can't instantiate partmodule-based handlers itself -- there's no way to tell if this was done already or not. // Which means there can only be one instance of such a handler per pod, and it can't receive configuration values from RPM. if (node.HasValue("isPartModule")) { foreach (PartModule potentialModule in ourMonitor.part.Modules) { if (potentialModule.ClassName == moduleName) { thatModule = potentialModule; break; } } } else if (node.HasValue("multiHandler")) { foreach (InternalModule potentialModule in ourMonitor.internalProp.internalModules) { if (potentialModule.ClassName == moduleName) { thatModule = potentialModule; break; } } } if (thatModule == null && !node.HasValue("isPartModule")) { try { thatModule = ourMonitor.internalProp.AddModule(handlerConfiguration); } catch { JUtil.LogErrorMessage(ourMonitor, "Caught exception when trying to instantiate module '{0}'. Something's fishy here", moduleName); } if (thatModule != null) { try { MethodInfo configureMethod = thatModule.GetType().GetMethod("Configure", BindingFlags.Instance | BindingFlags.Public); ParameterInfo[] parms = configureMethod.GetParameters(); if (parms.Length == 1 && parms[0].ParameterType == typeof(ConfigNode)) { configureMethod.Invoke(thatModule, new object[] { handlerConfiguration }); } } catch//(Exception e) { //JUtil.LogMessage(ourMonitor, "Exception {0}", e); //JUtil.LogMessage(ourMonitor, "Module didn't have a Configure method. This could be normal."); } } } if (thatModule == null) { JUtil.LogMessage(ourMonitor, "Warning, handler module \"{0}\" could not be loaded. This could be perfectly normal.", moduleName); return(null); } const string sigError = "Incorrect signature of the {0} method in {1}, ignoring option. If it doesn't work later, that's why."; if (node.HasValue("pageActiveMethod")) { foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("pageActiveMethod")) { try { support.activate = (Action <bool, int>)Delegate.CreateDelegate(typeof(Action <bool, int>), thatModule, m); } catch { JUtil.LogErrorMessage(ourMonitor, sigError, "page activation", moduleName); } break; } } } if (node.HasValue("buttonClickMethod")) { foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("buttonClickMethod")) { try { support.buttonClick = (Action <int>)Delegate.CreateDelegate(typeof(Action <int>), thatModule, m); } catch { JUtil.LogErrorMessage(ourMonitor, sigError, "button click", moduleName); } break; } } } if (node.HasValue("buttonReleaseMethod")) { foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("buttonReleaseMethod")) { try { support.buttonRelease = (Action <int>)Delegate.CreateDelegate(typeof(Action <int>), thatModule, m); } catch { JUtil.LogErrorMessage(ourMonitor, sigError, "button release", moduleName); } break; } } } if (node.HasValue("getHandlerReferencesMethod")) { foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("getHandlerReferencesMethod")) { try { support.getHandlerReferences = (Action <MonoBehaviour, MonoBehaviour>)Delegate.CreateDelegate(typeof(Action <MonoBehaviour, MonoBehaviour>), thatModule, m); } catch { JUtil.LogErrorMessage(ourMonitor, sigError, "handler references", moduleName); } break; } } } moduleInstance = thatModule; foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == methodName) { return(m); } } } return(null); }
private static MethodInfo InstantiateHandler(ConfigNode node, RasterPropMonitor ourMonitor, out MonoBehaviour moduleInstance, out HandlerSupportMethods support) { moduleInstance = null; support.activate = null; support.buttonClick = null; support.buttonRelease = null; support.getHandlerReferences = null; if (node.HasValue("name") && node.HasValue("method")) { string moduleName = node.GetValue("name"); string methodName = node.GetValue("method"); var handlerConfiguration = new ConfigNode("MODULE"); node.CopyTo(handlerConfiguration); MonoBehaviour thatModule = null; // Part modules are different in that they remain instantiated when you switch vessels, while the IVA doesn't. // Because of this RPM can't instantiate partmodule-based handlers itself -- there's no way to tell if this was done already or not. // Which means there can only be one instance of such a handler per pod, and it can't receive configuration values from RPM. if (node.HasValue("isPartModule")) { foreach (PartModule potentialModule in ourMonitor.part.Modules) { if (potentialModule.ClassName == moduleName) { thatModule = potentialModule; break; } } } else if (node.HasValue("multiHandler")) { foreach (InternalModule potentialModule in ourMonitor.internalProp.internalModules) { if (potentialModule.ClassName == moduleName) { thatModule = potentialModule; break; } } } if (thatModule == null && !node.HasValue("isPartModule")) { try { thatModule = ourMonitor.internalProp.AddModule(handlerConfiguration); } catch { JUtil.LogErrorMessage(ourMonitor, "Caught exception when trying to instantiate module '{0}'. Something's fishy here", moduleName); } } if (thatModule == null) { JUtil.LogMessage(ourMonitor, "Warning, handler module \"{0}\" could not be loaded. This could be perfectly normal.", moduleName); return null; } const string sigError = "Incorrect signature of the {0} method in {1}, ignoring option. If it doesn't work later, that's why."; if (node.HasValue("pageActiveMethod")) { foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("pageActiveMethod")) { try { support.activate = (Action<bool, int>)Delegate.CreateDelegate(typeof(Action<bool, int>), thatModule, m); } catch { JUtil.LogErrorMessage(ourMonitor, sigError, "page activation", moduleName); } break; } } } if (node.HasValue("buttonClickMethod")) { foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("buttonClickMethod")) { try { support.buttonClick = (Action<int>)Delegate.CreateDelegate(typeof(Action<int>), thatModule, m); } catch { JUtil.LogErrorMessage(ourMonitor, sigError, "button click", moduleName); } break; } } } if (node.HasValue("buttonReleaseMethod")) { foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("buttonReleaseMethod")) { try { support.buttonRelease = (Action<int>)Delegate.CreateDelegate(typeof(Action<int>), thatModule, m); } catch { JUtil.LogErrorMessage(ourMonitor, sigError, "button release", moduleName); } break; } } } if (node.HasValue("getHandlerReferencesMethod")) { foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == node.GetValue("getHandlerReferencesMethod")) { try { support.getHandlerReferences = (Action<MonoBehaviour, MonoBehaviour>)Delegate.CreateDelegate(typeof(Action<MonoBehaviour, MonoBehaviour>), thatModule, m); } catch { JUtil.LogErrorMessage(ourMonitor, sigError, "handler references", moduleName); } break; } } } moduleInstance = thatModule; foreach (MethodInfo m in thatModule.GetType().GetMethods()) { if (m.Name == methodName) { return m; } } } return null; }
public MonitorPage(int idNum, ConfigNode node, RasterPropMonitor thatMonitor) { ourMonitor = thatMonitor; screenWidth = ourMonitor.screenWidth; screenHeight = ourMonitor.screenHeight; cameraAspect = ourMonitor.cameraAspect; cameraObject = thatMonitor.cameraStructure; defaultColor = ourMonitor.defaultFontTintValue; screenXMin = 0; screenYMin = 0; pageNumber = idNum; isMutable = false; if (!node.HasData) { throw new ArgumentException("Empty page?"); } if (node.HasValue("name")) { string value = node.GetValue("name").Trim(); if (!IsValidPageName(value)) { JUtil.LogMessage(ourMonitor, "Warning, name given for page #{0} is invalid, ignoring.", pageNumber); } else { name = value; } } else { JUtil.LogMessage(ourMonitor, "Warning, page #{0} has no name. It's much better if it does.", pageNumber); } isDefault |= node.HasValue("default"); if (node.HasValue("button")) { SmarterButton.CreateButton(thatMonitor.internalProp, node.GetValue("button"), this, thatMonitor.PageButtonClick); } // Page locking system -- simple locking: simpleLockingPage |= node.HasValue("lockingPage"); // and name-based locking. if (node.HasValue("disableSwitchingTo")) { string[] tokens = node.GetValue("disableSwitchingTo").Split(','); foreach (string token in tokens) { disableSwitchingTo.Add(token.Trim()); } } unlocker |= node.HasValue("unlockerPage"); if (node.HasValue("localMargins")) { Vector4 margindata = ConfigNode.ParseVector4(node.GetValue("localMargins")); screenXMin = (int)margindata.x; screenYMin = (int)margindata.y; screenWidth = screenWidth - (int)margindata.z - screenXMin; screenHeight = screenHeight - (int)margindata.w - screenYMin; } pageFont = node.GetInt("defaultFontNumber") ?? 0; if (node.HasValue("defaultFontTint")) { defaultColor = ConfigNode.ParseColor32(node.GetValue("defaultFontTint")); } if (node.HasValue("techsRequired")) { techsRequired = node.GetValue("techsRequired").Split(new[] { ' ', ',', ';', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList(); } if (node.HasValue("fallbackOnNoTech")) { fallbackPageName = node.GetValue("fallbackOnNoTech").Trim(); } if (node.HasNode("CONTEXTREDIRECT")) { ConfigNode[] redirectnodes = node.GetNodes("CONTEXTREDIRECT"); for (int i = 0; i < redirectnodes.Length; ++i) { string[] redirects = redirectnodes[i].GetValues("redirect"); for (int j = 0; j < redirects.Length; ++j) { string[] tokens = redirects[j].Split(','); if (tokens.Length > 2 || !IsValidPageName(tokens[0].Trim()) || !IsValidPageName(tokens[1].Trim())) { JUtil.LogMessage(ourMonitor, "Warning, invalid page redirect statement on page #{0}.", pageNumber); continue; } redirectPages[tokens[0].Trim()] = tokens[1].Trim(); } string[] renumbers = redirectnodes[i].GetValues("renumber"); for (int j = 0; j < renumbers.Length; ++j) { string[] tokens = renumbers[j].Split(','); if (tokens.Length > 2) { JUtil.LogMessage(ourMonitor, "Warning, invalid global button redirect statement on page #{0}: requires two arguments.", pageNumber); continue; } int from, to; if (!int.TryParse(tokens[0], out from) || !int.TryParse(tokens[1], out to)) { JUtil.LogMessage(ourMonitor, "Warning, invalid global button redirect statement on page #{0}: something isn't a number", pageNumber); continue; } redirectGlobals[from] = to; } } JUtil.LogMessage(this, "Page '{2}' (#{0}) registers {1} page redirects and {3} global button redirects.", idNum, redirectPages.Count, name, redirectGlobals.Count); } foreach (ConfigNode handlerNode in node.GetNodes("PAGEHANDLER")) { MonoBehaviour handlerModule; HandlerSupportMethods supportMethods; MethodInfo handlerMethod = InstantiateHandler(handlerNode, ourMonitor, out handlerModule, out supportMethods); if (handlerMethod != null && handlerModule != null) { try { pageHandlerMethod = (Func <int, int, string>)Delegate.CreateDelegate(typeof(Func <int, int, string>), handlerModule, handlerMethod); } catch { JUtil.LogErrorMessage(ourMonitor, "Incorrect signature for the page handler method {0}", handlerModule.name); break; } pageHandlerS = supportMethods; isMutable = true; pageHandlerModule = handlerModule; break; } } if (pageHandlerMethod == null) { if (node.HasValue("text")) { text = JUtil.LoadPageDefinition(node.GetValue("text")); isMutable |= text.IndexOf("$&$", StringComparison.Ordinal) != -1; } } if (node.HasValue("textOverlay")) { textOverlay = JUtil.LoadPageDefinition(node.GetValue("textOverlay")); } foreach (ConfigNode handlerNode in node.GetNodes("BACKGROUNDHANDLER")) { MonoBehaviour handlerModule; HandlerSupportMethods supportMethods; MethodInfo handlerMethod = InstantiateHandler(handlerNode, ourMonitor, out handlerModule, out supportMethods); if (handlerMethod != null && handlerModule != null) { try { backgroundHandlerMethod = (Func <RenderTexture, float, bool>)Delegate.CreateDelegate(typeof(Func <RenderTexture, float, bool>), handlerModule, handlerMethod); } catch { JUtil.LogErrorMessage(ourMonitor, "Incorrect signature for the background handler method {0}", handlerModule.name); break; } backgroundHandlerS = supportMethods; isMutable = true; showNoSignal = node.HasValue("showNoSignal"); background = BackgroundType.Handler; backgroundHandlerModule = handlerModule; break; } } if (background == BackgroundType.None) { if (node.HasValue("cameraTransform")) { isMutable = true; background = BackgroundType.Camera; camera = node.GetValue("cameraTransform"); cameraFOV = defaultFOV; cameraFlickerChance = node.GetFloat("flickerChance") ?? 0; cameraFlickerRange = node.GetInt("flickerRange") ?? 0; if (node.HasValue("fov")) { float fov; cameraFOV = float.TryParse(node.GetValue("fov"), out fov) ? fov : defaultFOV; } else if (node.HasValue("zoomFov") && node.HasValue("zoomButtons")) { Vector3 zoomFov = ConfigNode.ParseVector3(node.GetValue("zoomFov")); Vector2 zoomButtons = ConfigNode.ParseVector2(node.GetValue("zoomButtons")); if ((int)zoomFov.z != 0 && ((int)zoomButtons.x != (int)zoomButtons.y)) { maxFOV = Math.Max(zoomFov.x, zoomFov.y); minFOV = Math.Min(zoomFov.x, zoomFov.y); zoomSteps = (int)zoomFov.z; zoomUpButton = (int)zoomButtons.x; zoomDownButton = (int)zoomButtons.y; zoomSkip = (maxFOV - minFOV) / zoomSteps; currentZoom = 0; cameraFOV = maxFOV; } else { JUtil.LogMessage(ourMonitor, "Ignored invalid camera zoom settings on page {0}.", pageNumber); } } } } if (background == BackgroundType.None) { if (node.HasValue("textureURL")) { string textureURL = node.GetValue("textureURL").EnforceSlashes(); if (GameDatabase.Instance.ExistsTexture(textureURL)) { backgroundTexture = GameDatabase.Instance.GetTexture(textureURL, false); background = BackgroundType.Texture; } } } if (node.HasValue("textureInterlayURL")) { string textureURL = node.GetValue("textureInterlayURL").EnforceSlashes(); if (GameDatabase.Instance.ExistsTexture(textureURL)) { interlayTexture = GameDatabase.Instance.GetTexture(textureURL, false); } else { JUtil.LogErrorMessage(ourMonitor, "Interlay texture {0} could not be loaded.", textureURL); } } if (node.HasValue("textureOverlayURL")) { string textureURL = node.GetValue("textureOverlayURL").EnforceSlashes(); if (GameDatabase.Instance.ExistsTexture(textureURL)) { overlayTexture = GameDatabase.Instance.GetTexture(textureURL, false); } else { JUtil.LogErrorMessage(ourMonitor, "Overlay texture {0} could not be loaded.", textureURL); } } }