-
-
Save spacechase0/2d8d4dbffe5f2ce9457d2c891a8b99e3 to your computer and use it in GitHub Desktop.
Generic Mod Config Menu example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Your config class | |
public class DummyConfig | |
{ | |
public bool dummyBool = true; | |
public int dummyInt1 = 50; | |
public int dummyInt2 = 50; | |
public float dummyFloat1 = 0.5f; | |
public float dummyFloat2 = 0.5f; | |
public string dummyString1 = "Kirby"; | |
public string dummyString2 = "Default"; | |
internal static string[] dummyString2Choices = new string[] { "Default", "Kitties", "Cats", "Meow" }; | |
public SButton dummyKeybinding = SButton.K; | |
public KeybindList dummyKeybinding2 = new KeybindList( new Keybind( SButton.LeftShift, SButton.S ) ); | |
public Color dummyColor = Color.White; | |
} | |
public DummyConfig config; | |
// Used for the complex widget | |
public class RandomColorWidgetState | |
{ | |
public Color color; | |
} | |
// In your Entry method | |
Helper.Events.GameLoop.GameLaunched += onLaunched; | |
// In your mod entry class | |
private void onLaunched(object sender, GameLaunchedEventArgs e) | |
{ | |
config = Helper.ReadConfig<DummyConfig>(); | |
var api = Helper.ModRegistry.GetApi<GenericModConfigMenuAPI>("spacechase0.GenericModConfigMenu"); | |
api.RegisterModConfig(ModManifest, () => config = new DummyConfig(), () => Helper.WriteConfig(config)); | |
api.SetDefaultIngameOptinValue( ModManifest, true ); | |
api.RegisterLabel(ModManifest, "Dummy Label", "Testing labels"); | |
api.RegisterParagraph( ModManifest, "Testing paragraph text. These are smaller than labels and should wrap based on length. In theory. They should also (in theory) support multiple rows. Whether that will look good or not is another question. But hey, it looks like it worked! Imagine that. Should I support images in documentation, too?" ); | |
api.RegisterImage( ModManifest, "Maps\\springobjects", new Rectangle( 32, 48, 16, 16 ) ); | |
api.RegisterImage( ModManifest, "Portraits\\Penny", null, 1 ); | |
api.SetDefaultIngameOptinValue( ModManifest, false ); | |
api.RegisterPageLabel( ModManifest, "Go to page: Simple Options", "", "Simple Options" ); | |
api.SetDefaultIngameOptinValue( ModManifest, true ); | |
api.RegisterPageLabel( ModManifest, "Go to page: Complex Options", "", "Complex Options" ); | |
api.SetDefaultIngameOptinValue( ModManifest, false ); | |
api.StartNewPage( ModManifest, "Simple Options" ); | |
api.RegisterPageLabel( ModManifest, "Back to main page", "", "" ); | |
api.RegisterSimpleOption(ModManifest, "Dummy Bool", "Testing a checkbox", () => config.dummyBool, (bool val) => config.dummyBool = val); | |
api.RegisterSimpleOption(ModManifest, "Dummy Int (1)", "Testing an int (simple)", () => config.dummyInt1, (int val) => config.dummyInt1 = val); | |
api.RegisterClampedOption(ModManifest, "Dummy Int (2)", "Testing an int (range)", () => config.dummyInt2, (int val) => config.dummyInt2 = val, 0, 100); | |
api.RegisterSimpleOption(ModManifest, "Dummy Float (1)", "Testing a float (simple)", () => config.dummyFloat1, (float val) => config.dummyFloat1 = val); | |
api.RegisterClampedOption(ModManifest, "Dummy Float (2)", "Testing a float (range)", () => config.dummyFloat2, (float val) => config.dummyFloat2 = val, 0, 1); | |
api.SetDefaultIngameOptinValue( ModManifest, true ); | |
api.StartNewPage( ModManifest, "Complex Options" ); | |
api.RegisterPageLabel( ModManifest, "Back to main page", "", "" ); | |
api.RegisterSimpleOption(ModManifest, "Dummy String (1)", "Testing a string", () => config.dummyString1, (string val) => config.dummyString1 = val); | |
api.RegisterChoiceOption(ModManifest, "Dummy String (2)", "Testing a dropdown box", () => config.dummyString2, (string val) => config.dummyString2 = val, DummyConfig.dummyString2Choices); | |
api.RegisterSimpleOption(ModManifest, "Dummy Keybinding", "Testing a keybinding", () => config.dummyKeybinding, (SButton val) => config.dummyKeybinding = val); | |
api.RegisterSimpleOption(ModManifest, "Dummy Keybinding 2", "Testing a keybinding list", () => config.dummyKeybinding2, (KeybindList val) => config.dummyKeybinding2 = val); | |
api.RegisterLabel(ModManifest, "", ""); | |
// Complex widget - this just generates a random color on click. | |
Func<Vector2, object, object> randomColorUpdate = | |
(Vector2 pos, object state_) => | |
{ | |
var state = state_ as RandomColorWidgetState; | |
if (state == null) | |
state = new RandomColorWidgetState() { color = config.dummyColor }; | |
var bounds = new Rectangle((int)pos.X + 12, (int)pos.Y + 12, 50 - 12 * 2, 50 - 12 * 2); | |
bool hover = bounds.Contains(Game1.getOldMouseX(), Game1.getOldMouseY()); | |
if ( hover && Game1.oldMouseState.LeftButton == ButtonState.Released && Mouse.GetState().LeftButton == ButtonState.Pressed) | |
{ | |
Game1.playSound("drumkit6"); | |
Random r = new Random(); | |
state.color.R = (byte) r.Next(256); | |
state.color.G = (byte) r.Next(256); | |
state.color.B = (byte) r.Next(256); | |
} | |
return state; | |
}; | |
Func<SpriteBatch, Vector2, object, object> randomColorDraw = | |
(SpriteBatch b, Vector2 pos, object state_) => | |
{ | |
var state = state_ as RandomColorWidgetState; | |
IClickableMenu.drawTextureBox(b, (int)pos.X, (int)pos.Y, 50, 50, Color.White); | |
var colorBox = new Rectangle((int)pos.X + 12, (int)pos.Y + 12, 50 - 12 * 2, 50 - 12 * 2); | |
b.Draw(Game1.staminaRect, colorBox, state.color); | |
return state; | |
}; | |
Action<object> randomColorSave = | |
(object state) => | |
{ | |
if ( state == null ) | |
return; | |
config.dummyColor = (state as RandomColorWidgetState).color; | |
}; | |
api.RegisterComplexOption(ModManifest, "Dummy Color", "Testing a complex widget (random color on click)", randomColorUpdate, randomColorDraw, randomColorSave); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface GenericModConfigMenuAPI | |
{ | |
void RegisterModConfig(IManifest mod, Action revertToDefault, Action saveToFile); | |
void UnregisterModConfig(IManifest mod); | |
void SetDefaultIngameOptinValue( IManifest mod, bool optedIn ); | |
void StartNewPage(IManifest mod, string pageName); | |
void OverridePageDisplayName(IManifest mod, string pageName, string displayName); | |
void RegisterLabel(IManifest mod, string labelName, string labelDesc); | |
void RegisterPageLabel( IManifest mod, string labelName, string labelDesc, string newPage ); | |
void RegisterParagraph(IManifest mod, string paragraph); | |
void RegisterImage( IManifest mod, string texPath, Rectangle? texRect = null, int scale = 4 ); | |
void RegisterSimpleOption(IManifest mod, string optionName, string optionDesc, Func<bool> optionGet, Action<bool> optionSet); | |
void RegisterSimpleOption(IManifest mod, string optionName, string optionDesc, Func<int> optionGet, Action<int> optionSet); | |
void RegisterSimpleOption(IManifest mod, string optionName, string optionDesc, Func<float> optionGet, Action<float> optionSet); | |
void RegisterSimpleOption(IManifest mod, string optionName, string optionDesc, Func<string> optionGet, Action<string> optionSet); | |
void RegisterSimpleOption(IManifest mod, string optionName, string optionDesc, Func<SButton> optionGet, Action<SButton> optionSet); | |
void RegisterSimpleOption(IManifest mod, string optionName, string optionDesc, Func<KeybindList> optionGet, Action<KeybindList> optionSet); | |
void RegisterClampedOption(IManifest mod, string optionName, string optionDesc, Func<int> optionGet, Action<int> optionSet, int min, int max); | |
void RegisterClampedOption(IManifest mod, string optionName, string optionDesc, Func<float> optionGet, Action<float> optionSet, float min, float max); | |
void RegisterClampedOption(IManifest mod, string optionName, string optionDesc, Func<int> optionGet, Action<int> optionSet, int min, int max, int interval); | |
void RegisterClampedOption(IManifest mod, string optionName, string optionDesc, Func<float> optionGet, Action<float> optionSet, float min, float max, float interval); | |
void RegisterChoiceOption(IManifest mod, string optionName, string optionDesc, Func<string> optionGet, Action<string> optionSet, string[] choices); | |
void RegisterComplexOption(IManifest mod, string optionName, string optionDesc, | |
Func<Vector2, object, object> widgetUpdate, | |
Func<SpriteBatch, Vector2, object, object> widgetDraw, | |
Action<object> onSave); | |
void SubscribeToChange(IManifest mod, Action<string, bool> changeHandler); | |
void SubscribeToChange(IManifest mod, Action<string, int> changeHandler); | |
void SubscribeToChange(IManifest mod, Action<string, float> changeHandler); | |
void SubscribeToChange(IManifest mod, Action<string, string> changeHandler); | |
void OpenModMenu(IManifest mod); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For
API.cs
, I suggest adding the following on top:If not, Visual Studio will complain about missing references for
IManifest
,Rectangle
,Vector2
, etc.