Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ dependencies {
embed 'org.mariuszgromada.math:MathParser.org-mXparser:6.1.0'

implementation(rfg.deobf("curse.maven:baubles-227083:2518667"))
implementation rfg.deobf("curse.maven:neverenoughanimation-1062347:6533650-sources-6533651")
compileOnlyApi rfg.deobf("curse.maven:neverenoughanimation-1062347:6533650-sources-6533651")
//implementation("com.cleanroommc:neverenoughanimations:1.0.6") { transitive false }
}
4 changes: 2 additions & 2 deletions src/main/java/com/cleanroommc/modularui/ModularUIConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ public class ModularUIConfig {
public static int defaultScrollSpeed = 30;

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

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

@Config.Comment("If true, pressing ESC key in the text field will restore the last text instead of confirming current one.")
public static boolean escRestoreLastText = false;
Expand Down
42 changes: 19 additions & 23 deletions src/main/java/com/cleanroommc/modularui/api/ITheme.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.cleanroommc.modularui.api;

import com.cleanroommc.modularui.screen.RichTooltip;
import com.cleanroommc.modularui.theme.WidgetSlotTheme;
import com.cleanroommc.modularui.theme.WidgetTextFieldTheme;
import com.cleanroommc.modularui.theme.SelectableTheme;
import com.cleanroommc.modularui.theme.SlotTheme;
import com.cleanroommc.modularui.theme.TextFieldTheme;
import com.cleanroommc.modularui.theme.WidgetTheme;
import com.cleanroommc.modularui.theme.WidgetThemeSelectable;
import com.cleanroommc.modularui.theme.WidgetThemeEntry;
import com.cleanroommc.modularui.theme.WidgetThemeKey;

import org.jetbrains.annotations.UnmodifiableView;

import java.util.Collection;

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

WidgetTheme getFallback();

WidgetTheme getPanelTheme();
@UnmodifiableView
Collection<WidgetThemeEntry<?>> getWidgetThemes();

WidgetTheme getButtonTheme();
WidgetThemeEntry<WidgetTheme> getFallback();

WidgetSlotTheme getItemSlotTheme();
WidgetThemeEntry<WidgetTheme> getPanelTheme();

WidgetSlotTheme getFluidSlotTheme();
WidgetThemeEntry<WidgetTheme> getButtonTheme();

WidgetTextFieldTheme getTextFieldTheme();
WidgetThemeEntry<SlotTheme> getItemSlotTheme();

WidgetThemeSelectable getToggleButtonTheme();
WidgetThemeEntry<SlotTheme> getFluidSlotTheme();

WidgetTheme getWidgetTheme(String id);

default <T extends WidgetTheme> T getWidgetTheme(Class<T> clazz, String id) {
WidgetTheme theme = getWidgetTheme(id);
if (clazz.isInstance(theme)) {
return (T) theme;
}
return null;
}
WidgetThemeEntry<TextFieldTheme> getTextFieldTheme();

boolean getSmoothProgressBarOverride();
WidgetThemeEntry<SelectableTheme> getToggleButtonTheme();

RichTooltip.Pos getTooltipPosOverride();
<T extends WidgetTheme> WidgetThemeEntry<T> getWidgetTheme(WidgetThemeKey<T> key);
}
96 changes: 76 additions & 20 deletions src/main/java/com/cleanroommc/modularui/api/IThemeApi.java
Original file line number Diff line number Diff line change
@@ -1,46 +1,89 @@
package com.cleanroommc.modularui.api;

import com.cleanroommc.modularui.drawable.GuiTextures;
import com.cleanroommc.modularui.screen.ModularScreen;
import com.cleanroommc.modularui.theme.SelectableTheme;
import com.cleanroommc.modularui.theme.SlotTheme;
import com.cleanroommc.modularui.theme.TextFieldTheme;
import com.cleanroommc.modularui.theme.ThemeAPI;
import com.cleanroommc.modularui.theme.ThemeBuilder;
import com.cleanroommc.modularui.theme.WidgetTheme;
import com.cleanroommc.modularui.theme.WidgetThemeKey;
import com.cleanroommc.modularui.theme.WidgetThemeKeyBuilder;
import com.cleanroommc.modularui.theme.WidgetThemeParser;
import com.cleanroommc.modularui.utils.JsonBuilder;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnmodifiableView;

import java.util.List;

/**
* An API interface for Themes.
*/
@ApiStatus.NonExtendable
public interface IThemeApi {

// widget themes
String FALLBACK = "default";
String PANEL = "panel";
String BUTTON = "button";
String ITEM_SLOT = "itemSlot";
String FLUID_SLOT = "fluidSlot";
String TEXT_FIELD = "textField";
String TOGGLE_BUTTON = "toggleButton";
WidgetThemeKey<WidgetTheme> FALLBACK = get().widgetThemeKeyBuilder("default", WidgetTheme.class)
.defaultTheme(WidgetTheme.darkTextNoShadow(18, 18, null))
.register();

WidgetThemeKey<WidgetTheme> PANEL = get().widgetThemeKeyBuilder("panel", WidgetTheme.class)
.defaultTheme(WidgetTheme.darkTextNoShadow(176, 166, GuiTextures.MC_BACKGROUND))
.register();

WidgetThemeKey<WidgetTheme> BUTTON = get().widgetThemeKeyBuilder("button", WidgetTheme.class)
.defaultTheme(WidgetTheme.whiteTextShadow(18, 18, GuiTextures.MC_BUTTON))
.defaultHoverTheme(WidgetTheme.whiteTextShadow(18, 18, GuiTextures.MC_BUTTON_HOVERED))
.register();

WidgetThemeKey<SlotTheme> ITEM_SLOT = get().widgetThemeKeyBuilder("itemSlot", SlotTheme.class)
.defaultTheme(new SlotTheme(GuiTextures.SLOT_ITEM))
.register();

WidgetThemeKey<SlotTheme> FLUID_SLOT = get().widgetThemeKeyBuilder("fluidSlot", SlotTheme.class)
.defaultTheme(new SlotTheme(GuiTextures.SLOT_FLUID))
.register();

WidgetThemeKey<TextFieldTheme> TEXT_FIELD = get().widgetThemeKeyBuilder("textField", TextFieldTheme.class)
.defaultTheme(new TextFieldTheme(0xFF2F72A8, 0xFF5F5F5F))
.register();

WidgetThemeKey<SelectableTheme> TOGGLE_BUTTON = get().widgetThemeKeyBuilder("toggleButton", SelectableTheme.class)
.defaultTheme(SelectableTheme.whiteTextShadow(18, 18, GuiTextures.MC_BUTTON, GuiTextures.MC_BUTTON_DISABLED))
.defaultHoverTheme(SelectableTheme.whiteTextShadow(18, 18, GuiTextures.MC_BUTTON_HOVERED, GuiTextures.MC_BUTTON_DISABLED))
.register();

// sub widget themes
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER = ITEM_SLOT.createSubKey("player");
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER_HOTBAR = ITEM_SLOT_PLAYER.createSubKey("playerHotbar");
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER_MAIN_INV = ITEM_SLOT_PLAYER.createSubKey("playerMainInventory");
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER_OFFHAND = ITEM_SLOT_PLAYER.createSubKey("playerOffhand");
WidgetThemeKey<SlotTheme> ITEM_SLOT_PLAYER_ARMOR = ITEM_SLOT_PLAYER.createSubKey("playerArmor");

String HOVER_SUFFIX = ":hover";

// properties
String PARENT = "parent";
String DEFAULT_WIDTH = "defaultWidth";
String DEFAULT_HEIGHT = "defaultHeight";
String BACKGROUND = "background";
String HOVER_BACKGROUND = "hoverBackground";
String COLOR = "color";
String TEXT_COLOR = "textColor";
String TEXT_SHADOW = "textShadow";
String ICON_COLOR = "iconColor";
String SLOT_HOVER_COLOR = "slotHoverColor";
String MARKED_COLOR = "markedColor";
String HINT_COLOR = "hintColor";
String SELECTED_BACKGROUND = "selectedBackground";
String SELECTED_HOVER_BACKGROUND = "selectedHoverBackground";
String SELECTED_COLOR = "selectedColor";
String SELECTED_TEXT_COLOR = "selectedTextColor";
String SELECTED_TEXT_SHADOW = "selectedTextShadow";
String SELECTED_ICON_COLOR = "selectedIconColor";

/**
* @return the default api implementation
Expand Down Expand Up @@ -70,20 +113,24 @@ static IThemeApi get() {
*/
boolean hasTheme(String id);

/**
* @param id id of the widget theme
* @return if a widget theme with the id is registered
*/
boolean hasWidgetTheme(String id);

/**
* Registers a theme json object. Themes from resource packs always have greater priority.
* Json builders are used here as they are much easier to merge as opposed to normal java objects.
*
* @param id id of the theme
* @param json theme data
*/
void registerTheme(String id, JsonBuilder json);

/**
* Registers a theme json object. Themes from resource packs always have greater priority.
*
* @param themeBuilder theme data
*/
default void registerTheme(ThemeBuilder<?> themeBuilder) {
registerTheme(themeBuilder.getId(), themeBuilder);
}

/**
* Gets all currently from java side registered theme json's for a theme.
*
Expand Down Expand Up @@ -133,11 +180,20 @@ default void registerThemeForScreen(String owner, String name, String theme) {
void registerThemeForScreen(String screen, String theme);

/**
* Register a widget theme.
* Registers a widget theme. It is recommended to store the resulting key in a static variable and make it accessible by public methods.
*
* @param id id of the widget theme
* @param defaultTheme the fallback widget theme
* @param parser the widget theme json parser function
* @param id id of the widget theme
* @param defaultTheme the fallback widget theme
* @param defaultHoverTheme the fallback hover widget theme
* @param parser the widget theme json parser function. This is usually another constructor.
* @return key to access the widget theme
*/
void registerWidgetTheme(String id, WidgetTheme defaultTheme, WidgetThemeParser parser);
<T extends WidgetTheme> WidgetThemeKey<T> registerWidgetTheme(String id, T defaultTheme, T defaultHoverTheme, WidgetThemeParser<T> parser);

default <T extends WidgetTheme> WidgetThemeKeyBuilder<T> widgetThemeKeyBuilder(String id, Class<T> type) {
return new WidgetThemeKeyBuilder<>(id);
}

@UnmodifiableView
List<WidgetThemeKey<?>> getWidgetThemeKeys();
}
69 changes: 27 additions & 42 deletions src/main/java/com/cleanroommc/modularui/api/drawable/IDrawable.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.cleanroommc.modularui.screen.viewport.GuiContext;
import com.cleanroommc.modularui.screen.viewport.ModularGuiContext;
import com.cleanroommc.modularui.theme.WidgetTheme;
import com.cleanroommc.modularui.theme.WidgetThemeEntry;
import com.cleanroommc.modularui.utils.Color;
import com.cleanroommc.modularui.widget.Widget;
import com.cleanroommc.modularui.widget.sizer.Area;

Expand All @@ -14,8 +16,9 @@
import org.jetbrains.annotations.Nullable;

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

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

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

/**
* @deprecated use {@link #draw(GuiContext, int, int, int, int, WidgetTheme)}
*/
@SideOnly(Side.CLIENT)
@Deprecated
default void draw(GuiContext context, int x, int y, int width, int height) {
draw(context, x, y, width, height, WidgetTheme.getDefault());
}

/**
* @deprecated use {@link #drawAtZero(GuiContext, int, int, WidgetTheme)}
*/
@SideOnly(Side.CLIENT)
@Deprecated
default void drawAtZero(GuiContext context, int width, int height) {
drawAtZero(context, width, height, WidgetTheme.getDefault());
}

/**
* Draws this drawable at the current (0|0) with the given size.
* Draws this drawable at the current (0|0) with the given size. This is useful inside widgets since GL is transformed to their
* position when they are drawing.
*
* @param context gui context
* @param width draw width
Expand All @@ -73,15 +60,6 @@ default void drawAtZero(GuiContext context, int width, int height, WidgetTheme w
draw(context, 0, 0, width, height, widgetTheme);
}

/**
* @deprecated use {@link #draw(GuiContext, Area, WidgetTheme)}
*/
@SideOnly(Side.CLIENT)
@Deprecated
default void draw(GuiContext context, Area area) {
draw(context, area, WidgetTheme.getDefault());
}

/**
* Draws this drawable in a given area.
*
Expand All @@ -95,16 +73,8 @@ default void draw(GuiContext context, Area area, WidgetTheme widgetTheme) {
}

/**
* @deprecated use {@link #drawAtZero(GuiContext, Area, WidgetTheme)}
*/
@Deprecated
@SideOnly(Side.CLIENT)
default void drawAtZero(GuiContext context, Area area) {
drawAtZero(context, area, WidgetTheme.getDefault());
}

/**
* Draws this drawable at the current (0|0) with the given area's size.
* 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
* position when they are drawing.
*
* @param context gui context
* @param area draw area
Expand All @@ -122,6 +92,21 @@ default boolean canApplyTheme() {
return false;
}

/**
* Applies the theme color to OpenGL if this drawable can have theme colors applied. This is determined by {@link #canApplyTheme()}.
* If this drawable does not allow theme colors, it will reset the current color (to white).
* This method should be called before drawing.
*
* @param themeColor theme color to apply (usually {@link WidgetTheme#getColor()})
*/
default void applyColor(int themeColor) {
if (canApplyTheme()) {
Color.setGlColor(themeColor);
} else {
Color.setGlColorOpaque(Color.WHITE.main);
}
}

/**
* @return a widget with this drawable as a background
*/
Expand Down Expand Up @@ -167,8 +152,8 @@ public DrawableWidget(IDrawable drawable) {

@SideOnly(Side.CLIENT)
@Override
public void draw(ModularGuiContext context, WidgetTheme widgetTheme) {
this.drawable.drawAtZero(context, getArea(), widgetTheme);
public void draw(ModularGuiContext context, WidgetThemeEntry<?> widgetTheme) {
this.drawable.drawAtZero(context, getArea(), getActiveWidgetTheme(widgetTheme, isHovering()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,19 @@ default IDrawable getRootDrawable() {
return drawable;
}

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

/**
* This returns an interactable wrapper of this icon. This is only used in
* {@link com.cleanroommc.modularui.drawable.text.RichText RichText}. This allows this icon to be able to listen to clicks and other
* inputs.
*/
default InteractableIcon asInteractable() {
return new InteractableIcon(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ default void draw(GuiContext context, int x, int y, int width, int height, Widge
}

@Override
default boolean canApplyTheme() {
return true;
}

default TextWidget<?> asWidget() {
return new TextWidget<>(this);
}
Expand Down
Loading