├── .editorconfig
├── .github
└── workflows
│ └── dotnet.yml
├── .gitignore
├── .gitmodules
├── CustomizePlus.sln
├── CustomizePlus
├── CustomizePlus.csproj
├── DalamudPackager.targets
├── Extensions
│ └── CommandManagerExtensions.cs
├── GlobalSuppressions.cs
├── Helpers
│ ├── ChatHelper.cs
│ └── CtrlHelper.cs
├── Plugin.cs
├── Services
│ └── DalamudServices.cs
├── UI
│ ├── UserInterfaceBase.cs
│ ├── UserInterfaceManager.cs
│ ├── WindowBase.cs
│ └── Windows
│ │ └── MainWindow.cs
└── customizePlus.json
├── Data
├── NotoSansCJKjp-Medium.otf
├── customizePlus.json
├── gamesym.ttf
└── icon.png
├── LICENSE.md
└── README.md
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | file_header_template = © Customize+.\nLicensed under the MIT license.
4 |
5 | dotnet_diagnostic.sa1000.severity = none
6 | dotnet_diagnostic.sa1027.severity = none
7 | dotnet_diagnostic.sa1600.severity = none
8 | dotnet_diagnostic.sa1503.severity = none
9 | dotnet_diagnostic.sa1633.severity = none
10 | dotnet_diagnostic.sa1401.severity = none
11 | dotnet_diagnostic.sa1601.severity = none
12 | dotnet_diagnostic.sa1602.severity = none
13 | dotnet_diagnostic.sa1516.severity = none
14 | dotnet_diagnostic.sa1618.severity = none
15 | dotnet_diagnostic.sa1611.severity = none
16 | dotnet_diagnostic.sa1615.severity = none
17 | dotnet_diagnostic.sa1011.severity = none
18 | dotnet_diagnostic.sa1134.severity = none
19 |
20 | dotnet_diagnostic.ide0011.severity = none
21 | dotnet_diagnostic.ide0022.severity = none
22 | dotnet_diagnostic.ide0023.severity = none
23 | dotnet_diagnostic.ide1006.severity = warning
24 | dotnet_diagnostic.ide0044.severity = suggestion
25 | dotnet_diagnostic.ide0058.severity = none
26 | dotnet_diagnostic.ide0073.severity = warning
27 | dotnet_diagnostic.ide0025.severity = none
28 | dotnet_diagnostic.ide0027.severity = none
29 | dotnet_diagnostic.ide0059.severity = none
30 | dotnet_diagnostic.ide0065.severity = none
31 |
32 | dotnet_diagnostic.unt0001.severity = warning
33 | dotnet_diagnostic.unt0002.severity = warning
34 | dotnet_diagnostic.unt0003.severity = warning
35 | dotnet_diagnostic.unt0004.severity = warning
36 | dotnet_diagnostic.unt0005.severity = warning
37 | dotnet_diagnostic.unt0006.severity = warning
38 | dotnet_diagnostic.unt0007.severity = warning
39 | dotnet_diagnostic.unt0008.severity = warning
40 | dotnet_diagnostic.unt0009.severity = warning
41 | dotnet_diagnostic.unt0010.severity = warning
42 | dotnet_diagnostic.unt0011.severity = warning
43 | dotnet_diagnostic.unt0012.severity = warning
44 | dotnet_diagnostic.unt0013.severity = none
45 | dotnet_diagnostic.unt0014.severity = warning
46 | dotnet_diagnostic.unt0015.severity = warning
47 | dotnet_diagnostic.unt0016.severity = warning
48 | dotnet_diagnostic.unt0017.severity = warning
49 | dotnet_diagnostic.unt0018.severity = warning
50 | dotnet_diagnostic.unt0019.severity = warning
51 | dotnet_diagnostic.unt0020.severity = warning
52 |
53 | dotnet_diagnostic.cs1591.severity = none
54 | dotnet_diagnostic.cs0067.severity = none
55 |
56 | dotnet_diagnostic.ca1416.severity = none
57 | dotnet_diagnostic.ca2201.severity = none
58 |
59 | # SA1101: Prefix local calls with this
60 | dotnet_diagnostic.sa1101.severity = silent
61 |
62 | # CS8602: Dereference of a possibly null reference.
63 | dotnet_diagnostic.cs8602.severity = silent
64 |
65 | # CS0168: Variable is declared but never used
66 | dotnet_diagnostic.cs0168.severity = silent
67 |
68 | # CS8600: Converting null literal or possible null value to non-nullable type.
69 | dotnet_diagnostic.cs8600.severity = suggestion
70 |
71 | [*.{cs,vb}]
72 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
73 | tab_width = 4
74 | indent_size = 4
75 | end_of_line = crlf
76 | dotnet_style_coalesce_expression = true:suggestion
77 | dotnet_style_null_propagation = true:suggestion
78 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
79 | dotnet_style_prefer_auto_properties = true:silent
80 | dotnet_style_object_initializer = true:suggestion
81 | dotnet_style_collection_initializer = true:suggestion
82 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
83 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
84 | dotnet_style_prefer_conditional_expression_over_return = true:silent
85 | dotnet_style_explicit_tuple_names = true:suggestion
86 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
87 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
88 | dotnet_style_prefer_compound_assignment = true:suggestion
89 | dotnet_style_prefer_simplified_interpolation = true:suggestion
90 | dotnet_style_namespace_match_folder = true:suggestion
91 | [*.{cs,vb}]
92 | #### Naming styles ####
93 |
94 | # Naming rules
95 |
96 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
97 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
98 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
99 |
100 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
101 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
102 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
103 |
104 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
105 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
106 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
107 |
108 | # Symbol specifications
109 |
110 | dotnet_naming_symbols.interface.applicable_kinds = interface
111 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
112 | dotnet_naming_symbols.interface.required_modifiers =
113 |
114 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
115 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
116 | dotnet_naming_symbols.types.required_modifiers =
117 |
118 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
119 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
120 | dotnet_naming_symbols.non_field_members.required_modifiers =
121 |
122 | # Naming styles
123 |
124 | dotnet_naming_style.begins_with_i.required_prefix = I
125 | dotnet_naming_style.begins_with_i.required_suffix =
126 | dotnet_naming_style.begins_with_i.word_separator =
127 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
128 |
129 | dotnet_naming_style.pascal_case.required_prefix =
130 | dotnet_naming_style.pascal_case.required_suffix =
131 | dotnet_naming_style.pascal_case.word_separator =
132 | dotnet_naming_style.pascal_case.capitalization = pascal_case
133 |
134 | dotnet_naming_style.pascal_case.required_prefix =
135 | dotnet_naming_style.pascal_case.required_suffix =
136 | dotnet_naming_style.pascal_case.word_separator =
137 | dotnet_naming_style.pascal_case.capitalization = pascal_case
138 |
139 | # Default severity for analyzer diagnostics with category 'StyleCop.CSharp.SpacingRules'
140 | dotnet_analyzer_diagnostic.category-stylecop.csharp.spacingrules.severity = silent
141 |
142 | # Default severity for analyzer diagnostics with category 'StyleCop.CSharp.ReadabilityRules'
143 | dotnet_analyzer_diagnostic.category-stylecop.csharp.readabilityrules.severity = silent
144 |
145 | # Default severity for analyzer diagnostics with category 'StyleCop.CSharp.LayoutRules'
146 | dotnet_analyzer_diagnostic.category-stylecop.csharp.layoutrules.severity = silent
147 |
148 | # Default severity for analyzer diagnostics with category 'StyleCop.CSharp.OrderingRules'
149 | dotnet_analyzer_diagnostic.category-stylecop.csharp.orderingrules.severity = silent
150 |
151 | [*.{asax,ascx,aspx,axaml,cs,cshtml,htm,html,master,paml,razor,skin,vb,xaml,xamlx,xoml}]
152 | indent_style = space
153 | indent_size = 4
154 | tab_width = 4
155 |
156 | [*.{appxmanifest,axml,build,config,csproj,dbml,discomap,dtd,jsproj,lsproj,njsproj,nuspec,proj,props,resw,resx,StyleCop,targets,tasks,vbproj,xml,xsd}]
157 | indent_style = space
158 | indent_size = 2
159 | tab_width = 2
160 |
161 | [*]
162 |
163 | # Microsoft .NET properties
164 | csharp_new_line_before_members_in_object_initializers = false
165 | csharp_preferred_modifier_order = public, private, protected, internal, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:suggestion
166 | csharp_style_prefer_utf8_string_literals = true:suggestion
167 | csharp_style_var_elsewhere = true:suggestion
168 | csharp_style_var_for_built_in_types = true:suggestion
169 | csharp_style_var_when_type_is_apparent = true:suggestion
170 | dotnet_naming_rule.private_constants_rule.import_to_resharper = as_predefined
171 | dotnet_naming_rule.private_constants_rule.resharper_style = Label + AaBb, AaBb
172 | dotnet_naming_rule.private_constants_rule.severity = warning
173 | dotnet_naming_rule.private_constants_rule.style = label_upper_camel_case_style
174 | dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols
175 | dotnet_naming_style.label_upper_camel_case_style.capitalization = pascal_case
176 | dotnet_naming_style.label_upper_camel_case_style.required_prefix = Label
177 | dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private
178 | dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field
179 | dotnet_naming_symbols.private_constants_symbols.required_modifiers = const
180 | dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
181 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none
182 | dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
183 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
184 | dotnet_style_predefined_type_for_member_access = true:suggestion
185 | dotnet_style_qualification_for_event = false:suggestion
186 | dotnet_style_qualification_for_field = false:suggestion
187 | dotnet_style_qualification_for_method = false:suggestion
188 | dotnet_style_qualification_for_property = false:suggestion
189 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
190 |
191 | # ReSharper inspection severities
192 | resharper_arrange_redundant_parentheses_highlighting = hint
193 | resharper_arrange_this_qualifier_highlighting = hint
194 | resharper_arrange_type_member_modifiers_highlighting = hint
195 | resharper_arrange_type_modifiers_highlighting = hint
196 | resharper_built_in_type_reference_style_for_member_access_highlighting = hint
197 | resharper_built_in_type_reference_style_highlighting = hint
198 | resharper_redundant_base_qualifier_highlighting = warning
199 | resharper_suggest_var_or_type_built_in_types_highlighting = hint
200 | resharper_suggest_var_or_type_elsewhere_highlighting = hint
201 | resharper_suggest_var_or_type_simple_types_highlighting = hint
202 | csharp_indent_labels = one_less_than_current
203 | csharp_using_directive_placement = outside_namespace:silent
204 | csharp_prefer_simple_using_statement = true:suggestion
205 | csharp_prefer_braces = true:silent
206 | csharp_style_namespace_declarations = block_scoped:silent
207 | csharp_style_expression_bodied_methods = false:silent
208 | csharp_style_expression_bodied_constructors = false:silent
209 | csharp_style_expression_bodied_operators = false:silent
210 | csharp_style_expression_bodied_properties = true:silent
211 | csharp_style_expression_bodied_indexers = true:silent
212 | csharp_style_expression_bodied_accessors = true:silent
213 | csharp_style_expression_bodied_lambdas = true:silent
214 | csharp_style_expression_bodied_local_functions = false:silent
215 | csharp_style_throw_expression = true:suggestion
216 | csharp_style_prefer_null_check_over_type_check = true:suggestion
217 | csharp_prefer_simple_default_expression = true:suggestion
218 | csharp_style_prefer_local_over_anonymous_function = true:suggestion
219 | csharp_style_prefer_index_operator = true:suggestion
220 | csharp_style_prefer_range_operator = true:suggestion
221 | csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
222 | csharp_style_prefer_tuple_swap = true:suggestion
223 | csharp_style_prefer_method_group_conversion = true:silent
224 | csharp_style_prefer_top_level_statements = true:silent
--------------------------------------------------------------------------------
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a .NET project
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
3 |
4 | name: .NET Build
5 |
6 | on:
7 | push:
8 | branches:
9 | - main
10 | - structureRework
11 | tags-ignore: '*'
12 | pull_request:
13 | types: [opened, reopened]
14 |
15 | jobs:
16 | build:
17 | runs-on: windows-latest
18 | steps:
19 | - uses: actions/checkout@v3.5.2
20 | with:
21 | submodules: true
22 | - name: Setup .NET
23 | uses: actions/setup-dotnet@v3.0.3
24 | with:
25 | dotnet-version: '7.x.x'
26 | - name: Restore dependencies
27 | run: dotnet restore
28 | - name: Download Dalamud
29 | run: |
30 | Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -OutFile latest.zip
31 | Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev\"
32 | - name: Build
33 | run: |
34 | dotnet build --no-restore --configuration Release --nologo
35 | - name: Rename file
36 | run: mv ${{ github.workspace }}/CustomizePlus/bin/x64/Release/CustomizePlus/latest.zip ${{ github.workspace }}/CustomizePlus/bin/x64/Release/CustomizePlus/CustomizePlus.zip
37 | - name: Upload a Build Artifact
38 | uses: actions/upload-artifact@v3.1.2
39 | with:
40 | path: |
41 | ${{ github.workspace }}/CustomizePlus/bin/x64/Release/
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | publish/
2 | \.vs/
3 | packages/
4 | *.user
5 | bin/
6 | obj/
7 | deploy/
8 | Setup/Release/
9 | Setup/Debug/
10 | *.tlog
11 | *.iobj
12 | *.ipdb
13 | *.filters
14 | *.pdb
15 | *.log
16 | *.obj
17 | *.idb
18 | *.recipe
19 | *.ilk
20 | \.vscode/
21 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Lib/XivToolsWpf"]
2 | path = Lib/XivToolsWpf
3 | url = https://github.com/XIV-Tools/XivToolsWpf
4 | [submodule "Lib/XivtoolsWpf"]
5 | path = Lib/XivtoolsWpf
6 | url = https://github.com/XIV-Tools/XivToolsWpf.git
7 |
--------------------------------------------------------------------------------
/CustomizePlus.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.31911.260
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4CF55D1D-C5C5-4368-89D6-31D79EF6978C}"
7 | ProjectSection(SolutionItems) = preProject
8 | .editorconfig = .editorconfig
9 | ..\..\..\..\Users\yuuki\AppData\Roaming\XIVLauncher\dalamud.log = ..\..\..\..\Users\yuuki\AppData\Roaming\XIVLauncher\dalamud.log
10 | repo.json = repo.json
11 | EndProjectSection
12 | EndProject
13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomizePlus", "CustomizePlus\CustomizePlus.csproj", "{5BA385F5-C17E-4CE4-828A-24F7F19C434B}"
14 | EndProject
15 | Global
16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
17 | Debug|Any CPU = Debug|Any CPU
18 | Debug|x64 = Debug|x64
19 | Release|Any CPU = Release|Any CPU
20 | Release|x64 = Release|x64
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {5BA385F5-C17E-4CE4-828A-24F7F19C434B}.Debug|Any CPU.ActiveCfg = Debug|x64
24 | {5BA385F5-C17E-4CE4-828A-24F7F19C434B}.Debug|Any CPU.Build.0 = Debug|x64
25 | {5BA385F5-C17E-4CE4-828A-24F7F19C434B}.Debug|x64.ActiveCfg = Debug|x64
26 | {5BA385F5-C17E-4CE4-828A-24F7F19C434B}.Debug|x64.Build.0 = Debug|x64
27 | {5BA385F5-C17E-4CE4-828A-24F7F19C434B}.Release|Any CPU.ActiveCfg = Release|x64
28 | {5BA385F5-C17E-4CE4-828A-24F7F19C434B}.Release|Any CPU.Build.0 = Release|x64
29 | {5BA385F5-C17E-4CE4-828A-24F7F19C434B}.Release|x64.ActiveCfg = Release|x64
30 | {5BA385F5-C17E-4CE4-828A-24F7F19C434B}.Release|x64.Build.0 = Release|x64
31 | EndGlobalSection
32 | GlobalSection(SolutionProperties) = preSolution
33 | HideSolutionNode = FALSE
34 | EndGlobalSection
35 | GlobalSection(ExtensibilityGlobals) = postSolution
36 | SolutionGuid = {B17E85B1-5F60-4440-9F9A-3DDE877E8CDF}
37 | EndGlobalSection
38 | EndGlobal
39 |
--------------------------------------------------------------------------------
/CustomizePlus/CustomizePlus.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 1.2.6.10
8 | CustomizePlus
9 |
10 | https://github.com/XIV-Tools/CustomizePlus
11 | true
12 |
13 |
14 |
15 | net8.0-windows
16 | x64
17 | enable
18 | latest
19 | true
20 | false
21 | false
22 | true
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | PreserveNewest
34 | false
35 |
36 |
37 |
38 |
39 | $(appdata)\XIVLauncher\addon\Hooks\dev\
40 | True
41 |
42 |
43 |
44 |
45 |
46 |
47 | all
48 | runtime; build; native; contentfiles; analyzers; buildtransitive
49 |
50 |
51 | $(DalamudLibPath)Newtonsoft.Json.dll
52 | false
53 |
54 |
55 | $(DalamudLibPath)Dalamud.dll
56 | false
57 |
58 |
59 | $(DalamudLibPath)ImGui.NET.dll
60 | false
61 |
62 |
63 | $(DalamudLibPath)ImGuiScene.dll
64 | false
65 |
66 |
67 | $(DalamudLibPath)Lumina.dll
68 | false
69 |
70 |
71 | $(DalamudLibPath)Lumina.Excel.dll
72 | false
73 |
74 |
75 | $(DalamudLibPath)FFXIVClientStructs.dll
76 | false
77 |
78 |
79 |
80 |
81 |
82 | PreserveNewest
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/CustomizePlus/DalamudPackager.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
--------------------------------------------------------------------------------
/CustomizePlus/Extensions/CommandManagerExtensions.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using System.Collections.Generic;
5 | using CustomizePlus.Services;
6 | using Dalamud.Game.Command;
7 | using Dalamud.Plugin.Services;
8 |
9 | namespace CustomizePlus.Extensions
10 | {
11 | public static class CommandManagerExtensions
12 | {
13 | private static readonly List BoundCommands = new();
14 |
15 | public static void AddCommand(this ICommandManager self, CommandInfo.HandlerDelegate handler, string command,
16 | string help)
17 | {
18 | var info = new CommandInfo(handler)
19 | {
20 | HelpMessage = help
21 | };
22 |
23 | if (!command.StartsWith('/'))
24 | {
25 | command = '/' + command;
26 | }
27 |
28 | BoundCommands.Add(command);
29 |
30 | self.AddHandler(command, info);
31 | }
32 |
33 | public static void Dispose()
34 | {
35 | foreach (var command in BoundCommands)
36 | {
37 | DalamudServices.CommandManager.RemoveHandler(command);
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/CustomizePlus/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using System.Diagnostics.CodeAnalysis;
5 |
6 | [assembly:
7 | SuppressMessage("StyleCop.CSharp.NamingRules", "SA1309:Field names should not begin with underscore",
8 | Justification = "Supressed in favor of CA1500. Use _camelCase for private fields.",
9 | Scope = "namespaceanddescendants", Target = "~N:CustomizePlus")]
--------------------------------------------------------------------------------
/CustomizePlus/Helpers/ChatHelper.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using CustomizePlus.Services;
5 | using Dalamud.Game.Text.SeStringHandling;
6 |
7 | namespace CustomizePlus.Helpers
8 | {
9 | internal static class ChatHelper
10 | {
11 | public static void PrintInChat(string message)
12 | {
13 | var stringBuilder = new SeStringBuilder();
14 | stringBuilder.AddUiForeground(45);
15 | stringBuilder.AddText($"[Customize+] {message}");
16 | stringBuilder.AddUiForegroundOff();
17 | DalamudServices.ChatGui.Print(stringBuilder.BuiltString);
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/CustomizePlus/Helpers/CtrlHelper.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using Dalamud.Interface;
6 | using Dalamud.Utility;
7 | using ImGuiNET;
8 |
9 | namespace CustomizePlus.Helpers
10 | {
11 | public static class CtrlHelper
12 | {
13 | ///
14 | /// Gets the width of an icon button, checkbox, etc...
15 | ///
16 | /// per https://github.com/ocornut/imgui/issues/3714#issuecomment-759319268
17 | public static float IconButtonWidth => ImGui.GetFrameHeight() + (2 * ImGui.GetStyle().ItemInnerSpacing.X);
18 |
19 | public static bool TextBox(string label, ref string value)
20 | {
21 | ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
22 | return ImGui.InputText(label, ref value, 1024);
23 | }
24 |
25 | public static bool TextPropertyBox(string label, Func get, Action set)
26 | {
27 | var temp = get();
28 | var result = TextBox(label, ref temp);
29 | if (result)
30 | {
31 | set(temp);
32 | }
33 |
34 | return result;
35 | }
36 |
37 | public static bool Checkbox(string label, ref bool value)
38 | {
39 | return ImGui.Checkbox(label, ref value);
40 | }
41 |
42 | public static bool CheckboxWithTextAndHelp(string label, string text, string helpText, ref bool value)
43 | {
44 | var checkBoxState = ImGui.Checkbox(label, ref value);
45 | ImGui.SameLine();
46 | ImGui.PushFont(UiBuilder.IconFont);
47 | ImGui.Text(FontAwesomeIcon.InfoCircle.ToIconString());
48 | ImGui.PopFont();
49 | AddHoverText(helpText);
50 | ImGui.SameLine();
51 | ImGui.Text(text);
52 |
53 | AddHoverText(helpText);
54 |
55 | return checkBoxState;
56 | }
57 |
58 | public static bool CheckboxToggle(string label, in bool shown, Action toggle)
59 | {
60 | var temp = shown;
61 | var toggled = ImGui.Checkbox(label, ref temp);
62 |
63 | if (toggled)
64 | {
65 | toggle(temp);
66 | }
67 |
68 | return toggled;
69 | }
70 |
71 | public static bool ArrowToggle(string label, ref bool value)
72 | {
73 | var toggled = ImGui.ArrowButton(label, value ? ImGuiDir.Down : ImGuiDir.Right);
74 |
75 | if (toggled)
76 | {
77 | value = !value;
78 | }
79 |
80 | return value;
81 | }
82 |
83 | public static void AddHoverText(string text)
84 | {
85 | if (ImGui.IsItemHovered())
86 | {
87 | ImGui.SetTooltip(text);
88 | }
89 | }
90 |
91 | public enum TextAlignment { Left, Center, Right };
92 | public static void StaticLabel(string? text, TextAlignment align = TextAlignment.Left, string tooltip = "")
93 | {
94 | if (text != null)
95 | {
96 | if (align == TextAlignment.Center)
97 | {
98 | ImGui.Dummy(new System.Numerics.Vector2((ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize(text).X) / 2, 0));
99 | ImGui.SameLine();
100 | }
101 | else if (align == TextAlignment.Right)
102 | {
103 | ImGui.Dummy(new System.Numerics.Vector2(ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize(text).X, 0));
104 | ImGui.SameLine();
105 | }
106 |
107 | ImGui.Text(text);
108 | if (!tooltip.IsNullOrWhitespace())
109 | {
110 | AddHoverText(tooltip);
111 | }
112 | }
113 | }
114 |
115 | public static void StaticLabelWithIconOnBothSides(FontAwesomeIcon icon, string? text, TextAlignment align = TextAlignment.Left, string tooltip = "")
116 | {
117 | if (text != null)
118 | {
119 | if (align == TextAlignment.Center)
120 | {
121 | ImGui.Dummy(new System.Numerics.Vector2((ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize(text).X - 30) / 2, 0));
122 | ImGui.SameLine();
123 | }
124 | else if (align == TextAlignment.Right)
125 | {
126 | ImGui.Dummy(new System.Numerics.Vector2(ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize(text).X - 30, 0));
127 | ImGui.SameLine();
128 | }
129 |
130 | ImGui.PushFont(UiBuilder.IconFont);
131 | ImGui.Text(icon.ToIconString());
132 | ImGui.PopFont();
133 | ImGui.SameLine();
134 | ImGui.Text(text);
135 | ImGui.SameLine();
136 | ImGui.PushFont(UiBuilder.IconFont);
137 | ImGui.Text(icon.ToIconString());
138 | ImGui.PopFont();
139 |
140 | if (!tooltip.IsNullOrWhitespace())
141 | {
142 | AddHoverText(tooltip);
143 | }
144 | }
145 | }
146 |
147 | public static void LabelWithIcon(FontAwesomeIcon icon, string text)
148 | {
149 | ImGui.SameLine();
150 | ImGui.PushFont(UiBuilder.IconFont);
151 | ImGui.Text(icon.ToIconString());
152 | ImGui.PopFont();
153 | ImGui.SameLine();
154 | ImGui.TextWrapped(text);
155 | }
156 | }
157 | }
--------------------------------------------------------------------------------
/CustomizePlus/Plugin.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | // Signautres stolen from:
5 | // https://github.com/0ceal0t/DXTest/blob/8e9aef4f6f871e7743aafe56deb9e8ad4dc87a0d/SamplePlugin/Plugin.DX.cs
6 | // I don't know how they work, but they do!
7 |
8 | using System;
9 | using CustomizePlus.Extensions;
10 | using CustomizePlus.Helpers;
11 | using CustomizePlus.Services;
12 | using CustomizePlus.UI;
13 | using CustomizePlus.UI.Windows;
14 | using Dalamud.Logging;
15 | using Dalamud.Plugin;
16 | using FFXIVClientStructs.FFXIV.Client.UI;
17 |
18 | namespace CustomizePlus
19 | {
20 | public sealed class Plugin : IDalamudPlugin
21 | {
22 | public string Name => "Customize Plus";
23 |
24 | public static UserInterfaceManager InterfaceManager { get; } = new();
25 |
26 | public Plugin(DalamudPluginInterface pluginInterface)
27 | {
28 | try
29 | {
30 | DalamudServices.Initialize(pluginInterface);
31 | DalamudServices.PluginInterface.UiBuilder.DisableGposeUiHide = true;
32 |
33 | DalamudServices.CommandManager.AddCommand((s, t) => MainWindow.Toggle(), "/customize",
34 | "Toggles the Customize+ configuration window.");
35 | DalamudServices.CommandManager.AddCommand((s, t) => MainWindow.Toggle(), "/c+",
36 | "Toggles the Customize+ configuration window.");
37 |
38 | DalamudServices.PluginInterface.UiBuilder.Draw += InterfaceManager.Draw;
39 | DalamudServices.PluginInterface.UiBuilder.OpenConfigUi += MainWindow.Toggle;
40 |
41 | MainWindow.Show();
42 |
43 | ChatHelper.PrintInChat("Customize+ Started!");
44 |
45 | UIModule.PlayChatSoundEffect(11);
46 | ChatHelper.PrintInChat("CUSTOMIZE+ IS NO LONGER FUNCTIONAL, OPEN SETTINGS FOR DETAILS");
47 | }
48 | catch (Exception ex)
49 | {
50 | PluginLog.Error(ex, "Error instantiating plugin");
51 | ChatHelper.PrintInChat(
52 | "An error occurred while starting Customize+. See the Dalamud log for more details");
53 | }
54 | }
55 |
56 | public void Dispose()
57 | {
58 | InterfaceManager.Dispose();
59 |
60 | CommandManagerExtensions.Dispose();
61 |
62 | DalamudServices.PluginInterface.UiBuilder.Draw -= InterfaceManager.Draw;
63 | DalamudServices.PluginInterface.UiBuilder.OpenConfigUi -= MainWindow.Show;
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/CustomizePlus/Services/DalamudServices.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using Dalamud.Game;
5 | using Dalamud.IoC;
6 | using Dalamud.Plugin;
7 | using Dalamud.Plugin.Services;
8 |
9 | namespace CustomizePlus.Services
10 | {
11 | public class DalamudServices
12 | {
13 |
14 |
15 | [PluginService]
16 | [RequiredVersion("1.0")]
17 | public static DalamudPluginInterface PluginInterface { get; private set; } = null!;
18 |
19 | [PluginService]
20 | [RequiredVersion("1.0")]
21 | public static ISigScanner SigScanner { get; private set; } = null!;
22 |
23 | [PluginService]
24 | public static IFramework Framework { get; private set; } = null!;
25 |
26 | [PluginService]
27 | [RequiredVersion("1.0")]
28 | public static IObjectTable ObjectTable { get; private set; } = null!;
29 |
30 | [PluginService]
31 | [RequiredVersion("1.0")]
32 | public static ICommandManager CommandManager { get; private set; } = null!;
33 |
34 | [PluginService]
35 | [RequiredVersion("1.0")]
36 | public static IChatGui ChatGui { get; private set; } = null!;
37 |
38 | [PluginService]
39 | [RequiredVersion("1.0")]
40 | public static IClientState ClientState { get; private set; } = null!;
41 |
42 | [PluginService]
43 | [RequiredVersion("1.0")]
44 | public static IGameGui GameGui { get; private set; } = null!;
45 |
46 | [PluginService]
47 | [RequiredVersion("1.0")]
48 | internal static IGameInteropProvider Hooker { get; private set; } = null!;
49 |
50 | public static void Initialize(DalamudPluginInterface pluginInterface)
51 | {
52 | pluginInterface.Create();
53 | }
54 |
55 | public static void Destroy()
56 | {
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/CustomizePlus/UI/UserInterfaceBase.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 |
6 | namespace CustomizePlus.UI
7 | {
8 | public abstract class UserInterfaceBase : IDisposable
9 | {
10 | public bool IsOpen { get; private set; }
11 |
12 | protected int Index { get; private set; }
13 | protected UserInterfaceManager Manager => Plugin.InterfaceManager;
14 |
15 | protected virtual bool SingleInstance => false;
16 |
17 | public virtual void Dispose()
18 | {
19 | }
20 |
21 | public virtual void Open()
22 | {
23 | if (SingleInstance)
24 | {
25 | var instance = Manager.GetUserInterface(GetType());
26 | if (instance != null)
27 | {
28 | instance?.Focus();
29 | return;
30 | }
31 | }
32 |
33 | IsOpen = true;
34 | }
35 |
36 | public virtual void Focus()
37 | {
38 | // ??
39 | }
40 |
41 | public abstract void Draw();
42 |
43 | public virtual void Close()
44 | {
45 | IsOpen = false;
46 | }
47 |
48 | internal void DoDraw(int index)
49 | {
50 | Index = index;
51 | Draw();
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/CustomizePlus/UI/UserInterfaceManager.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 |
7 | namespace CustomizePlus.UI
8 | {
9 | public class UserInterfaceManager : IDisposable
10 | {
11 | private readonly List _interfaces = new();
12 |
13 | public void Dispose()
14 | {
15 | foreach (var iface in _interfaces)
16 | {
17 | iface.Close();
18 | iface.Dispose();
19 | }
20 |
21 | _interfaces.Clear();
22 | }
23 |
24 | public void Draw()
25 | {
26 | if (_interfaces.Count <= 0)
27 | {
28 | return;
29 | }
30 |
31 | for (var i = _interfaces.Count - 1; i >= 0; i--)
32 | {
33 | _interfaces[i].DoDraw(i);
34 |
35 | if (!_interfaces[i].IsOpen)
36 | {
37 | _interfaces[i].Dispose();
38 | _interfaces.RemoveAt(i);
39 | }
40 | }
41 | }
42 |
43 | public T Show()
44 | where T : UserInterfaceBase
45 | {
46 | //todo: do not allow more than a single instance of the same window?
47 | var ui = Activator.CreateInstance();
48 | ui.Open();
49 |
50 | if (ui.IsOpen)
51 | {
52 | _interfaces.Add(ui);
53 | }
54 |
55 | return ui;
56 | }
57 |
58 | // Added this so you can close with /customize. This may need a rework in the future to access the broader usecase of the rest of the methods. But this should serve for now?
59 | public void Toggle()
60 | where T : UserInterfaceBase, new()
61 | {
62 | if (_interfaces.Count <= 0)
63 | {
64 | new InvalidOperationException("Interfaces is empty.");
65 | }
66 |
67 | // Close all windows, if we closed any window set 'switchedOff' to true so we know we are hiding interfaces.
68 | // If we did not turn anything off, we probably want to show our window.
69 | if (!CloseAllUserInterfaces())
70 | {
71 | Show();
72 | }
73 | }
74 |
75 | // Closes all Interfaces, returns true if at least one Interface was closed.
76 | public bool CloseAllUserInterfaces()
77 | {
78 | var interfaceWasClosed = false;
79 | foreach (var currentInterface in _interfaces)
80 | {
81 | if (currentInterface.IsOpen)
82 | {
83 | currentInterface.Close();
84 | interfaceWasClosed = true;
85 | }
86 | }
87 |
88 | return interfaceWasClosed;
89 | }
90 |
91 | public UserInterfaceBase? GetUserInterface(Type type)
92 | {
93 | foreach (var ui in _interfaces)
94 | {
95 | if (ui.GetType().IsAssignableTo(type))
96 | {
97 | return ui;
98 | }
99 | }
100 |
101 | return null;
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/CustomizePlus/UI/WindowBase.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using System.Numerics;
5 | using ImGuiNET;
6 |
7 | namespace CustomizePlus.UI
8 | {
9 | public abstract class WindowBase : UserInterfaceBase
10 | {
11 | private bool _isAlwaysVisibleDummy = true; //dummy variable for LockCloseButton = true
12 | private bool _isVisible;
13 |
14 | protected abstract string Title { get; }
15 |
16 | protected virtual Vector2? ForcedSize { get; set; }
17 | protected virtual Vector2 MinSize => new(600, 256);
18 | protected virtual Vector2 MaxSize => new(2560, 1440);
19 |
20 | protected virtual ImGuiWindowFlags WindowFlags { get; set; } = ImGuiWindowFlags.None;
21 | protected virtual bool LockCloseButton { get; set; }
22 |
23 | ///
24 | /// Gets normally you wouldn't want to override this.
25 | ///
26 | protected virtual string DrawTitle => $"{Title}";
27 |
28 | public override void Open()
29 | {
30 | base.Open();
31 | _isVisible = true;
32 | }
33 |
34 | public override void Focus()
35 | {
36 | ImGui.SetWindowFocus(DrawTitle);
37 | base.Focus();
38 | }
39 |
40 | public sealed override void Draw()
41 | {
42 | ImGui.SetNextWindowSizeConstraints(MinSize, MaxSize);
43 |
44 | if (ForcedSize != null)
45 | {
46 | ImGui.SetNextWindowSize((Vector2)ForcedSize);
47 | }
48 |
49 | if (ImGui.Begin(DrawTitle, ref LockCloseButton ? ref _isAlwaysVisibleDummy : ref _isVisible, WindowFlags))
50 | {
51 | DrawContents();
52 | }
53 |
54 | ImGui.End();
55 |
56 | if (!_isVisible)
57 | {
58 | Close();
59 | }
60 | }
61 |
62 | protected abstract void DrawContents();
63 | }
64 | }
--------------------------------------------------------------------------------
/CustomizePlus/UI/Windows/MainWindow.cs:
--------------------------------------------------------------------------------
1 | // © Customize+.
2 | // Licensed under the MIT license.
3 |
4 | using System.Diagnostics;
5 | using System.Drawing;
6 | using System.Numerics;
7 | using System.Windows.Forms;
8 | using CustomizePlus.Helpers;
9 | using Dalamud.Interface;
10 | using ImGuiNET;
11 |
12 | namespace CustomizePlus.UI.Windows
13 | {
14 | public class MainWindow : WindowBase
15 | {
16 | private static Vector4 WarningColor = new Vector4(1, 0.5f, 0, 1);
17 |
18 | protected override string Title => "Customize+";
19 | protected override bool SingleInstance => true;
20 |
21 | public static void Show()
22 | {
23 | Plugin.InterfaceManager.Show();
24 | }
25 |
26 | public static void Toggle()
27 | {
28 | Plugin.InterfaceManager.Toggle();
29 | }
30 |
31 | protected override void DrawContents()
32 | {
33 | ImGui.PushStyleColor(ImGuiCol.Text, WarningColor);
34 | CtrlHelper.StaticLabelWithIconOnBothSides(FontAwesomeIcon.ExclamationTriangle, "ATTENTION, PLEASE READ!", CtrlHelper.TextAlignment.Center);
35 | ImGui.PopStyleColor();
36 | CtrlHelper.StaticLabel("You need to update Customize+ to latest version. Currently installed version is no longer functional.", CtrlHelper.TextAlignment.Center);
37 | CtrlHelper.StaticLabel("Please delete your current version, remove XIV-Tools repository if you are using it and install Customize+ from the following url: https://github.com/Aether-Tools/CustomizePlus", CtrlHelper.TextAlignment.Center);
38 | ImGui.PushStyleColor(ImGuiCol.Text, WarningColor);
39 | CtrlHelper.StaticLabelWithIconOnBothSides(FontAwesomeIcon.ExclamationTriangle, "Your settings will be automatically migrated to new version.", CtrlHelper.TextAlignment.Center);
40 | ImGui.PopStyleColor();
41 |
42 | CtrlHelper.StaticLabel("If you need help, feel free to join support discord: https://discord.gg/KvGJCCnG8t", CtrlHelper.TextAlignment.Center);
43 |
44 | ImGui.Dummy(new Vector2((ImGui.GetContentRegionAvail().X / 2) - 150, 0));
45 | ImGui.SameLine();
46 | if (ImGui.Button("Copy Repository Link"))
47 | {
48 | Clipboard.SetText("https://raw.githubusercontent.com/Aether-Tools/DalamudPlugins/main/repo.json");
49 | }
50 | ImGui.SameLine();
51 | if (ImGui.Button("Open Link to GitHub"))
52 | {
53 | Process.Start(new ProcessStartInfo("https://github.com/Aether-Tools/CustomizePlus") { UseShellExecute = true });
54 | }
55 | ImGui.Dummy(new Vector2((ImGui.GetContentRegionAvail().X / 2) - 75, 0));
56 | ImGui.SameLine();
57 | if (ImGui.Button("Join Support Discord"))
58 | {
59 | Process.Start(new ProcessStartInfo("https://discord.gg/KvGJCCnG8t") { UseShellExecute = true });
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/CustomizePlus/customizePlus.json:
--------------------------------------------------------------------------------
1 | {
2 | "Author": "XIV Tools",
3 | "Name": "Customize+",
4 | "Punchline": "Customize your character beyond FFXIV's limitations.",
5 | "Description": "A plugin that allows you to create and apply Anamnesis-style body scaling full time.",
6 | "InternalName": "CustomizePlus",
7 | "ApplicableVersion": "any",
8 | "DalamudApiLevel": 9,
9 | "Tags": [
10 | "anamnesis",
11 | "customize",
12 | "XIV Tools"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/Data/NotoSansCJKjp-Medium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XIV-Tools/CustomizePlus/7c5aaed442c5e3b4fb61a511adfce3d9b4a319c0/Data/NotoSansCJKjp-Medium.otf
--------------------------------------------------------------------------------
/Data/customizePlus.json:
--------------------------------------------------------------------------------
1 | {
2 | "Author": "XIV Tools",
3 | "Name": "Customize Plus",
4 | "Punchline": "Customize your character beyond FFXIV's limitations.",
5 | "Description": "A plugin that allows you to create and apply Anamnesis-style body scaling full time.",
6 | "InternalName": "CustomizePlus",
7 | "ApplicableVersion": "any",
8 | "Tags": [
9 | "anamnesis",
10 | "customize",
11 | "XIV Tools"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/Data/gamesym.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XIV-Tools/CustomizePlus/7c5aaed442c5e3b4fb61a511adfce3d9b4a319c0/Data/gamesym.ttf
--------------------------------------------------------------------------------
/Data/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XIV-Tools/CustomizePlus/7c5aaed442c5e3b4fb61a511adfce3d9b4a319c0/Data/icon.png
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021-2023 Customize+ Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Repository has been moved
2 | Customize+ repository is now located at https://github.com/Aether-Tools/CustomizePlus
--------------------------------------------------------------------------------