Skip to content

Page handlers

MOARdV edited this page Sep 5, 2015 · 42 revisions

A Page Handler is the most basic variant of an RPM plugin. To make a RasterPropMonitor page handler, you just need to make an InternalModule with an extra public method that takes two int arguments and returns a string. That's it. To use one, configure the prop like this:

		PAGE
		{
			button = ThatButtonTransform
			PAGEHANDLER
			{
				name = YourClassName
				method = TheMethodToCall
			}
		}

With that configuration, RasterPropMonitor will automatically load your module into the prop, and pass it the entirety of PAGEHANDLER block, so you can load the variables from there as KSPFields, as if you were being loaded from a prop.cfg directly. Then, whenever a screen update timer calls for recalculating the page text, it will call the method you gave, and you can return whatever text you want. The int arguments are the screen width and height in characters respectively, so you can take the screen size into account: public string Method(int screenWidth,int screenHeight)

The return string is the entire screen with Environment.NewLine marking the line breaks, and it will be processed exactly like RasterPropMonitor's own page definition file. Anything that doesn't fit into the screen will be smoothly ignored.

There are some optional parameters, which don't have to be present or handled, but these names are reserved:

  • pageActiveMethod -- This must be the name of a method that returns void and takes a single bool argument and a single int argument. (public void pageActiveMethod(bool pageActive,int pageNumber)) If this option is present, the method with that name will be called whenever the page is activated (with the value of true) and whenever it is deactivated (with the value of false). The integer argument will contain the page number, starting with zero -- pages are numbered in the order they are declared. Your module is active all the time, but only called occasionally -- so if you want to handle extra special events or suspend processing when your page is not active, this is the way to do it.
  • buttonClickMethod -- This must be the name of a method that returns void and takes a single int argument. (public void buttonClickMethod(int buttonNumber)) If the monitor has any globalButtons defined, these will be handled by the monitor, and the number of button in the list of globalButtons will be passed to your buttonClickMethod so you can act upon it. It's recommended to keep which button ID is understood as what configurable, because there are a variety of monitor props in current use.
  • buttonReleaseMethod -- This works the same as buttonClickMethod, (public void buttonReleaseMethod(int buttonNumber)) but is getting called when the globalButton is released.
  • getHandlerReferencesMethod -- This method, if given, will receive two MonoBehaviour objects -- the first is the reference to the page handler of the current page, the second is the reference to the background handler. (public void getHandlerReferences(MonoBehaviour pageHandler, MonoBehaviour backgroundHandler)) Both might as well turn out to be null. It will be always called immediately before the actual method that returns the text or draws on the screen is called.
  • multiHandler -- If this option is present, the same instance of the handler module will be used for all cases when it is present in a page of that particular monitor. Only one copy will be created, the first one mentioned, and it will be the only one initialized with configuration options from within the handler block -- in all other cases, the previously declared handler module will be found and used. All the options regarding method/buttonClickMethod/pageActiveMethod can be different on every page, however, so you can handle multiple types of pages at once in the same module instance, or have a single module instance that is both a page and a background handler.

PartModule based handlers

There are cases when an InternalModule just won't do as a handler because of how it's getting instantiated and then destroyed all the time -- KSP likes to destroy and recreate IVAs every time something interesting happens -- or for some other reason. If you really need to, you can have a PartModule be your page or background handler, but the following restrictions must be observed:

  • RPM cannot instantiate such a module, for the simple reason that RPM instances come and go while you switch vessels, but part modules come and go much less often. It needs to be defined within the part.cfg of the pod itself, because that's the only part that is guaranteed to be there when RPM wakes up.
  • It follows that RPM can't pass it any configuration options either, and that there can only be one instance of such a module per pod, which must be capable of serving any number of diverse RPM instances within the pod that you configure to call it. I.e. a multiHandler option is implied with extra complications.

Provided these conditions can be satisfied, isPartModule option inside the handler definition block will tell RPM to look for an instance of it on the pod part instead of inside a prop:

PAGEHANDLER
{
	name = YourModuleName
	method = TheMethodToCall
	isPartModule = yes
}

All other options, like pageActiveMethod, buttonClickMethod, buttonReleaseMethod are still valid, multiHandler option will be ignored.

Builtin page handlers

The package comes with built-in page handlers to do things you can't do with page definition files:

RasterPropMonitorComputer

The RasterPropMonitorComputer module -- the one that every pod that houses RPM props needs to have -- has two page handler functions as it's side job:

	PAGEHANDLER
	{
		name = RasterPropMonitorComputer
		method = VesselDescriptionWordwrapped
		isPartModule = yes
	}

or alternatively

	PAGEHANDLER
	{
		name = RasterPropMonitorComputer
		method = VesselDescriptionRaw
		isPartModule = yes
	}

Both of these page handler blocks will return the vessel description as the player entered it in the VAB/SPH when building the vessel. The Raw variant will return a description exactly as is. The Wordwrapped description will return it wrapped to match the screen width.

In both cases, the 'AG0='...'AG9=' action group markings will be deleted from the text.

JSIFlightLog

This page handler will print the flight log -- the one you see when you press F3 in flight -- to a screen in real time. There are no options to scroll up, and it's pretty basic, but it might spice up your IVA. It is also sort of a tutorial for writing RPM plugins, as it's code is commented extensively to explain what it does and why. Configuration options:

  • pageTitle -- If this option is present, this line will become the page title of the screen, i.e. will be printed on top. Variable processing still applies to it, although if you wish to use curly brackets, (which you will need to do if you want to use variables) you need to replace them just like you would replace them when writing a page definition in a prop config file.

The method that returns the page is named ShowLog, i.e. to add it to a page, you need to use:

			PAGEHANDLER
			{
				name = JSIFlightLog
				method = ShowLog
				pageTitle = ========== Flight Log ==========
			}

JSISASMenu

This page handler allows the user to control SAS, both toggling it on/off as well as selecting which mode it is in.

	PAGEHANDLER
	{
		name = JSISASMenu
		method = ShowMenu
		buttonClickMethod = ButtonProcessor
		pageActiveMethod = PageActive
                    ...configuration options go here.
	}

Configuration options:

  • pageTitle -- Page title for all pages of the menu.
  • buttonUp -- Number of global button that will navigate up in the currently displayed menu.
  • buttonDown -- Number of global button that will navigate down in the currently displayed menu.
  • buttonEnter -- Number of global button that will select the current menu item.
  • itemColor -- Color of a regular menu item.
  • menuTitleFormatString -- A formatter string to customize the SAS menu title. The default format is "== SAS Menu == {0}".
  • selectedColor -- Color of a menu item in active state.
  • unavailableColor -- Color of a temporarily unavailable menu item.

JSITargetMenu

This page handler permits the user to select a target, be it a vessel, a vessel's docking port, or a celestial body, without ever leaving the IVA, as well as select the reference part of your vessel as if you clicked "Control from here" without actually going outside to do it. It is essentially unusable when your monitor prop does not have global buttons, so beware:

	PAGEHANDLER
	{
		name = JSITargetMenu
		method = ShowMenu
		buttonClickMethod = ButtonProcessor
		pageActiveMethod = PageActive
                    ...configuration options go here.
	}

Configuration options:

  • pageTitle -- The title of the menu page, if any. Suffers from the usual <=/=> replacement requirement if you wish to substitute variables.
  • refreshMenuRate -- List of vessels and docking ports available will be updated once every this number of frames. Defaults to 60.
  • buttonUp -- Number of global button that will navigate up in the currently displayed menu.
  • buttonDown -- Number of global button that will navigate down in the currently displayed menu.
  • buttonEnter -- Number of global button that will select the current menu item. For all menus except the root this will mean targeting it.
  • buttonEsc -- Number of global button that will go to an upper level menu.
  • buttonHome -- Number of global button that will switch the sorting order between alphabetic (default) and distance. Docking ports are not sorted by either.
  • nameColor -- Color of the item names in lists.
  • distanceColor -- Color of the distances in lists.
  • selectedColor -- Color of the currently targeted item. When a docking port is targeted, the vessel it belongs to also counts as targeted.
  • unavailableColor -- Color of the items that are not available. KSP does not let you target the celestial you are currently orbiting, as well as vessels in spheres of influence other than the one you're currently in. This color will be used to grey them out.
  • distanceColumn -- Names of vessels will be truncated to start the separate column of distances, this is how far it will be from the beginning of the line, not counting the cursor. Defaults to 30. Don't forget that the width of the cursor column is hard-coded to 2.
  • distanceColumnWidth -- The width the distance column will be truncated to. Defaults to 8.
  • distanceFormatString -- Format string for the distance. Defaults to " <=0:SIP_6=>m".
  • menuTitleFormatString -- Menu title format string. You can't use variables in this one, but the title of the menu predefined for various menu branches will be inserted in place of {0} -- which has to be written as <=0=> because it's being loaded from a .cfg file.
  • defaultFilter -- The filter setting the monitors start up with, an integer bit mask. The default value is 15, i.e. to show ships, stations, probes and landers. To produce a new value, sum up the numbers for things you want to be enabled in the default filter:
    • 1 - Ship
    • 2 - Station
    • 4 - Probe
    • 8 - Lander
    • 16 - Rover
    • 32 - EVA
    • 64 - Flag
    • 128 - Base
    • 256 - Debris
    • 1024 - Unknown.

Menu of the target docking ports will only be available if the vessel is loaded, which, unless you use a mod that alters the loading distance, is 2.3km away from your vessel. It will be shown when you select an already targeted vessel again. KSP will also prevent the docking port from staying targeted unless you much closer than that -- I wish I knew how far exactly.

JSIVariablePageTextSwitcher

This page handler does not do anything interesting per se -- it just selects between one or the other page text definition based on the output of a variable. This is handy if you find that you want the page to exist in two different states, (for example, one if there is a target selected and one if there isn't) but editing it in such a fashion using string.format tricks is proving too cumbersome. It is very similar in function to JSIVariableAnimator in threshold mode, and actually shares some code with it.

PAGEHANDLER
{
	name = JSIVariablePageTextSwitcher
	method = ShowPage
	pageActiveMethod = PageActive
	...configuration options go here.
}

Legacy Configuration Options

These options apply to legacy configurations or any other situation where there is only one variable controlling switching between two pages.

  • scale -- <variable name or value>,<variable name or value> Just like in JSIVariableAnimator, this lets you define the bottom and top ends of the scale.
  • variableName -- Name of the variable to track. This is actually something of a misnomer, in that it can also be a floating point number, i.e. you can drive a scale around a static number if you want to.
  • threshold -- <bottom of the threshold range>,<top of the threshold range> -- Threshold range.
  • definitionIn,definitionOut -- Page definition just like in a text option of a PAGE{} block. The "In" one will be displayed when the threshold condition matches, "Out" one otherwise.
  • refreshRate -- How many frames to skip before checking the variable again. Defaults to 10.

Multi-page Configuration

This configuration can be used when there are two or more pages that are controlled by a single variable page switcher.

  • definitionOut -- The default page definition. This is the page that is displayed when none of the other page selectors trigger.
  • refreshRate -- How many frames to skip before checking the variable again. Defaults to 10.
PAGE_DEFINITION
{
   variableName = PERSISTENT_MOARdV_FDNMODE
   range = 0.5, 1.5
   page = MOARdV/FlightSystemsRedux/NumericDisplay/fdt1_nodetime.txt
}

PAGE_DEFINITION nodes are places within the JSIVariablePageTextSwitcher. They are evaluated in the order they appear in the configuration file, and evaluation stops as soon as one of the variables are in range.

  • variableName -- The variable to test. This can be any of the defined variables or a constant.
  • range -- The range of values that will trigger the page. These may be numbers or defined variables.
  • page -- The page URI that is displayed when the page is activated.

MechJebRPM

This page handler gives you an on-screen menu permitting you to control SmartASS capabilities of your MechJeb unit, if your ship has one, as well as execute a maneuver node using MechJeb.

	PAGEHANDLER
	{
		name = MechJebRPM
		method = ShowMenu
		pageActiveMethod = PageActive
		buttonClickMethod = ClickProcessor
		...configuration options go here
	}

Configuration options:

  • pageTitle -- Page title for all pages of the menu.
  • buttonUp -- Number of global button that will navigate up in the currently displayed menu.
  • buttonDown -- Number of global button that will navigate down in the currently displayed menu.
  • buttonEnter -- Number of global button that will select the current menu item.
  • buttonEsc -- Number of global button that will go to an upper level menu.
  • buttonHome -- Number of global button that will switch the Force Roll angle when the currently selected menu item is Force Roll.
  • itemColor -- Color of a regular menu item.
  • selectedColor -- Color of a menu item in active state.
  • unavailableColor -- Color of a temporarily unavailable menu item.
  • forceRollStep -- One press of buttonHome will switch the Force Roll angle by this many degrees. Defaults to 90.