Giter Site home page Giter Site logo

sariohara / cp77_nativesettings Goto Github PK

View Code? Open in Web Editor NEW

This project forked from justarandomguyintheinternet/cp77_nativesettings

0.0 1.0 0.0 51 KB

A small mod for Cyberpunk 2077 that allows other mods to easily add settings menus using only native UI

Lua 100.00%

cp77_nativesettings's Introduction

Native Settings

A small mod for Cyberpunk 2077 that allows other mods to easily add settings options to a custom, fully native UI Mods settings menu. User-friendly and fully controller compatible.

How to use:

  1. CET Version 1.18.1+ is required
  2. Add this mod to your mod's requirement list: Nexus page
  3. Import it into your mod:
    nativeSettings = GetMod("nativeSettings")

Add a new tab:

  • Multiple mods can share the same tab
  • path should be a / followed by a simple keyword
  • label is what will be displayed
  • callbackFunction is an optional function parameter that gets called when the tab gets closed
     nativeSettings.addTab("/myMod", "My mod", callbackFunction()) -- Add a tab (path, label, callback)

Add a new subcategory:

  • Use subcategories to organize options
  • path should be your mods tab path (e.g. /myMod), followed by a /, followed by a simple keyword.
  • label is what will be displayed
  • optionalIndex is an optional int parameter to control the position of the subcategory (Default is same order as addSubcategory's get called)
     nativeSettings.addSubcategory("/myMod/sub", "A subcategory") -- Add a subcategory (path, label, optionalIndex)

Adding option widgets:

  • All option widgets can be added to either a tab directly (Provide the tab path), or a tab's subcategory (Provide full path)

Parameters every widget has:

  • path : Where the widget goes, e.g. /myMod or /myMod/sub
  • label : What gets displayed to the left of the widget
  • desc : A description of what the option does, gets displayed when hovered over
  • currentValue : This is what the option's initial value (Type depends on the widget) is. Usually, this value would get read from a settings file / database insideonInit
  • defaultValue : This is what the option's default value should be, gets set when the Defaults button is hit
  • callback : Here, you pass a function f(value) that gets called when the options gets changed. It gets called with a single parameter, the updated value
  • optionalIndex : Optional index parameter that can be used to control the order of the options (Default is same order as the addOption's get called)

Toggle:

  • This adds a basic true/false switch
  • Datatype is boolean
     -- Parameters: path, label, desc, currentValue, defaultValue, callback, optionalIndex
    
     nativeSettings.addSwitch("/myMod/sub", "Switch", "Description", true, true, function(state)
     	print("Changed SWITCH to ", state)
     	-- Add any logic you need in here, such as saving the changes to file / database
     end)

Slider Int:

  • This adds a slider, that can only get set to whole numbers
  • Datatype is int
  • min : This is the minimum value of the slider
  • max : This is the maximum value of the slider
  • step : This is the minimum amount the slider can move
     -- Parameters: path, label, desc, min, max, step, currentValue, defaultValue, callback, optionalIndex
    
     nativeSettings.addRangeInt("/myMod/sub", "Slider Int", "Description", 1, 100, 1, 50, 25, function(value)
     	print("Changed SLIDER INT to ", value)
     	-- Add any logic you need in here, such as saving the changes to file / database
     end)

Slider Float:

  • This adds a slider, that can be set to any value
  • Datatype is float (int also works)
  • min : This is the minimum value of the slider
  • max : This is the maximum value of the slider
  • step : This is the minimum amount the slider can move
  • format : This is a format string, to control how the value gets displayed (Works the same as lua's string.format())
     -- Parameters: path, label, desc, min, max, step, format, currentValue, defaultValue, callback, optionalIndex
    
     nativeSettings.addRangeFloat("/myMod/sub", "Slider Float", "Description", 1, 100, 0.25, "%.2f", 50, 1, function(value)
     	print("Changed SLIDER FLOAT to ", value)
     	-- Add any logic you need in here, such as saving the changes to file / database
     end)

String List:

  • This adds a list of strings, that can be chosen of
  • Datatype is table
  • The table must be numerical indexed
  • currentValue / defaultValue is the index of the selected element
     -- Parameters: path, label, desc, elements, currentValue, defaultValue, callback, optionalIndex
    
     local  list = {[1] = "Option 1", [2] = "Option 2", [3] = "Option 3", [4] = "Option 4"} -- Create list of options, with numeric index
    
     nativeSettings.addSelectorString("/myMod/sub", "String List", "Description", list, 1, 3, function(value)
     	print("Changed LIST STRING to ", list[value])
     	-- Add any logic you need in here, such as saving the changes to file / database
     end)

Keybind:

  • This adds a keybind widget, that can be clicked on to store any pressed key
  • Datatype is string
  • When pressed, it will return the keycode e.g IK_X of the pressed key
  • currentKey and defaultKey needs to be a valid keycode
  • isHold determines whether or not the key icon has a "Hold" outline
  • The actual reading of raw inputs has to be done via Codeware, for examples on how to implement this using CET, including a simple module for setting up multikey bindings, check the provided example in this repo
  • Controller bindings are supported too, but require Codeware to work (Required for actually reading inputs anyways), for an example on how to forward the input events from Codeware to Native Settings check the provided examples
     -- Parameters: path, label, desc, currentKey, defaultKey, isHold, callback, optionalIndex
    
     nativeSettings.addKeyBinding("/myMod/sub", "Keybind", "Description", "IK_1", "IK_5", false, function(key)
     	print("Changed KEYBIND to", key)
     	-- Add any logic you need in here, such as saving the changes to file / database
     end)

Button:

  • This adds a simple, interactable button which calls the callback function without any parameters when clicked
  • Has no currentValue and defaultValue parameters
  • buttonText is the text that gets displayed inside the button
  • textSize is the size of the buttonText text
     -- Parameters: path, label, desc, buttonText, textSize, callback, optionalIndex
    
     nativeSettings.addButton("/myMod/sub", "Button", "Description", "Button label", 45, function()
     	print("User clicked BUTTON")
     	-- Add any logic you need in here, such as calling a function from your mod
     end)

Custom Widget:

  • This is not a typical widget, i.e. it does not have any visible UI
  • It can be used to get a reference to the settings screen's main inkCompoundWidget
  • With this reference you can add your own custom widgets to the settings page, such as the Furigana mod is doing
  • inkCompoundWidget is the SettingsMainGameController's settingsOptionsList widget
-- Parameters: path, callback, optionalIndex

	nativeSettings.addCustom("/myMod/sub", function(inkCompoundWidget)
		-- Add any logic you need in here, such as adding custom UI to the inkCompoundWidget
	end)

Removing options / subcategories:

  • Option widgets as well as subcategories can be added or removed while the UI is active
  • Use this in combination with the optionalIndex parameter of any addOption function to add and remove options where they are needed

Options:

  • optionTable is what gets returned by any addOption function (switch/int/float/list/button)
     -- Parameters: optionTable
     nativeSettings.removeOption(optionTable)

Subcategories:

  • path is the full path to the subcategory you want to remove
     -- Parameters: path
     nativeSettings.removeSubcategory("/myMod/sub")

The refresh function:

  • Calling this function is not necessary anymore, as of version 1.4
  • Refreshes the UI when active, to reflect changes made by adding (e.g. addSwitch) or removing (e.g. removeOption) option widgets or entire subcategories
  • When adding or removing multiple option widgets or subcategories at once, make sure to only call refresh once, after all adding / removing operations are done
     nativeSettings.refresh()

The setOption function:

  • The nativeSettings mod only gets the settings values at the startup in form of the currentValue
  • If you modify any settings / options from e.g. a secondary ImGui settings window, the values displayed by nativeSettings will be out of sync
  • Use the setOption(optionTable, value) function if you change an option from outside the nativeSettings window, to make sure everything stays synced
  • optionTable is what gets returned by any addOption function (switch/int/float/list)
  • value is the value you want to set
  • Example:
     local settingsTables = {} -- An empty table to store the return from the addOption functions, in case we want to use setOption() or removeOption(), can be ignored otherwise
     local switchState = false -- Would usually get loaded from a config file / database
     local nativeSettings
    
     registerForEvent("onInit", function()
     	nativeSettings = GetMod("nativeSettings") -- Get a reference to the nativeSettings mod
    
     	if not nativeSettings then -- Make sure the mod is installed
     		print("Error: NativeSettings not found!")
     		return
     	end
    
     	nativeSettings.addTab("/myMod", "My mod") -- Add our mods tab (path, label)
     	nativeSettings.addSubcategory("/myMod/sub", "A subcategory") -- Optional: Add a subcategory (path, label), you can add as many as you want
    
     	settingsTables["switch"] = nativeSettings.addSwitch("/myMod/sub", "Switch", "Description", switchState, true, function(state) -- Setup a switch, and store its returned table
     		print("Changed SWITCH to ", state)
     		switchState = state
     	end)
     end)
    
     registerForEvent("onDraw", function()
     	if ImGui.Begin("Alternative Settings Window", ImGuiWindowFlags.AlwaysAutoResize) then
     		switchState, changed = ImGui.Checkbox("Switch", switchState)
     		if changed then -- We changed the option value from somewhere else
     			nativeSettings.setOption(settingsTables["switch"], switchState) -- Update the value for the nativeSettings mod
     		end
     	end
     	ImGui.End()
     end)

Credits:

  • psiberx for answering all my questions, as well as doing a lot of work on CET that makes this mod even work and creating Cron.lua, UIButton.lua, Ref.lua and EventProxy.lua.
  • RMK for adding the keybind widget, making proper handling for adding and removing elements and generally helping with bugfixing
  • dkollmann for adding the "custom" widget type and implementing the optional callback for tabs
  • nim for hating ImGui

cp77_nativesettings's People

Contributors

dkollmann avatar justarandomguyintheinternet avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.