-
Notifications
You must be signed in to change notification settings - Fork 4
Mod Tools
Mod tools are similar to scripts except they can create GUIs. Accessible via the Mod Tools sub menu in the Tools menu. Loaded mod tools show in the submenu, and any opened files are reloaded on startup and appear in that submenu.
Mod tools support all the functions that scripts support (e.g. engine.readnumber() and jrpc.callvoidat())
-- These 4 functions return a table that represent the GUI element.
gui.create_dockpanel(lastChildFill : boolean) -> table
gui.create_stackpanel(isVertical : boolean) -> table
gui.create_gridpanel() -> table
gui.create_button(text : string) -> table
gui.create_text(text : string) -> table
-- Sets the GUI's root panel to draw
gui.set_root_panel(panel : table)
-- Blocks until there's pending messages queued on the lua thread, then processes them, and returns.
-- For example, when the user presses a button, it dispatches a click event to the lua thread,
-- then this method will process that press event (which starts an internal loop until the click
-- release event is sent, and this inner loop calls the equivalent of pump.try_run_messages())
pump.run_messages()
-- Processes any pending messages queued on the lua thread, or returns if the queue is empty.
-- This is the same as `pump.run_messages()` except doesn't block if the queue is empty.
-- Note, this may block anyway (e.g. pressing a button which has a holding function set)
pump.try_run_messages()These are not in release builds yet.
-- Creates a timer that invokes the callback function at the specified interval (in seconds). The interval is also the delay for invoking the callback for the first time (aka due time)
gui.create_timer(interval : number, callback : function) -> TimerObject
-- Destroys the timer returned by create_timer, which stops the callback from being invoked.
gui.destroy_timer(timer : TimerObject)These are instance methods, so the invisible first parameter is the element itself
-- Horizontally aligns this element relative to the parent. Can be "stretch", "left", "center" or "right"
set_align_h(align : string)
-- Vertically aligns this element relative to the parent. Can be "stretch", "top", "center" or "bottom"
set_align_v(align : string)
-- These 6 functions accept nil (to clear the fixed size value) or a normal number.
-- Width and Height are nil by default, which means auto-size
-- MinWidth and MinHeight are 0 by default
-- MaxWidth and MaxHeight are math.huge by default
-- By default, all controls will try to take up as much space as possible,
-- which is typically better than using a fixed width or height.
-- It's also better to use a grid instead of fixed size/offsets, since it will resize properly
set_width(value : number?)
set_height(value : number?)
set_minwidth(value : number?)
set_maxwidth(value : number?)
set_minheight(value : number?)
set_maxheight(value : number?)Stack, Dock and Grid panels contain these functions. These are instance methods, so the invisible first parameter is the panel itself
-- Returns the index of the element within the panel. The index is zero-based, so 0 is the first element. If the element was not found, -1 is returned.
index_of(element : table) -> number
-- Removes an element from the panel at the given index
remove_at(index : number)All column/row parameters pass column first and row next, so that it behaves like X and Y coordinates. These are instance methods, so the invisible first parameter is the panel itself
-- Note: Row and column indices are zero-based and cannot be negative
-- RowSpan and ColumnSpan must be >= 1
add(column : number, row : number, element : table)
add(column : number, row : number, columnSpan : number, rowSpan : number, element : table)-- Adds a row with the given format for the pixel height. E.g. "25", "3*", "Auto"
add_row(layout: string)
-- Adds a column with the given format for the pixel width. E.g. "25", "3*", "Auto"
add_column(layout: string)
-- Removes the row at the given index. The index is zero-based, so 0 is the first row.
remove_row(index : number)
-- Removes the column at the given index. The index is zero-based, so 0 is the first column.
remove_column(index : number)These are instance methods, so the invisible first parameter is the panel itself
-- Adds an element docked to either "left", "top", "right" or "bottom"
add(dock : string, element : table)
-- Adds an element docked to the left. Ideally only use for the last child when lastChildFill is true
add(element : table)These are instance methods, so the invisible first parameter is the panel itself
-- Adds an element
add(element : table)These are instance methods, so the invisible first parameter is the button itself.
The callback function is invoked with the Button (table) as the first parameter, which lets you access and modify the button itself during its own callback(s).
-- Sets the function that runs when the user clicks then releases their mouse on the button.
-- Provide nil to remove the callback
set_press_function(callback : function(sender : table)?)
-- Sets the function that is called in a loop while the user has left-click pressed.
-- The 'delta' parameter is the amount of time since the callback was last called, in seconds.
-- Remarks about the callback's return value: When no value is available or it returns false, the loop continues. When true, it breaks the loop (as if
the user released their LMB). Return nothing or false to truly loop until the user stops pressing.
-- Provide nil to remove the callback
set_holding_function(callback : function(sender : table, delta : number)? -> boolean?)
-- Sets the button's text
set_text(text : string)The holding function is provided the delta time between each callback invocation. On the first run, it will be very very small.
You should use this if you need to, for example, increase a float on the console at a fixed rate (e.g. 25.0 per second).
Example: engine.writenumber(addr, "float", 25.0 * delta)
In the demo script at the bottom of the page, the text increments by 3000 per second on a modern PC. This is because setting the text requires posting a message to the UI dispatcher to set the text, because the caller is the lua thread. If you only used lua code and no network operations, it would run as fast as the lua virtual machine can execute, which is significantly faster than 3000 times per second.
These are instance methods, so the invisible first parameter is the text block itself
-- Sets the text of the text block
set_text(text : string)Text Boxes allow users to input data into your mod tool, e.g. specify a target address or offset, a number or plain text.
Text Boxes have three modes:
-
textThe user types text, and you access that text in the script. -
addressThe value is an unsigned 32-bit integer. This doesn't have to be used for an address, it could be an offset or anything that requires a non-negative integer up to 4.2~ billion -
numberThe value is a regular lua number.
These are instance methods, so the invisible first parameter is the text block itself
-- Sets the value as plain text.
set_text(value : string)
-- Sets the value as an unsigned 32-bit integer value
set_address(value : string|number)
-- Sets the value as a decimal number
set_number(value : number)
-- Gets the value in the text box. This returns either a string ("text" mode) or number ("address" or "number" mode).
get_value() -> string|number
-- Sets the callback that runs when the text box's value changes. This includes both from code (e.g. set_number), or when the user types something and presses enter or moves focus away from the text box.
-- This is not called for each key pressed. Use set_keypress_function instead.
-- The sender parameter is the text box
set_value_change_function(callback : function(sender : table)?)
-- Sets the callback that runs when the user presses or releases a key.
-- sender is the text box.
-- isPressed specifies if it was a key press instead of release.
-- symbol specifies the key symbol (e.g. "w" for the W key)
-- keyCode specifies the exact Avalonia key code value
set_keypress_function(callback : function(sender : table, isPressed : boolean, symbol : string, keyCode : number)?)For more info about key codes, see Key Codes
Warning
Avoid using loops within callback functions, and instead, use timers. If you absolutely must, then call pump.try_run_messages() often.
Looping in a callback stops the main thread from communicating with the lua thread if you don't pump the messages, so UI interactions won't get dispatched.
This is a demo of UI layout
press_btn_counter = 0
holding_btn_counter = 0
function CreateTestDock(side)
-- create a dock panel that won't fill the last child control,
-- since we want a left and right dock
local dock = gui.create_dockpanel(false)
-- create a horizontal stack panel
local bottom_spL = gui.create_stackpanel(true)
bottom_spL:add(gui.create_button(side .. " left btn 1"))
bottom_spL:add(gui.create_button(side .. " left btn 2"))
bottom_spL:add(gui.create_button(side .. " left btn 3"))
-- create a horizontal stack panel
local bottom_spR = gui.create_stackpanel(true)
bottom_spR:add(gui.create_button(side .. " right btn 1"))
bottom_spR:add(gui.create_button(side .. " right btn 2"))
bottom_spR:add(gui.create_button(side .. " right btn 3"))
-- add panels to the dock
dock:add("left", bottom_spL)
dock:add("right", bottom_spR)
return dock
end
-- create our root panel, which will fill the last child (tmpstack)
-- to the window contents (inbetween the top and bottom docks ofc)
local root = gui.create_dockpanel(true)
-- For some reason we have to set these as local variables before passing to root:add(), otherwise we get 511 arguments???
local top_panel = CreateTestDock("Top ")
local btm_panel = CreateTestDock("Bottom ")
root:add("top", top_panel)
root:add("bottom", btm_panel)
-- create a vertical stack panel
local tmpstack = gui.create_stackpanel(true)
tmpstack:add(gui.create_text("Hello!"))
local tmpbutton1 = gui.create_button("Click to incr per press")
tmpbutton1:set_press_function(function (sender)
press_btn_counter = press_btn_counter + 1
sender:set_text(press_btn_counter)
end)
tmpstack:add(tmpbutton1)
local tmpbutton2 = gui.create_button("Click to incr while holding")
tmpbutton2:set_holding_function(function (sender, delta)
holding_btn_counter = holding_btn_counter + 1
sender:set_text(holding_btn_counter)
end)
tmpstack:add(tmpbutton2)
root:add(tmpstack)
-- assign root panel to the GUI
gui.set_root_panel(root)
-- the important part. In order for button clicks to work,
-- pump.run_messages() must be called often
while true do
pump.run_messages()
end
Here is a small script to move the player around using 4 buttons:
local tb_x = gui.create_text("Pos X: ???");
local tb_y = gui.create_text("Pos Y: ???");
local grid = gui.create_gridpanel()
grid:add_row("40")
grid:add_row("40")
grid:add_row("40")
grid:add_column("40")
grid:add_column("40")
grid:add_column("40")
local btn_fwd = gui.create_button("+Y");
local btn_lft = gui.create_button("-X");
local btn_rht = gui.create_button("+X");
local btn_bck = gui.create_button("-Y");
btn_fwd:set_holding_function(function (sender, delta)
local num = engine.readnumber(0x830CBFA0, "float") + (100 * delta)
engine.writenumber(0x830CBFA0, "float", num)
tb_y:set_text("Pos Y: " .. tostring(num))
end)
btn_lft:set_holding_function(function (sender, delta)
local num = engine.readnumber(0x830CBF9C, "float") - (100 * delta)
engine.writenumber(0x830CBF9C, "float", num)
tb_x:set_text("Pos X: " .. tostring(num))
end)
btn_rht:set_holding_function(function (sender, delta)
local num = engine.readnumber(0x830CBF9C, "float") + (100 * delta)
engine.writenumber(0x830CBF9C, "float", num)
tb_x:set_text("Pos X: " .. tostring(num))
end)
btn_bck:set_holding_function(function (sender, delta)
local num = engine.readnumber(0x830CBFA0, "float") - (100 * delta)
engine.writenumber(0x830CBFA0, "float", num)
tb_y:set_text("Pos Y: " .. tostring(num))
end)
grid:add(1, 0, btn_fwd)
grid:add(0, 1, btn_lft)
grid:add(2, 1, btn_rht)
grid:add(1, 2, btn_bck)
local stack = gui.create_stackpanel(true)
stack:add(grid)
stack:add(tb_x)
stack:add(tb_y)
-- assign root panel to the GUI
gui.set_root_panel(stack)
-- the important part. In order for button clicks to work,
-- pump.run_messages() must be called often
while true do
pump.run_messages()
end
function GetSensorData()
local addr_HalSendSMCMessage = jrpc.getprocaddress("xboxkrnl.exe", 0x29)
-- XamSwapDiscPatchAddress + 0x3000
local addr_XamBuffer = jrpc.getprocaddress("xam.xex", 0xA29) + 12288
local smcMsg = "7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
jrpc.callat("int", addr_HalSendSMCMessage, {"byte[]", smcMsg}, {"int", addr_XamBuffer})
return engine.readbytes(addr_XamBuffer, 12)
end
function GetTemperature(sensorType, data)
if sensorType < 0 or sensorType > 3 then
error("Sensor type must be 0, 1, 2, or 3")
end
local lo = data[sensorType * 2 + 2]
local hi = data[sensorType * 2 + 3]
return bit32.bor(lo, bit32.lshift(hi, 8)) / 256.0
end
s_CpuLabel = gui.create_text("CPU: ? c")
s_GpuLabel = gui.create_text("GPU: ? c")
s_MemLabel = gui.create_text("MEMORY: ? c")
s_BrdLabel = gui.create_text("CHASSIS: ? c")
function UpdateTemps()
local data = GetSensorData()
s_CpuLabel:set_text("CPU: " .. GetTemperature(0, data) .. "c")
s_GpuLabel:set_text("GPU: " .. GetTemperature(1, data) .. "c")
s_MemLabel:set_text("MEMORY: " .. GetTemperature(2, data) .. "c")
s_BrdLabel:set_text("CHASSIS: " .. GetTemperature(3, data) .. "c")
end
local stack = gui.create_stackpanel(true)
stack:add(s_CpuLabel)
stack:add(s_GpuLabel)
stack:add(s_MemLabel)
stack:add(s_BrdLabel)
gui.set_root_panel(stack)
gui.create_timer(1, UpdateTemps)
while (true) do
pump.run_messages()
end
s_TbValChange = gui.create_text("")
s_TbKeyPressed = gui.create_text("")
local tb = gui.create_textbox("address")
tb:set_value_change_function(function (sender)
s_TbValChange:set_text(tostring(sender:get_value()))
end)
tb:set_keypress_function(function (sender, press, symbol, code)
s_TbKeyPressed:set_text(tostring(press) .. ", " .. symbol .. ", " .. tostring(code))
end)
local stack = gui.create_stackpanel(true)
stack:add(tb)
stack:add(s_TbValChange)
stack:add(s_TbKeyPressed)
gui.set_root_panel(stack)
while true do
pump.run_messages()
endIn key callbacks, the Code column corresponds to the keyCode parameter.
Source: https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Base/Input/Key.cs
| Key Code Name | Code | Description |
|---|---|---|
| None | 0 | No key pressed. |
| Cancel | 1 | The Cancel key. |
| Back | 2 | The Back key. |
| Tab | 3 | The Tab key. |
| LineFeed | 4 | The Linefeed key. |
| Clear | 5 | The Clear key. |
| Enter | 6 | The Enter key. |
| Return | 6 | The Return key. |
| Pause | 7 | The Pause key. |
| Capital | 8 | The Caps Lock key. |
| CapsLock | 8 | The Caps Lock key. |
| HangulMode | 9 | The IME Hangul mode key. |
| KanaMode | 9 | The IME Kana mode key. |
| JunjaMode | 10 | The IME Junja mode key. |
| FinalMode | 11 | The IME Final mode key. |
| HanjaMode | 12 | The IME Hanja mode key. |
| KanjiMode | 12 | The IME Kanji mode key. |
| Escape | 13 | The Escape key. |
| ImeConvert | 14 | The IME Convert key. |
| ImeNonConvert | 15 | The IME NonConvert key. |
| ImeAccept | 16 | The IME Accept key. |
| ImeModeChange | 17 | The IME Mode change key. |
| Space | 18 | The space bar. |
| PageUp | 19 | The Page Up key. |
| Prior | 19 | The Page Up key. |
| Next | 20 | The Page Down key. |
| PageDown | 20 | The Page Down key. |
| End | 21 | The End key. |
| Home | 22 | The Home key. |
| Left | 23 | The Left arrow key. |
| Up | 24 | The Up arrow key. |
| Right | 25 | The Right arrow key. |
| Down | 26 | The Down arrow key. |
| Select | 27 | The Select key. |
| 28 | The Print key. | |
| Execute | 29 | The Execute key. |
| PrintScreen | 30 | The Print Screen key. |
| Snapshot | 30 | The Print Screen key. |
| Insert | 31 | The Insert key. |
| Delete | 32 | The Delete key. |
| Help | 33 | The Help key. |
| D0 | 34 | The 0 key. |
| D1 | 35 | The 1 key. |
| D2 | 36 | The 2 key. |
| D3 | 37 | The 3 key. |
| D4 | 38 | The 4 key. |
| D5 | 39 | The 5 key. |
| D6 | 40 | The 6 key. |
| D7 | 41 | The 7 key. |
| D8 | 42 | The 8 key. |
| D9 | 43 | The 9 key. |
| A | 44 | The A key. |
| B | 45 | The B key. |
| C | 46 | The C key. |
| D | 47 | The D key. |
| E | 48 | The E key. |
| F | 49 | The F key. |
| G | 50 | The G key. |
| H | 51 | The H key. |
| I | 52 | The I key. |
| J | 53 | The J key. |
| K | 54 | The K key. |
| L | 55 | The L key. |
| M | 56 | The M key. |
| N | 57 | The N key. |
| O | 58 | The O key. |
| P | 59 | The P key. |
| Q | 60 | The Q key. |
| R | 61 | The R key. |
| S | 62 | The S key. |
| T | 63 | The T key. |
| U | 64 | The U key. |
| V | 65 | The V key. |
| W | 66 | The W key. |
| X | 67 | The X key. |
| Y | 68 | The Y key. |
| Z | 69 | The Z key. |
| LWin | 70 | The left Windows key. |
| RWin | 71 | The right Windows key. |
| Apps | 72 | The Application key. |
| Sleep | 73 | The Sleep key. |
| NumPad0 | 74 | The 0 key on the numeric keypad. |
| NumPad1 | 75 | The 1 key on the numeric keypad. |
| NumPad2 | 76 | The 2 key on the numeric keypad. |
| NumPad3 | 77 | The 3 key on the numeric keypad. |
| NumPad4 | 78 | The 4 key on the numeric keypad. |
| NumPad5 | 79 | The 5 key on the numeric keypad. |
| NumPad6 | 80 | The 6 key on the numeric keypad. |
| NumPad7 | 81 | The 7 key on the numeric keypad. |
| NumPad8 | 82 | The 8 key on the numeric keypad. |
| NumPad9 | 83 | The 9 key on the numeric keypad. |
| Multiply | 84 | The Multiply key. |
| Add | 85 | The Add key. |
| Separator | 86 | The Separator key. |
| Subtract | 87 | The Subtract key. |
| Decimal | 88 | The Decimal key. |
| Divide | 89 | The Divide key. |
| F1 | 90 | The F1 key. |
| F2 | 91 | The F2 key. |
| F3 | 92 | The F3 key. |
| F4 | 93 | The F4 key. |
| F5 | 94 | The F5 key. |
| F6 | 95 | The F6 key. |
| F7 | 96 | The F7 key. |
| F8 | 97 | The F8 key. |
| F9 | 98 | The F9 key. |
| F10 | 99 | The F10 key. |
| F11 | 100 | The F11 key. |
| F12 | 101 | The F12 key. |
| F13 | 102 | The F13 key. |
| F14 | 103 | The F14 key. |
| F15 | 104 | The F15 key. |
| F16 | 105 | The F16 key. |
| F17 | 106 | The F17 key. |
| F18 | 107 | The F18 key. |
| F19 | 108 | The F19 key. |
| F20 | 109 | The F20 key. |
| F21 | 110 | The F21 key. |
| F22 | 111 | The F22 key. |
| F23 | 112 | The F23 key. |
| F24 | 113 | The F24 key. |
| NumLock | 114 | The Numlock key. |
| Scroll | 115 | The Scroll key. |
| LeftShift | 116 | The left Shift key. |
| RightShift | 117 | The right Shift key. |
| LeftCtrl | 118 | The left Ctrl key. |
| RightCtrl | 119 | The right Ctrl key. |
| LeftAlt | 120 | The left Alt key. |
| RightAlt | 121 | The right Alt key. |
| BrowserBack | 122 | The browser Back key. |
| BrowserForward | 123 | The browser Forward key. |
| BrowserRefresh | 124 | The browser Refresh key. |
| BrowserStop | 125 | The browser Stop key. |
| BrowserSearch | 126 | The browser Search key. |
| BrowserFavorites | 127 | The browser Favorites key. |
| BrowserHome | 128 | The browser Home key. |
| VolumeMute | 129 | The Volume Mute key. |
| VolumeDown | 130 | The Volume Down key. |
| VolumeUp | 131 | The Volume Up key. |
| MediaNextTrack | 132 | The media Next Track key. |
| MediaPreviousTrack | 133 | The media Previous Track key. |
| MediaStop | 134 | The media Stop key. |
| MediaPlayPause | 135 | The media Play/Pause key. |
| LaunchMail | 136 | The Launch Mail key. |
| SelectMedia | 137 | The Select Media key. |
| LaunchApplication1 | 138 | The Launch Application 1 key. |
| LaunchApplication2 | 139 | The Launch Application 2 key. |
| Oem1 | 140 | The OEM 1 key. |
| OemSemicolon | 140 | The OEM Semicolon key. |
| OemPlus | 141 | The OEM Plus key. |
| OemComma | 142 | The OEM Comma key. |
| OemMinus | 143 | The OEM Minus key. |
| OemPeriod | 144 | The OEM Period key. |
| Oem2 | 145 | The OEM 2 key. |
| OemQuestion | 145 | The OEM Question Mark key. |
| Oem3 | 146 | The OEM 3 key. |
| OemTilde | 146 | The OEM Tilde key. |
| AbntC1 | 147 | The ABNT_C1 (Brazilian) key. |
| AbntC2 | 148 | The ABNT_C2 (Brazilian) key. |
| Oem4 | 149 | The OEM 4 key. |
| OemOpenBrackets | 149 | The OEM Open Brackets key. |
| Oem5 | 150 | The OEM 5 key. |
| OemPipe | 150 | The OEM Pipe key. |
| Oem6 | 151 | The OEM 6 key. |
| OemCloseBrackets | 151 | The OEM Close Brackets key. |
| Oem7 | 152 | The OEM 7 key. |
| OemQuotes | 152 | The OEM Quotes key. |
| Oem8 | 153 | The OEM 8 key. |
| Oem102 | 154 | The OEM 3 key. |
| OemBackslash | 154 | The OEM Backslash key. |
| ImeProcessed | 155 | A special key masking the real key being processed by an IME. |
| System | 156 | A special key masking the real key being processed as a system key. |
| DbeAlphanumeric | 157 | The DBE_ALPHANUMERIC key. |
| OemAttn | 157 | The OEM ATTN key. |
| DbeKatakana | 158 | The DBE_KATAKANA key. |
| OemFinish | 158 | The OEM Finish key. |
| DbeHiragana | 159 | The DBE_HIRAGANA key. |
| OemCopy | 159 | The OEM Copy key. |
| DbeSbcsChar | 160 | The DBE_SBCSCHAR key. |
| OemAuto | 160 | The OEM Auto key. |
| DbeDbcsChar | 161 | The DBE_DBCSCHAR key. |
| OemEnlw | 161 | The OEM ENLW key. |
| DbeRoman | 162 | The DBE_ROMAN key. |
| OemBackTab | 162 | The OEM BackTab key. |
| Attn | 163 | The ATTN key. |
| DbeNoRoman | 163 | The DBE_NOROMAN key. |
| CrSel | 164 | The CRSEL key. |
| DbeEnterWordRegisterMode | 164 | The DBE_ENTERWORDREGISTERMODE key. |
| DbeEnterImeConfigureMode | 165 | The DBE_ENTERIMECONFIGMODE key. |
| ExSel | 165 | The EXSEL key. |
| DbeFlushString | 166 | The DBE_FLUSHSTRING key. |
| EraseEof | 166 | The ERASE EOF Key. |
| DbeCodeInput | 167 | The DBE_CODEINPUT key. |
| Play | 167 | The Play key. |
| DbeNoCodeInput | 168 | The DBE_NOCODEINPUT key. |
| Zoom | 168 | The Zoom key. |
| DbeDetermineString | 169 | The DBE_DETERMINESTRING key. |
| NoName | 169 | Reserved for future use. |
| DbeEnterDialogConversionMode | 170 | The DBE_ENTERDLGCONVERSIONMODE key. |
| Pa1 | 170 | The PA1 key. |
| OemClear | 171 | The OEM Clear key. |
| DeadCharProcessed | 172 | The key is used with another key to create a single combined character. |
| FnLeftArrow | 10001 | OSX Platform-specific Fn+Left key |
| FnRightArrow | 10002 | OSX Platform-specific Fn+Right key |
| FnUpArrow | 10003 | OSX Platform-specific Fn+Up key |
| FnDownArrow | 10004 | OSX Platform-specific Fn+Down key |
| MediaHome | 100000 | Remove control home button |
| MediaChannelList | 100001 | TV Channel up |
| MediaChannelRaise | 100002 | TV Channel up |
| MediaChannelLower | 100003 | TV Channel down |
| MediaRecord | 100005 | TV Channel down |
| MediaRed | 100010 | Remote control Red button |
| MediaGreen | 100011 | Remote control Green button |
| MediaYellow | 100012 | Remote control Yellow button |
| MediaBlue | 100013 | Remote control Blue button |
| MediaMenu | 100020 | Remote control Menu button |
| MediaMore | 100021 | Remote control dots button |
| MediaOption | 100022 | Remote control option button |
| MediaInfo | 100023 | Remote control channel info button |
| MediaSearch | 100024 | Remote control search button |
| MediaSubtitle | 100025 | Remote control subtitle/caption button |
| MediaTvGuide | 100026 | Remote control Tv guide detail button |
| MediaPreviousChannel | 100027 | Remote control Previous Channel |
-
Home
- Connect to a console
- Scanning Options
- Scan results & Saved Address Table
- Remote Commands
- Memory Dump
- Tools
- Preferences/App Settings
-
API
- Making a custom connection
- Busy Tokens
- Models, ViewStates, MVP & Binding
- Plugins
- Config Pages
- Brushes and Icons
- Data Manager, Context Data and Data Keys
- Commands and Shortcuts
- Context Menus
- Windows and Dialogs