Skip to content

Commit ff0a71c

Browse files
authored
Theme improvements (#162)
* minor improvements & comments for drawables * lots of theme improvements * introduce WidgetThemeKey & sub themes * show theme id in debug info * color type * helpers for building themes in java * minor additions (:trol:) * fixes * things
1 parent da1de39 commit ff0a71c

File tree

80 files changed

+1741
-788
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+1741
-788
lines changed

dependencies.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ dependencies {
2525
embed 'org.mariuszgromada.math:MathParser.org-mXparser:6.1.0'
2626

2727
implementation(rfg.deobf("curse.maven:baubles-227083:2518667"))
28-
implementation rfg.deobf("curse.maven:neverenoughanimation-1062347:6533650-sources-6533651")
28+
compileOnlyApi rfg.deobf("curse.maven:neverenoughanimation-1062347:6533650-sources-6533651")
2929
//implementation("com.cleanroommc:neverenoughanimations:1.0.6") { transitive false }
3030
}

src/main/java/com/cleanroommc/modularui/ModularUIConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ public class ModularUIConfig {
1313
public static int defaultScrollSpeed = 30;
1414

1515
@Config.Comment("If progress bar should step in texture pixels or screen pixels. (Screen pixels are way smaller and therefore smoother)")
16-
public static boolean smoothProgressBar = true;
16+
public static boolean smoothProgressBar = false;
1717

1818
// Default direction
1919
@Config.Comment("Default tooltip position around the widget or its panel.")
20-
public static RichTooltip.Pos tooltipPos = RichTooltip.Pos.VERTICAL;
20+
public static RichTooltip.Pos tooltipPos = RichTooltip.Pos.NEXT_TO_MOUSE;
2121

2222
@Config.Comment("If true, pressing ESC key in the text field will restore the last text instead of confirming current one.")
2323
public static boolean escRestoreLastText = false;

src/main/java/com/cleanroommc/modularui/api/ITheme.java

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package com.cleanroommc.modularui.api;
22

3-
import com.cleanroommc.modularui.screen.RichTooltip;
4-
import com.cleanroommc.modularui.theme.WidgetSlotTheme;
5-
import com.cleanroommc.modularui.theme.WidgetTextFieldTheme;
3+
import com.cleanroommc.modularui.theme.SelectableTheme;
4+
import com.cleanroommc.modularui.theme.SlotTheme;
5+
import com.cleanroommc.modularui.theme.TextFieldTheme;
66
import com.cleanroommc.modularui.theme.WidgetTheme;
7-
import com.cleanroommc.modularui.theme.WidgetThemeSelectable;
7+
import com.cleanroommc.modularui.theme.WidgetThemeEntry;
8+
import com.cleanroommc.modularui.theme.WidgetThemeKey;
9+
10+
import org.jetbrains.annotations.UnmodifiableView;
11+
12+
import java.util.Collection;
813

914
/**
1015
* A theme is parsed from json and contains style information like color or background texture.
@@ -36,31 +41,22 @@ static ITheme get(String id) {
3641
*/
3742
ITheme getParentTheme();
3843

39-
WidgetTheme getFallback();
40-
41-
WidgetTheme getPanelTheme();
44+
@UnmodifiableView
45+
Collection<WidgetThemeEntry<?>> getWidgetThemes();
4246

43-
WidgetTheme getButtonTheme();
47+
WidgetThemeEntry<WidgetTheme> getFallback();
4448

45-
WidgetSlotTheme getItemSlotTheme();
49+
WidgetThemeEntry<WidgetTheme> getPanelTheme();
4650

47-
WidgetSlotTheme getFluidSlotTheme();
51+
WidgetThemeEntry<WidgetTheme> getButtonTheme();
4852

49-
WidgetTextFieldTheme getTextFieldTheme();
53+
WidgetThemeEntry<SlotTheme> getItemSlotTheme();
5054

51-
WidgetThemeSelectable getToggleButtonTheme();
55+
WidgetThemeEntry<SlotTheme> getFluidSlotTheme();
5256

53-
WidgetTheme getWidgetTheme(String id);
54-
55-
default <T extends WidgetTheme> T getWidgetTheme(Class<T> clazz, String id) {
56-
WidgetTheme theme = getWidgetTheme(id);
57-
if (clazz.isInstance(theme)) {
58-
return (T) theme;
59-
}
60-
return null;
61-
}
57+
WidgetThemeEntry<TextFieldTheme> getTextFieldTheme();
6258

63-
boolean getSmoothProgressBarOverride();
59+
WidgetThemeEntry<SelectableTheme> getToggleButtonTheme();
6460

65-
RichTooltip.Pos getTooltipPosOverride();
61+
<T extends WidgetTheme> WidgetThemeEntry<T> getWidgetTheme(WidgetThemeKey<T> key);
6662
}

src/main/java/com/cleanroommc/modularui/api/IThemeApi.java

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,89 @@
11
package com.cleanroommc.modularui.api;
22

3+
import com.cleanroommc.modularui.drawable.GuiTextures;
34
import com.cleanroommc.modularui.screen.ModularScreen;
5+
import com.cleanroommc.modularui.theme.SelectableTheme;
6+
import com.cleanroommc.modularui.theme.SlotTheme;
7+
import com.cleanroommc.modularui.theme.TextFieldTheme;
48
import com.cleanroommc.modularui.theme.ThemeAPI;
9+
import com.cleanroommc.modularui.theme.ThemeBuilder;
510
import com.cleanroommc.modularui.theme.WidgetTheme;
11+
import com.cleanroommc.modularui.theme.WidgetThemeKey;
12+
import com.cleanroommc.modularui.theme.WidgetThemeKeyBuilder;
613
import com.cleanroommc.modularui.theme.WidgetThemeParser;
714
import com.cleanroommc.modularui.utils.JsonBuilder;
815

16+
import org.jetbrains.annotations.ApiStatus;
917
import org.jetbrains.annotations.Contract;
1018
import org.jetbrains.annotations.NotNull;
1119
import org.jetbrains.annotations.Nullable;
20+
import org.jetbrains.annotations.UnmodifiableView;
1221

1322
import java.util.List;
1423

1524
/**
1625
* An API interface for Themes.
1726
*/
27+
@ApiStatus.NonExtendable
1828
public interface IThemeApi {
1929

2030
// widget themes
21-
String FALLBACK = "default";
22-
String PANEL = "panel";
23-
String BUTTON = "button";
24-
String ITEM_SLOT = "itemSlot";
25-
String FLUID_SLOT = "fluidSlot";
26-
String TEXT_FIELD = "textField";
27-
String TOGGLE_BUTTON = "toggleButton";
31+
WidgetThemeKey<WidgetTheme> FALLBACK = get().widgetThemeKeyBuilder("default", WidgetTheme.class)
32+
.defaultTheme(WidgetTheme.darkTextNoShadow(18, 18, null))
33+
.register();
34+
35+
WidgetThemeKey<WidgetTheme> PANEL = get().widgetThemeKeyBuilder("panel", WidgetTheme.class)
36+
.defaultTheme(WidgetTheme.darkTextNoShadow(176, 166, GuiTextures.MC_BACKGROUND))
37+
.register();
38+
39+
WidgetThemeKey<WidgetTheme> BUTTON = get().widgetThemeKeyBuilder("button", WidgetTheme.class)
40+
.defaultTheme(WidgetTheme.whiteTextShadow(18, 18, GuiTextures.MC_BUTTON))
41+
.defaultHoverTheme(WidgetTheme.whiteTextShadow(18, 18, GuiTextures.MC_BUTTON_HOVERED))
42+
.register();
43+
44+
WidgetThemeKey<SlotTheme> ITEM_SLOT = get().widgetThemeKeyBuilder("itemSlot", SlotTheme.class)
45+
.defaultTheme(new SlotTheme(GuiTextures.SLOT_ITEM))
46+
.register();
47+
48+
WidgetThemeKey<SlotTheme> FLUID_SLOT = get().widgetThemeKeyBuilder("fluidSlot", SlotTheme.class)
49+
.defaultTheme(new SlotTheme(GuiTextures.SLOT_FLUID))
50+
.register();
51+
52+
WidgetThemeKey<TextFieldTheme> TEXT_FIELD = get().widgetThemeKeyBuilder("textField", TextFieldTheme.class)
53+
.defaultTheme(new TextFieldTheme(0xFF2F72A8, 0xFF5F5F5F))
54+
.register();
55+
56+
WidgetThemeKey<SelectableTheme> TOGGLE_BUTTON = get().widgetThemeKeyBuilder("toggleButton", SelectableTheme.class)
57+
.defaultTheme(SelectableTheme.whiteTextShadow(18, 18, GuiTextures.MC_BUTTON, GuiTextures.MC_BUTTON_DISABLED))
58+
.defaultHoverTheme(SelectableTheme.whiteTextShadow(18, 18, GuiTextures.MC_BUTTON_HOVERED, GuiTextures.MC_BUTTON_DISABLED))
59+
.register();
60+
61+
// sub widget themes
62+
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER = ITEM_SLOT.createSubKey("player");
63+
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER_HOTBAR = ITEM_SLOT_PLAYER.createSubKey("playerHotbar");
64+
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER_MAIN_INV = ITEM_SLOT_PLAYER.createSubKey("playerMainInventory");
65+
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER_OFFHAND = ITEM_SLOT_PLAYER.createSubKey("playerOffhand");
66+
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER_ARMOR = ITEM_SLOT_PLAYER.createSubKey("playerArmor");
67+
68+
String HOVER_SUFFIX = ":hover";
2869

2970
// properties
3071
String PARENT = "parent";
72+
String DEFAULT_WIDTH = "defaultWidth";
73+
String DEFAULT_HEIGHT = "defaultHeight";
3174
String BACKGROUND = "background";
32-
String HOVER_BACKGROUND = "hoverBackground";
3375
String COLOR = "color";
3476
String TEXT_COLOR = "textColor";
3577
String TEXT_SHADOW = "textShadow";
78+
String ICON_COLOR = "iconColor";
3679
String SLOT_HOVER_COLOR = "slotHoverColor";
3780
String MARKED_COLOR = "markedColor";
3881
String HINT_COLOR = "hintColor";
3982
String SELECTED_BACKGROUND = "selectedBackground";
40-
String SELECTED_HOVER_BACKGROUND = "selectedHoverBackground";
4183
String SELECTED_COLOR = "selectedColor";
4284
String SELECTED_TEXT_COLOR = "selectedTextColor";
4385
String SELECTED_TEXT_SHADOW = "selectedTextShadow";
86+
String SELECTED_ICON_COLOR = "selectedIconColor";
4487

4588
/**
4689
* @return the default api implementation
@@ -70,20 +113,24 @@ static IThemeApi get() {
70113
*/
71114
boolean hasTheme(String id);
72115

73-
/**
74-
* @param id id of the widget theme
75-
* @return if a widget theme with the id is registered
76-
*/
77-
boolean hasWidgetTheme(String id);
78-
79116
/**
80117
* Registers a theme json object. Themes from resource packs always have greater priority.
118+
* Json builders are used here as they are much easier to merge as opposed to normal java objects.
81119
*
82120
* @param id id of the theme
83121
* @param json theme data
84122
*/
85123
void registerTheme(String id, JsonBuilder json);
86124

125+
/**
126+
* Registers a theme json object. Themes from resource packs always have greater priority.
127+
*
128+
* @param themeBuilder theme data
129+
*/
130+
default void registerTheme(ThemeBuilder<?> themeBuilder) {
131+
registerTheme(themeBuilder.getId(), themeBuilder);
132+
}
133+
87134
/**
88135
* Gets all currently from java side registered theme json's for a theme.
89136
*
@@ -133,11 +180,20 @@ default void registerThemeForScreen(String owner, String name, String theme) {
133180
void registerThemeForScreen(String screen, String theme);
134181

135182
/**
136-
* Register a widget theme.
183+
* Registers a widget theme. It is recommended to store the resulting key in a static variable and make it accessible by public methods.
137184
*
138-
* @param id id of the widget theme
139-
* @param defaultTheme the fallback widget theme
140-
* @param parser the widget theme json parser function
185+
* @param id id of the widget theme
186+
* @param defaultTheme the fallback widget theme
187+
* @param defaultHoverTheme the fallback hover widget theme
188+
* @param parser the widget theme json parser function. This is usually another constructor.
189+
* @return key to access the widget theme
141190
*/
142-
void registerWidgetTheme(String id, WidgetTheme defaultTheme, WidgetThemeParser parser);
191+
<T extends WidgetTheme> WidgetThemeKey<T> registerWidgetTheme(String id, T defaultTheme, T defaultHoverTheme, WidgetThemeParser<T> parser);
192+
193+
default <T extends WidgetTheme> WidgetThemeKeyBuilder<T> widgetThemeKeyBuilder(String id, Class<T> type) {
194+
return new WidgetThemeKeyBuilder<>(id);
195+
}
196+
197+
@UnmodifiableView
198+
List<WidgetThemeKey<?>> getWidgetThemeKeys();
143199
}

src/main/java/com/cleanroommc/modularui/api/drawable/IDrawable.java

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import com.cleanroommc.modularui.screen.viewport.GuiContext;
66
import com.cleanroommc.modularui.screen.viewport.ModularGuiContext;
77
import com.cleanroommc.modularui.theme.WidgetTheme;
8+
import com.cleanroommc.modularui.theme.WidgetThemeEntry;
9+
import com.cleanroommc.modularui.utils.Color;
810
import com.cleanroommc.modularui.widget.Widget;
911
import com.cleanroommc.modularui.widget.sizer.Area;
1012

@@ -14,8 +16,9 @@
1416
import org.jetbrains.annotations.Nullable;
1517

1618
/**
17-
* An object which can be drawn. This is mainly used for backgrounds and overlays in
19+
* An object which can be drawn at any size. This is mainly used for backgrounds and overlays in
1820
* {@link com.cleanroommc.modularui.api.widget.IWidget}.
21+
* To draw at a fixed size, use {@link IIcon} (see {@link #asIcon()}).
1922
*/
2023
public interface IDrawable {
2124

@@ -30,7 +33,8 @@ static IDrawable of(IDrawable... drawables) {
3033
}
3134

3235
/**
33-
* Draws this drawable at the given position with the given size.
36+
* Draws this drawable at the given position with the given size. It's the implementors responsibility to properly apply the widget
37+
* theme by calling {@link #applyColor(int)} before drawing.
3438
*
3539
* @param context current context to draw with
3640
* @param x x position
@@ -43,25 +47,8 @@ static IDrawable of(IDrawable... drawables) {
4347
void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme);
4448

4549
/**
46-
* @deprecated use {@link #draw(GuiContext, int, int, int, int, WidgetTheme)}
47-
*/
48-
@SideOnly(Side.CLIENT)
49-
@Deprecated
50-
default void draw(GuiContext context, int x, int y, int width, int height) {
51-
draw(context, x, y, width, height, WidgetTheme.getDefault());
52-
}
53-
54-
/**
55-
* @deprecated use {@link #drawAtZero(GuiContext, int, int, WidgetTheme)}
56-
*/
57-
@SideOnly(Side.CLIENT)
58-
@Deprecated
59-
default void drawAtZero(GuiContext context, int width, int height) {
60-
drawAtZero(context, width, height, WidgetTheme.getDefault());
61-
}
62-
63-
/**
64-
* Draws this drawable at the current (0|0) with the given size.
50+
* Draws this drawable at the current (0|0) with the given size. This is useful inside widgets since GL is transformed to their
51+
* position when they are drawing.
6552
*
6653
* @param context gui context
6754
* @param width draw width
@@ -73,15 +60,6 @@ default void drawAtZero(GuiContext context, int width, int height, WidgetTheme w
7360
draw(context, 0, 0, width, height, widgetTheme);
7461
}
7562

76-
/**
77-
* @deprecated use {@link #draw(GuiContext, Area, WidgetTheme)}
78-
*/
79-
@SideOnly(Side.CLIENT)
80-
@Deprecated
81-
default void draw(GuiContext context, Area area) {
82-
draw(context, area, WidgetTheme.getDefault());
83-
}
84-
8563
/**
8664
* Draws this drawable in a given area.
8765
*
@@ -95,16 +73,8 @@ default void draw(GuiContext context, Area area, WidgetTheme widgetTheme) {
9573
}
9674

9775
/**
98-
* @deprecated use {@link #drawAtZero(GuiContext, Area, WidgetTheme)}
99-
*/
100-
@Deprecated
101-
@SideOnly(Side.CLIENT)
102-
default void drawAtZero(GuiContext context, Area area) {
103-
drawAtZero(context, area, WidgetTheme.getDefault());
104-
}
105-
106-
/**
107-
* Draws this drawable at the current (0|0) with the given area's size.
76+
* Draws this drawable at the current (0|0) with the given area's size. This is useful inside widgets since GL is transformed to their
77+
* position when they are drawing.
10878
*
10979
* @param context gui context
11080
* @param area draw area
@@ -122,6 +92,21 @@ default boolean canApplyTheme() {
12292
return false;
12393
}
12494

95+
/**
96+
* Applies the theme color to OpenGL if this drawable can have theme colors applied. This is determined by {@link #canApplyTheme()}.
97+
* If this drawable does not allow theme colors, it will reset the current color (to white).
98+
* This method should be called before drawing.
99+
*
100+
* @param themeColor theme color to apply (usually {@link WidgetTheme#getColor()})
101+
*/
102+
default void applyColor(int themeColor) {
103+
if (canApplyTheme()) {
104+
Color.setGlColor(themeColor);
105+
} else {
106+
Color.setGlColorOpaque(Color.WHITE.main);
107+
}
108+
}
109+
125110
/**
126111
* @return a widget with this drawable as a background
127112
*/
@@ -167,8 +152,8 @@ public DrawableWidget(IDrawable drawable) {
167152

168153
@SideOnly(Side.CLIENT)
169154
@Override
170-
public void draw(ModularGuiContext context, WidgetTheme widgetTheme) {
171-
this.drawable.drawAtZero(context, getArea(), widgetTheme);
155+
public void draw(ModularGuiContext context, WidgetThemeEntry<?> widgetTheme) {
156+
this.drawable.drawAtZero(context, getArea(), getActiveWidgetTheme(widgetTheme, isHovering()));
172157
}
173158
}
174159
}

src/main/java/com/cleanroommc/modularui/api/drawable/IIcon.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,19 @@ default IDrawable getRootDrawable() {
4040
return drawable;
4141
}
4242

43+
/**
44+
* This returns a hoverable wrapper of this icon. This is only used in {@link com.cleanroommc.modularui.drawable.text.RichText RichText}.
45+
* This allows this icon to have its own tooltip.
46+
*/
4347
default HoverableIcon asHoverable() {
4448
return new HoverableIcon(this);
4549
}
4650

51+
/**
52+
* This returns an interactable wrapper of this icon. This is only used in
53+
* {@link com.cleanroommc.modularui.drawable.text.RichText RichText}. This allows this icon to be able to listen to clicks and other
54+
* inputs.
55+
*/
4756
default InteractableIcon asInteractable() {
4857
return new InteractableIcon(this);
4958
}

src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ default void draw(GuiContext context, int x, int y, int width, int height, Widge
200200
}
201201

202202
@Override
203+
default boolean canApplyTheme() {
204+
return true;
205+
}
206+
203207
default TextWidget<?> asWidget() {
204208
return new TextWidget<>(this);
205209
}

0 commit comments

Comments
 (0)