diff --git a/src/main/java/com/hfstudio/guidenh/client/RegionWandRenderer.java b/src/main/java/com/hfstudio/guidenh/client/RegionWandRenderer.java index b27c36da..3bb12360 100644 --- a/src/main/java/com/hfstudio/guidenh/client/RegionWandRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/client/RegionWandRenderer.java @@ -13,6 +13,7 @@ import com.gtnewhorizon.gtnhlib.blockpos.IBlockPos; import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.GuidebookText; import com.hfstudio.guidenh.guide.internal.item.RegionWandExporter; import com.hfstudio.guidenh.guide.internal.item.RegionWandExporter.SelectionAction; @@ -176,11 +177,11 @@ private static void drawTargetPreview(int x, int y, int z) { GL11.glLineWidth(3f); GL11.glBegin(GL11.GL_LINES); - GL11.glColor4f(1f, 0.2f, 0.2f, 0.95f); + ColorUtils.applyGlColor(ColorUtils.REGION_X_AXIS.getColor()); line(cx - radius, cy, cz, cx + radius, cy, cz); - GL11.glColor4f(0.25f, 1f, 0.25f, 0.95f); + ColorUtils.applyGlColor(ColorUtils.REGION_Y_AXIS.getColor()); line(cx, cy - radius, cz, cx, cy + radius, cz); - GL11.glColor4f(0.25f, 0.45f, 1f, 0.95f); + ColorUtils.applyGlColor(ColorUtils.REGION_Z_AXIS.getColor()); line(cx, cy, cz - radius, cx, cy, cz + radius); GL11.glEnd(); GL11.glLineWidth(2f); diff --git a/src/main/java/com/hfstudio/guidenh/config/ModConfig.java b/src/main/java/com/hfstudio/guidenh/config/ModConfig.java index 46e936f0..bd301b34 100644 --- a/src/main/java/com/hfstudio/guidenh/config/ModConfig.java +++ b/src/main/java/com/hfstudio/guidenh/config/ModConfig.java @@ -94,15 +94,6 @@ public static class Debug { @DefaultBoolean(true) public boolean showMousePosition = true; - @Comment("Debug text color (ARGB format)") - public int debugTextColor = 0xFFC47BA1; - - @Comment("Debug outline border color (ARGB format, 0 to mirror text color)") - public int debugOutlineColor = 0; - - @Comment("Debug cursor dot color (ARGB format)") - public int debugCursorColor = 0xCC00FF00; - @Comment("Debug text scale factor") @DefaultFloat(0.8f) @RangeFloat(min = 0.5f, max = 2.0f) @@ -188,6 +179,10 @@ public static class Ui { @DefaultBoolean(false) public boolean sceneEditorAutoPickEnabled = false; + @Comment("Whether exporting SNBT from the scene editor also opens the exported structure folder.") + @DefaultBoolean(false) + public boolean sceneEditorExportOpenFolderAfterExport = false; + @Comment("Whether point snapping is enabled in the scene editor by default.") @DefaultBoolean(true) public boolean sceneEditorSnapPointEnabled = true; diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/ARGB.java b/src/main/java/com/hfstudio/guidenh/guide/color/ARGB.java deleted file mode 100644 index ba410f05..00000000 --- a/src/main/java/com/hfstudio/guidenh/guide/color/ARGB.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.hfstudio.guidenh.guide.color; - -public class ARGB { - - private ARGB() {} - - public static int alpha(int argb) { - return (argb >> 24) & 0xFF; - } - - public static int red(int argb) { - return (argb >> 16) & 0xFF; - } - - public static int green(int argb) { - return (argb >> 8) & 0xFF; - } - - public static int blue(int argb) { - return argb & 0xFF; - } - - public static int color(int alpha, int red, int green, int blue) { - return (alpha & 0xFF) << 24 | (red & 0xFF) << 16 | (green & 0xFF) << 8 | (blue & 0xFF); - } - - public static int color(int red, int green, int blue) { - return color(0xFF, red, green, blue); - } - - public static int multiply(int color1, int color2) { - return color( - alpha(color1) * alpha(color2) / 255, - red(color1) * red(color2) / 255, - green(color1) * green(color2) / 255, - blue(color1) * blue(color2) / 255); - } - - public static int opaque(int color) { - return color | 0xFF000000; - } - - public static int white(int alpha) { - return color(alpha, 0xFF, 0xFF, 0xFF); - } - - public static boolean hasTransparency(int color) { - return alpha(color) < 0xFF; - } - - public static int lerp(float t, int from, int to) { - int fromA = alpha(from), fromR = red(from), fromG = green(from), fromB = blue(from); - int toA = alpha(to), toR = red(to), toG = green(to), toB = blue(to); - return color( - (int) (fromA + t * (toA - fromA)), - (int) (fromR + t * (toR - fromR)), - (int) (fromG + t * (toG - fromG)), - (int) (fromB + t * (toB - fromB))); - } -} diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/ColorUtils.java b/src/main/java/com/hfstudio/guidenh/guide/color/ColorUtils.java new file mode 100644 index 00000000..079c683d --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/color/ColorUtils.java @@ -0,0 +1,516 @@ +package com.hfstudio.guidenh.guide.color; + +import java.util.Locale; + +import org.lwjgl.opengl.GL11; + +import com.gtnewhorizon.gtnhlib.color.ColorResource; +import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog; + +/** + * Central registry for colors used by GuideNH. + * + *

+ * Color resources can be overridden by resource packs and are refreshed by GTNHLib when resources reload. Callers + * should resolve a resource with {@link ColorResource#getColor()} at the point where the color is consumed. + *

+ */ +public class ColorUtils { + + private static final ColorResource.Factory COLORS = new ColorResource.Factory("guidenh"); + + public static final ColorResource TRANSPARENT = COLORS.argb("transparent", "0x00000000"); + public static final ColorResource BLACK = COLORS.argb("black", "0xFF000000"); + public static final ColorResource WHITE = COLORS.argb("white", "0xFFFFFFFF"); + public static final ColorResource RGB_WHITE = COLORS.rgb("rgbWhite", "0xFFFFFF"); + public static final ColorResource WHITE_70 = COLORS.argb("white70", "0xB3FFFFFF"); + public static final ColorResource REGION_X_AXIS = COLORS.argb("regionXAxis", "0xF2FF3333"); + public static final ColorResource REGION_Y_AXIS = COLORS.argb("regionYAxis", "0xF240FF40"); + public static final ColorResource REGION_Z_AXIS = COLORS.argb("regionZAxis", "0xF24073FF"); + + public static final ColorResource PANEL = COLORS.argb("panel", "0xB418181C"); + public static final ColorResource PANEL_INNER = COLORS.argb("panelInner", "0x70121216"); + public static final ColorResource PANEL_BORDER = COLORS.argb("panelBorder", "0xFF5A5A5A"); + public static final ColorResource PANEL_HEADER = COLORS.argb("panelHeader", "0xFFDEE6F0"); + public static final ColorResource PANEL_MUTED_TEXT = COLORS.argb("panelMutedText", "0xFFB9C2CE"); + public static final ColorResource PANEL_SUBTLE_TEXT = COLORS.argb("panelSubtleText", "0xFF8F98A3"); + + public static final ColorResource INPUT_BORDER = COLORS.argb("inputBorder", "0xFF3E434A"); + public static final ColorResource INPUT_FOCUSED_BORDER = COLORS.argb("inputFocusedBorder", "0xFF7FC8FF"); + public static final ColorResource INPUT_ERROR_BORDER = COLORS.argb("inputErrorBorder", "0xFFFF6767"); + public static final ColorResource INPUT_BACKGROUND = COLORS.argb("inputBackground", "0x80101012"); + public static final ColorResource CHECKBOX_BACKGROUND = COLORS.argb("checkboxBackground", "0xA0141418"); + public static final ColorResource CHECKBOX_CHECK = COLORS.argb("checkboxCheck", "0xFF00CAF2"); + + public static final ColorResource TAB_ACTIVE = COLORS.argb("tabActive", "0xD6202C36"); + public static final ColorResource TAB_INACTIVE = COLORS.argb("tabInactive", "0x6612181C"); + public static final ColorResource TAB_HOVER = COLORS.argb("tabHover", "0xA61C252E"); + public static final ColorResource ELEMENT_ROW = COLORS.argb("elementRow", "0x6A121418"); + public static final ColorResource ELEMENT_ROW_SELECTED = COLORS.argb("elementRowSelected", "0x9A1C222A"); + public static final ColorResource ELEMENT_ROW_EXPANDED = COLORS.argb("elementRowExpanded", "0x7A101216"); + public static final ColorResource ELEMENT_MENU = COLORS.argb("elementMenu", "0xEE121418"); + public static final ColorResource ELEMENT_MENU_HOVER = COLORS.argb("elementMenuHover", "0xCC1A222A"); + + public static final ColorResource DIALOG_OVERLAY = COLORS.argb("dialogOverlay", "0x8A050608"); + public static final ColorResource DIALOG = COLORS.argb("dialog", "0xF0181C22"); + public static final ColorResource DIALOG_HOVER = COLORS.argb("dialogHover", "0xCC24303A"); + public static final ColorResource TEXT = COLORS.argb("text", "0xFFF0F0F0"); + public static final ColorResource TEXT_MUTED = COLORS.argb("textMuted", "0xFFD0D8E0"); + public static final ColorResource TEXT_DISABLED = COLORS.argb("textDisabled", "0xFF8F98A3"); + public static final ColorResource ACCENT = COLORS.argb("accent", "0xFF00CAF2"); + public static final ColorResource ERROR = COLORS.argb("error", "0xFFFF6767"); + public static final ColorResource DEBUG_TEXT = COLORS.argb("debugText", "0xFFC47BA1"); + public static final ColorResource DEBUG_CURSOR = COLORS.argb("debugCursor", "0xCC00FF00"); + public static final ColorResource DEBUG_OUTLINE = COLORS.argb("debugOutline", "0xFFC47BA1"); + + public static final ConstantColor LINK = new ConstantColor(rgb(0, 213, 255)); + public static final ConstantColor BODY_TEXT = new ConstantColor(rgb(210, 210, 210)); + public static final ConstantColor ERROR_TEXT = new ConstantColor(rgb(255, 0, 0)); + public static final ConstantColor CRAFTING_RECIPE_TYPE = new ConstantColor(rgb(64, 64, 64)); + public static final ConstantColor THEMATIC_BREAK = new ConstantColor(rgb(155, 155, 155)); + public static final ConstantColor HEADER1_SEPARATOR = new ConstantColor(argb(127, 255, 255, 255)); + public static final ConstantColor HEADER2_SEPARATOR = new ConstantColor(argb(127, 210, 210, 210)); + public static final ConstantColor NAVBAR_BG_TOP = new ConstantColor(BLACK.getColor()); + public static final ConstantColor NAVBAR_BG_BOTTOM = new ConstantColor(argb(127, 0, 0, 0)); + public static final ConstantColor NAVBAR_ROW_HOVER = new ConstantColor(rgb(33, 33, 33)); + public static final ConstantColor NAVBAR_EXPAND_ARROW = new ConstantColor(rgb(238, 238, 238)); + public static final ConstantColor TABLE_BORDER = new ConstantColor(rgb(124, 124, 124)); + public static final ConstantColor ICON_BUTTON_NORMAL = new ConstantColor(mono(200)); + public static final ConstantColor ICON_BUTTON_DISABLED = new ConstantColor(mono(64)); + public static final ConstantColor ICON_BUTTON_HOVER = new ConstantColor(rgb(0, 213, 255)); + public static final ConstantColor IN_WORLD_BLOCK_HIGHLIGHT = new ConstantColor(argb(0xCC, 0x99, 0x99, 0x99)); + public static final ConstantColor SYMBOLIC_SCENE_BACKGROUND = new ConstantColor(argb(20, 0, 0, 0)); + public static final ConstantColor GUIDE_SCREEN_BACKGROUND = new ConstantColor(argb(229, 63, 63, 63)); + public static final ConstantColor BLOCKQUOTE_BACKGROUND = new ConstantColor(argb(64, 255, 255, 255)); + + public static final ConstantColor MC_BLACK = new ConstantColor(hexToRgb("#000")); + public static final ConstantColor MC_DARK_BLUE = new ConstantColor(hexToRgb("#00A")); + public static final ConstantColor MC_DARK_GREEN = new ConstantColor(hexToRgb("#0A0")); + public static final ConstantColor MC_DARK_AQUA = new ConstantColor(hexToRgb("#0AA")); + public static final ConstantColor MC_DARK_RED = new ConstantColor(hexToRgb("#A00")); + public static final ConstantColor MC_DARK_PURPLE = new ConstantColor(hexToRgb("#A0A")); + public static final ConstantColor MC_GOLD = new ConstantColor(hexToRgb("#AA0")); + public static final ConstantColor MC_GRAY = new ConstantColor(hexToRgb("#AAA")); + public static final ConstantColor MC_DARK_GRAY = new ConstantColor(hexToRgb("#555")); + public static final ConstantColor MC_BLUE = new ConstantColor(hexToRgb("#55F")); + public static final ConstantColor MC_GREEN = new ConstantColor(hexToRgb("#5F5")); + public static final ConstantColor MC_AQUA = new ConstantColor(hexToRgb("#5FF")); + public static final ConstantColor MC_RED = new ConstantColor(hexToRgb("#F55")); + public static final ConstantColor MC_LIGHT_PURPLE = new ConstantColor(hexToRgb("#F5F")); + public static final ConstantColor MC_YELLOW = new ConstantColor(hexToRgb("#FF5")); + public static final ConstantColor MC_WHITE = new ConstantColor(hexToRgb("#FFF")); + + public static ColorValue symbolic(String id) { + if (id == null) { + return null; + } + return switch (id.toUpperCase(Locale.ROOT)) { + case "LINK" -> LINK; + case "BODY_TEXT" -> BODY_TEXT; + case "ERROR_TEXT" -> ERROR_TEXT; + case "CRAFTING_RECIPE_TYPE" -> CRAFTING_RECIPE_TYPE; + case "THEMATIC_BREAK" -> THEMATIC_BREAK; + case "HEADER1_SEPARATOR" -> HEADER1_SEPARATOR; + case "HEADER2_SEPARATOR" -> HEADER2_SEPARATOR; + case "NAVBAR_BG_TOP" -> NAVBAR_BG_TOP; + case "NAVBAR_BG_BOTTOM" -> NAVBAR_BG_BOTTOM; + case "NAVBAR_ROW_HOVER" -> NAVBAR_ROW_HOVER; + case "NAVBAR_EXPAND_ARROW" -> NAVBAR_EXPAND_ARROW; + case "TABLE_BORDER" -> TABLE_BORDER; + case "ICON_BUTTON_NORMAL" -> ICON_BUTTON_NORMAL; + case "ICON_BUTTON_DISABLED" -> ICON_BUTTON_DISABLED; + case "ICON_BUTTON_HOVER" -> ICON_BUTTON_HOVER; + case "IN_WORLD_BLOCK_HIGHLIGHT" -> IN_WORLD_BLOCK_HIGHLIGHT; + case "SCENE_BACKGROUND" -> SYMBOLIC_SCENE_BACKGROUND; + case "GUIDE_SCREEN_BACKGROUND" -> GUIDE_SCREEN_BACKGROUND; + case "BLOCKQUOTE_BACKGROUND" -> BLOCKQUOTE_BACKGROUND; + case "BLACK" -> MC_BLACK; + case "DARK_BLUE" -> MC_DARK_BLUE; + case "DARK_GREEN" -> MC_DARK_GREEN; + case "DARK_AQUA" -> MC_DARK_AQUA; + case "DARK_RED" -> MC_DARK_RED; + case "DARK_PURPLE" -> MC_DARK_PURPLE; + case "GOLD" -> MC_GOLD; + case "GRAY" -> MC_GRAY; + case "DARK_GRAY" -> MC_DARK_GRAY; + case "BLUE" -> MC_BLUE; + case "GREEN" -> MC_GREEN; + case "AQUA" -> MC_AQUA; + case "RED" -> MC_RED; + case "LIGHT_PURPLE" -> MC_LIGHT_PURPLE; + case "YELLOW" -> MC_YELLOW; + case "WHITE" -> MC_WHITE; + default -> null; + }; + } + + public static final ColorResource SCENE_BACKGROUND = COLORS.argb("sceneBackground", "0xFF0A0A10"); + public static final ColorResource SCENE_BORDER = COLORS.argb("sceneBorder", "0xFF303040"); + public static final ColorResource X_AXIS = COLORS.argb("xAxis", "0xFFFF5A5A"); + public static final ColorResource Y_AXIS = COLORS.argb("yAxis", "0xFF67E26C"); + public static final ColorResource Z_AXIS = COLORS.argb("zAxis", "0xFF64A8FF"); + public static final ColorResource XY_PLANE = COLORS.argb("xyPlane", "0xD8FFD45A"); + public static final ColorResource YZ_PLANE = COLORS.argb("yzPlane", "0xD85AE9FF"); + public static final ColorResource ZX_PLANE = COLORS.argb("zxPlane", "0xD8F16BFF"); + public static final ColorResource HIGHLIGHT = COLORS.argb("highlight", "0x8000FFAA"); + + public static final ColorResource CHART_BACKGROUND = COLORS.argb("chartBackground", "0xFF1B1F23"); + public static final ColorResource CHART_BORDER = COLORS.argb("chartBorder", "0xFF3A4047"); + public static final ColorResource CHART_AXIS = COLORS.argb("chartAxis", "0xFFB8C2CF"); + public static final ColorResource CHART_GRID = COLORS.argb("chartGrid", "0x33B8C2CF"); + public static final ColorResource CHART_TITLE = COLORS.argb("chartTitle", "0xFFE0E0E0"); + public static final ColorResource CHART_LABEL = COLORS.argb("chartLabel", "0xFFB8C2CF"); + + public static final ColorResource SCROLLBAR_TRACK = COLORS.argb("scrollbarTrack", "0x35101010"); + public static final ColorResource SCROLLBAR_THUMB = COLORS.argb("scrollbarThumb", "0xA0D8D8D8"); + public static final ColorResource SCROLLBAR_HOVER = COLORS.argb("scrollbarHover", "0x889AA3B2"); + + public static final ColorResource[] CHART_PALETTE = { COLORS.argb("chartPalette01", "0xFFE15759"), + COLORS.argb("chartPalette02", "0xFF4E79A7"), COLORS.argb("chartPalette03", "0xFF59A14F"), + COLORS.argb("chartPalette04", "0xFFF28E2B"), COLORS.argb("chartPalette05", "0xFF76B7B2"), + COLORS.argb("chartPalette06", "0xFFEDC948"), COLORS.argb("chartPalette07", "0xFFB07AA1"), + COLORS.argb("chartPalette08", "0xFFFF9DA7"), COLORS.argb("chartPalette09", "0xFF9C755F"), + COLORS.argb("chartPalette10", "0xFFBAB0AC"), COLORS.argb("chartPalette11", "0xFF1F77B4"), + COLORS.argb("chartPalette12", "0xFFFF7F0E"), COLORS.argb("chartPalette13", "0xFF2CA02C"), + COLORS.argb("chartPalette14", "0xFFD62728"), COLORS.argb("chartPalette15", "0xFF9467BD"), + COLORS.argb("chartPalette16", "0xFF8C564B") }; + + public static final ColorResource[] FUNCTION_GRAPH_PALETTE = { COLORS.argb("functionGraphPalette01", "0xFFE15759"), + COLORS.argb("functionGraphPalette02", "0xFF4E79A7"), COLORS.argb("functionGraphPalette03", "0xFF59A14F"), + COLORS.argb("functionGraphPalette04", "0xFFF28E2B"), COLORS.argb("functionGraphPalette05", "0xFF76B7B2"), + COLORS.argb("functionGraphPalette06", "0xFFB07AA1"), COLORS.argb("functionGraphPalette07", "0xFFEDC948"), + COLORS.argb("functionGraphPalette08", "0xFF9C755F"), COLORS.argb("functionGraphPalette09", "0xFFFF9DA7"), + COLORS.argb("functionGraphPalette10", "0xFF1F77B4"), COLORS.argb("functionGraphPalette11", "0xFFFF7F0E"), + COLORS.argb("functionGraphPalette12", "0xFF2CA02C"), COLORS.argb("functionGraphPalette13", "0xFFD62728"), + COLORS.argb("functionGraphPalette14", "0xFF9467BD") }; + + public static final ColorResource ARGB_0E0E20 = COLORS.rgb("color0E0E20", "0x0E0E20"); + public static final ColorResource ARGB_10000000 = COLORS.argb("color10000000", "0x10000000"); + public static final ColorResource ARGB_121216 = COLORS.rgb("color121216", "0x121216"); + public static final ColorResource ARGB_1A0C1117 = COLORS.argb("color1A0C1117", "0x1A0C1117"); + public static final ColorResource ARGB_1A6FB6FF = COLORS.argb("color1A6FB6FF", "0x1A6FB6FF"); + public static final ColorResource ARGB_1AF0F6FF = COLORS.argb("color1AF0F6FF", "0x1AF0F6FF"); + public static final ColorResource ARGB_20FFFFFF = COLORS.argb("color20FFFFFF", "0x20FFFFFF"); + public static final ColorResource ARGB_22262D38 = COLORS.argb("color22262D38", "0x22262D38"); + public static final ColorResource ARGB_22FFFFFF = COLORS.argb("color22FFFFFF", "0x22FFFFFF"); + public static final ColorResource ARGB_262A3340 = COLORS.argb("color262A3340", "0x262A3340"); + public static final ColorResource MERMAID_SUBGRAPH_BACKGROUND_DARK = COLORS + .argb("mermaidSubgraphBackgroundDark", "0x301E2A2A"); + public static final ColorResource MERMAID_SUBGRAPH_BACKGROUND_PURPLE = COLORS + .argb("mermaidSubgraphBackgroundPurple", "0x301E2A45"); + public static final ColorResource ARGB_30242B33 = COLORS.argb("color30242B33", "0x30242B33"); + public static final ColorResource MERMAID_SUBGRAPH_BACKGROUND_VIOLET = COLORS + .argb("mermaidSubgraphBackgroundViolet", "0x302A1E45"); + public static final ColorResource MERMAID_SUBGRAPH_BACKGROUND_GOLD = COLORS + .argb("mermaidSubgraphBackgroundGold", "0x302A2A1E"); + public static final ColorResource ARGB_33101012 = COLORS.argb("color33101012", "0x33101012"); + public static final ColorResource ARGB_33262D38 = COLORS.argb("color33262D38", "0x33262D38"); + public static final ColorResource ARGB_33FFFFFF = COLORS.argb("color33FFFFFF", "0x33FFFFFF"); + public static final ColorResource ARGB_34101018 = COLORS.argb("color34101018", "0x34101018"); + public static final ColorResource ARGB_40000000 = COLORS.argb("color40000000", "0x40000000"); + public static final ColorResource ARGB_40FFFFFF = COLORS.argb("color40FFFFFF", "0x40FFFFFF"); + public static final ColorResource ARGB_4438BDF8 = COLORS.argb("color4438BDF8", "0x4438BDF8"); + public static final ColorResource ARGB_44FFFFFF = COLORS.argb("color44FFFFFF", "0x44FFFFFF"); + public static final ColorResource ARGB_4CFFFFFF = COLORS.argb("color4CFFFFFF", "0x4CFFFFFF"); + public static final ColorResource ARGB_4D000000 = COLORS.argb("color4D000000", "0x4D000000"); + public static final ColorResource ARGB_4D6E7681 = COLORS.argb("color4D6E7681", "0x4D6E7681"); + public static final ColorResource ARGB_5028007F = COLORS.argb("color5028007F", "0x5028007F"); + public static final ColorResource ARGB_505000FF = COLORS.argb("color505000FF", "0x505000FF"); + public static final ColorResource ARGB_5512181C = COLORS.argb("color5512181C", "0x5512181C"); + public static final ColorResource ARGB_5522262C = COLORS.argb("color5522262C", "0x5522262C"); + public static final ColorResource ARGB_55FFFFFF = COLORS.argb("color55FFFFFF", "0x55FFFFFF"); + public static final ColorResource ARGB_60FFFFFF = COLORS.argb("color60FFFFFF", "0x60FFFFFF"); + public static final ColorResource ARGB_6600F5FF = COLORS.argb("color6600F5FF", "0x6600F5FF"); + public static final ColorResource ARGB_661E232B = COLORS.argb("color661E232B", "0x661E232B"); + public static final ColorResource ARGB_6622262C = COLORS.argb("color6622262C", "0x6622262C"); + public static final ColorResource ARGB_663D89C9 = COLORS.argb("color663D89C9", "0x663D89C9"); + public static final ColorResource ARGB_66434C57 = COLORS.argb("color66434C57", "0x66434C57"); + public static final ColorResource ARGB_66464A50 = COLORS.argb("color66464A50", "0x66464A50"); + public static final ColorResource ARGB_6656C8FF = COLORS.argb("color6656C8FF", "0x6656C8FF"); + public static final ColorResource ARGB_66586275 = COLORS.argb("color66586275", "0x66586275"); + public static final ColorResource ARGB_665A5A5A = COLORS.argb("color665A5A5A", "0x665A5A5A"); + public static final ColorResource ARGB_66AA2222 = COLORS.argb("color66AA2222", "0x66AA2222"); + public static final ColorResource ARGB_66FFFFFF = COLORS.argb("color66FFFFFF", "0x66FFFFFF"); + public static final ColorResource ARGB_70000000 = COLORS.argb("color70000000", "0x70000000"); + public static final ColorResource ARGB_7A1C252E = COLORS.argb("color7A1C252E", "0x7A1C252E"); + public static final ColorResource ARGB_80000000 = COLORS.argb("color80000000", "0x80000000"); + public static final ColorResource ARGB_802A2A2A = COLORS.argb("color802A2A2A", "0x802A2A2A"); + public static final ColorResource ARGB_80768496 = COLORS.argb("color80768496", "0x80768496"); + public static final ColorResource ARGB_80AAAADD = COLORS.argb("color80AAAADD", "0x80AAAADD"); + public static final ColorResource ARGB_80FFFFFF = COLORS.argb("color80FFFFFF", "0x80FFFFFF"); + public static final ColorResource ARGB_88000000 = COLORS.argb("color88000000", "0x88000000"); + public static final ColorResource ARGB_88303946 = COLORS.argb("color88303946", "0x88303946"); + public static final ColorResource ARGB_88FFFFFF = COLORS.argb("color88FFFFFF", "0x88FFFFFF"); + public static final ColorResource ARGB_8A00CAF2 = COLORS.argb("color8A00CAF2", "0x8A00CAF2"); + public static final ColorResource ARGB_94D049BB = COLORS.argb("color94D049BB", "0x94D049BB"); + public static final ColorResource ARGB_96D9B44A = COLORS.argb("color96D9B44A", "0x96D9B44A"); + public static final ColorResource MERMAID_SUBGRAPH_BORDER_BLUE = COLORS + .argb("mermaidSubgraphBorderBlue", "0x99434C57"); + public static final ColorResource MERMAID_SUBGRAPH_BORDER_TEAL = COLORS + .argb("mermaidSubgraphBorderTeal", "0x9943574C"); + public static final ColorResource MERMAID_SUBGRAPH_BORDER_GREEN = COLORS + .argb("mermaidSubgraphBorderGreen", "0x994C5743"); + public static final ColorResource MERMAID_SUBGRAPH_BORDER_OLIVE = COLORS + .argb("mermaidSubgraphBorderOlive", "0x99575743"); + public static final ColorResource ARGB_99B8C0CC = COLORS.argb("color99B8C0CC", "0x99B8C0CC"); + public static final ColorResource ARGB_9E3779B9 = COLORS.argb("color9E3779B9", "0x9E3779B9"); + public static final ColorResource ARGB_A0121216 = COLORS.argb("colorA0121216", "0xA0121216"); + public static final ColorResource ARGB_A014161A = COLORS.argb("colorA014161A", "0xA014161A"); + public static final ColorResource ARGB_A0AAB5C2 = COLORS.argb("colorA0AAB5C2", "0xA0AAB5C2"); + public static final ColorResource ARGB_A6181A20 = COLORS.argb("colorA6181A20", "0xA6181A20"); + public static final ColorResource ARGB_AA111922 = COLORS.argb("colorAA111922", "0xAA111922"); + public static final ColorResource ARGB_AA1CB4E9 = COLORS.argb("colorAA1CB4E9", "0xAA1CB4E9"); + public static final ColorResource ARGB_AAFFC107 = COLORS.argb("colorAAFFC107", "0xAAFFC107"); + public static final ColorResource ARGB_BF58476D = COLORS.argb("colorBF58476D", "0xBF58476D"); + public static final ColorResource ARGB_C0AAAADD = COLORS.argb("colorC0AAAADD", "0xC0AAAADD"); + public static final ColorResource ARGB_C0FFFFFF = COLORS.argb("colorC0FFFFFF", "0xC0FFFFFF"); + public static final ColorResource ARGB_C824303A = COLORS.argb("colorC824303A", "0xC824303A"); + public static final ColorResource ARGB_CBF29CE4 = COLORS.argb("colorCBF29CE4", "0xCBF29CE4"); + public static final ColorResource ARGB_CC00FF00 = COLORS.argb("colorCC00FF00", "0xCC00FF00"); + public static final ColorResource ARGB_CC0C1117 = COLORS.argb("colorCC0C1117", "0xCC0C1117"); + public static final ColorResource ARGB_CC0E0E20 = COLORS.argb("colorCC0E0E20", "0xCC0E0E20"); + public static final ColorResource ARGB_CC0F0F12 = COLORS.argb("colorCC0F0F12", "0xCC0F0F12"); + public static final ColorResource ARGB_CC2A3A46 = COLORS.argb("colorCC2A3A46", "0xCC2A3A46"); + public static final ColorResource ARGB_CC768496 = COLORS.argb("colorCC768496", "0xCC768496"); + public static final ColorResource ARGB_CCEAF6FF = COLORS.argb("colorCCEAF6FF", "0xCCEAF6FF"); + public static final ColorResource ARGB_D0000000 = COLORS.argb("colorD0000000", "0xD0000000"); + public static final ColorResource ARGB_D0202020 = COLORS.argb("colorD0202020", "0xD0202020"); + public static final ColorResource ARGB_D8FFFFFF = COLORS.argb("colorD8FFFFFF", "0xD8FFFFFF"); + public static final ColorResource ARGB_E0101010 = COLORS.argb("colorE0101010", "0xE0101010"); + public static final ColorResource ARGB_E0151515 = COLORS.argb("colorE0151515", "0xE0151515"); + public static final ColorResource ARGB_F00C1117 = COLORS.argb("colorF00C1117", "0xF00C1117"); + public static final ColorResource ARGB_F0100010 = COLORS.argb("colorF0100010", "0xF0100010"); + public static final ColorResource ARGB_F0181818 = COLORS.argb("colorF0181818", "0xF0181818"); + public static final ColorResource ARGB_F0F0F0 = COLORS.rgb("colorF0F0F0", "0xF0F0F0"); + public static final ColorResource ARGB_F8FFFFFF = COLORS.argb("colorF8FFFFFF", "0xF8FFFFFF"); + public static final ColorResource ARGB_FF00008B = COLORS.argb("colorFF00008B", "0xFF00008B"); + public static final ColorResource ARGB_FF0000FF = COLORS.argb("colorFF0000FF", "0xFF0000FF"); + public static final ColorResource ARGB_FF006400 = COLORS.argb("colorFF006400", "0xFF006400"); + public static final ColorResource ARGB_FF008B8B = COLORS.argb("colorFF008B8B", "0xFF008B8B"); + public static final ColorResource ARGB_FF00D2FC = COLORS.argb("colorFF00D2FC", "0xFF00D2FC"); + public static final ColorResource ARGB_FF00E000 = COLORS.argb("colorFF00E000", "0xFF00E000"); + public static final ColorResource ARGB_FF00FF00 = COLORS.argb("colorFF00FF00", "0xFF00FF00"); + public static final ColorResource ARGB_FF00FFFF = COLORS.argb("colorFF00FFFF", "0xFF00FFFF"); + public static final ColorResource ARGB_FF0D1117 = COLORS.argb("colorFF0D1117", "0xFF0D1117"); + public static final ColorResource ARGB_FF111922 = COLORS.argb("colorFF111922", "0xFF111922"); + public static final ColorResource ARGB_FF121216 = COLORS.argb("colorFF121216", "0xFF121216"); + public static final ColorResource ARGB_FF161B22 = COLORS.argb("colorFF161B22", "0xFF161B22"); + public static final ColorResource ARGB_FF1E1E1E = COLORS.argb("colorFF1E1E1E", "0xFF1E1E1E"); + public static final ColorResource ARGB_FF1F2A38 = COLORS.argb("colorFF1F2A38", "0xFF1F2A38"); + public static final ColorResource ARGB_FF202020 = COLORS.argb("colorFF202020", "0xFF202020"); + public static final ColorResource ARGB_FF262A33 = COLORS.argb("colorFF262A33", "0xFF262A33"); + public static final ColorResource ARGB_FF2A2A2A = COLORS.argb("colorFF2A2A2A", "0xFF2A2A2A"); + public static final ColorResource ARGB_FF2D3137 = COLORS.argb("colorFF2D3137", "0xFF2D3137"); + public static final ColorResource ARGB_FF30363D = COLORS.argb("colorFF30363D", "0xFF30363D"); + public static final ColorResource ARGB_FF333333 = COLORS.argb("colorFF333333", "0xFF333333"); + public static final ColorResource ARGB_FF33404C = COLORS.argb("colorFF33404C", "0xFF33404C"); + public static final ColorResource ARGB_FF373737 = COLORS.argb("colorFF373737", "0xFF373737"); + public static final ColorResource ARGB_FF3A3A3A = COLORS.argb("colorFF3A3A3A", "0xFF3A3A3A"); + public static final ColorResource ARGB_FF464A50 = COLORS.argb("colorFF464A50", "0xFF464A50"); + public static final ColorResource ARGB_FF46505A = COLORS.argb("colorFF46505A", "0xFF46505A"); + public static final ColorResource ARGB_FF4A4A4A = COLORS.argb("colorFF4A4A4A", "0xFF4A4A4A"); + public static final ColorResource ARGB_FF4D5661 = COLORS.argb("colorFF4D5661", "0xFF4D5661"); + public static final ColorResource ARGB_FF4FA3FF = COLORS.argb("colorFF4FA3FF", "0xFF4FA3FF"); + public static final ColorResource ARGB_FF53565C = COLORS.argb("colorFF53565C", "0xFF53565C"); + public static final ColorResource ARGB_FF555555 = COLORS.argb("colorFF555555", "0xFF555555"); + public static final ColorResource ARGB_FF586170 = COLORS.argb("colorFF586170", "0xFF586170"); + public static final ColorResource ARGB_FF5D6C7C = COLORS.argb("colorFF5D6C7C", "0xFF5D6C7C"); + public static final ColorResource ARGB_FF5EA8FF = COLORS.argb("colorFF5EA8FF", "0xFF5EA8FF"); + public static final ColorResource ARGB_FF61B75D = COLORS.argb("colorFF61B75D", "0xFF61B75D"); + public static final ColorResource ARGB_FF638EF1 = COLORS.argb("colorFF638EF1", "0xFF638EF1"); + public static final ColorResource ARGB_FF666666 = COLORS.argb("colorFF666666", "0xFF666666"); + public static final ColorResource ARGB_FF737A82 = COLORS.argb("colorFF737A82", "0xFF737A82"); + public static final ColorResource ARGB_FF73DACA = COLORS.argb("colorFF73DACA", "0xFF73DACA"); + public static final ColorResource ARGB_FF79C0FF = COLORS.argb("colorFF79C0FF", "0xFF79C0FF"); + public static final ColorResource ARGB_FF7A7A7A = COLORS.argb("colorFF7A7A7A", "0xFF7A7A7A"); + public static final ColorResource ARGB_FF7AA2F7 = COLORS.argb("colorFF7AA2F7", "0xFF7AA2F7"); + public static final ColorResource ARGB_FF7C8795 = COLORS.argb("colorFF7C8795", "0xFF7C8795"); + public static final ColorResource ARGB_FF7DCFFF = COLORS.argb("colorFF7DCFFF", "0xFF7DCFFF"); + public static final ColorResource ARGB_FF7EE787 = COLORS.argb("colorFF7EE787", "0xFF7EE787"); + public static final ColorResource ARGB_FF800080 = COLORS.argb("colorFF800080", "0xFF800080"); + public static final ColorResource ARGB_FF808080 = COLORS.argb("colorFF808080", "0xFF808080"); + public static final ColorResource ARGB_FF8755DD = COLORS.argb("colorFF8755DD", "0xFF8755DD"); + public static final ColorResource ARGB_FF888888 = COLORS.argb("colorFF888888", "0xFF888888"); + public static final ColorResource ARGB_FF88BBFF = COLORS.argb("colorFF88BBFF", "0xFF88BBFF"); + public static final ColorResource ARGB_FF8A6A00 = COLORS.argb("colorFF8A6A00", "0xFF8A6A00"); + public static final ColorResource ARGB_FF8B0000 = COLORS.argb("colorFF8B0000", "0xFF8B0000"); + public static final ColorResource ARGB_FF8B8B8B = COLORS.argb("colorFF8B8B8B", "0xFF8B8B8B"); + public static final ColorResource ARGB_FF8B949E = COLORS.argb("colorFF8B949E", "0xFF8B949E"); + public static final ColorResource ARGB_FF8FC7FF = COLORS.argb("colorFF8FC7FF", "0xFF8FC7FF"); + public static final ColorResource ARGB_FF9AA3B2 = COLORS.argb("colorFF9AA3B2", "0xFF9AA3B2"); + public static final ColorResource ARGB_FF9ECE6A = COLORS.argb("colorFF9ECE6A", "0xFF9ECE6A"); + public static final ColorResource ARGB_FF9FC6FF = COLORS.argb("colorFF9FC6FF", "0xFF9FC6FF"); + public static final ColorResource ARGB_FF9FFFB0 = COLORS.argb("colorFF9FFFB0", "0xFF9FFFB0"); + public static final ColorResource ARGB_FFA0A0A0 = COLORS.argb("colorFFA0A0A0", "0xFFA0A0A0"); + public static final ColorResource ARGB_FFA5D6FF = COLORS.argb("colorFFA5D6FF", "0xFFA5D6FF"); + public static final ColorResource ARGB_FFAAAAAA = COLORS.argb("colorFFAAAAAA", "0xFFAAAAAA"); + public static final ColorResource ARGB_FFB8C0CC = COLORS.argb("colorFFB8C0CC", "0xFFB8C0CC"); + public static final ColorResource ARGB_FFBBBBBB = COLORS.argb("colorFFBBBBBB", "0xFFBBBBBB"); + public static final ColorResource ARGB_FFC0C0FF = COLORS.argb("colorFFC0C0FF", "0xFFC0C0FF"); + public static final ColorResource ARGB_FFC47BA1 = COLORS.argb("colorFFC47BA1", "0xFFC47BA1"); + public static final ColorResource ARGB_FFC79D3E = COLORS.argb("colorFFC79D3E", "0xFFC79D3E"); + public static final ColorResource ARGB_FFCCCCCC = COLORS.argb("colorFFCCCCCC", "0xFFCCCCCC"); + public static final ColorResource ARGB_FFCDD6E1 = COLORS.argb("colorFFCDD6E1", "0xFFCDD6E1"); + public static final ColorResource ARGB_FFD2A8FF = COLORS.argb("colorFFD2A8FF", "0xFFD2A8FF"); + public static final ColorResource ARGB_FFD5DCE7 = COLORS.argb("colorFFD5DCE7", "0xFFD5DCE7"); + public static final ColorResource ARGB_FFD7DEE7 = COLORS.argb("colorFFD7DEE7", "0xFFD7DEE7"); + public static final ColorResource ARGB_FFD8E9FF = COLORS.argb("colorFFD8E9FF", "0xFFD8E9FF"); + public static final ColorResource ARGB_FFE0AF68 = COLORS.argb("colorFFE0AF68", "0xFFE0AF68"); + public static final ColorResource ARGB_FFE2E6ED = COLORS.argb("colorFFE2E6ED", "0xFFE2E6ED"); + public static final ColorResource ARGB_FFE46150 = COLORS.argb("colorFFE46150", "0xFFE46150"); + public static final ColorResource ARGB_FFE5E9F0 = COLORS.argb("colorFFE5E9F0", "0xFFE5E9F0"); + public static final ColorResource ARGB_FFE6E6E6 = COLORS.argb("colorFFE6E6E6", "0xFFE6E6E6"); + public static final ColorResource ARGB_FFE6EDF3 = COLORS.argb("colorFFE6EDF3", "0xFFE6EDF3"); + public static final ColorResource ARGB_FFE8A317 = COLORS.argb("colorFFE8A317", "0xFFE8A317"); + public static final ColorResource ARGB_FFE8E8E8 = COLORS.argb("colorFFE8E8E8", "0xFFE8E8E8"); + public static final ColorResource ARGB_FFE8EDF5 = COLORS.argb("colorFFE8EDF5", "0xFFE8EDF5"); + public static final ColorResource ARGB_FFEAF6FF = COLORS.argb("colorFFEAF6FF", "0xFFEAF6FF"); + public static final ColorResource ARGB_FFEEEEEE = COLORS.argb("colorFFEEEEEE", "0xFFEEEEEE"); + public static final ColorResource ARGB_FFF1F6FB = COLORS.argb("colorFFF1F6FB", "0xFFF1F6FB"); + public static final ColorResource ARGB_FFF4F7FB = COLORS.argb("colorFFF4F7FB", "0xFFF4F7FB"); + public static final ColorResource ARGB_FFF4FBFF = COLORS.argb("colorFFF4FBFF", "0xFFF4FBFF"); + public static final ColorResource ARGB_FFF7768E = COLORS.argb("colorFFF7768E", "0xFFF7768E"); + public static final ColorResource ARGB_FFFF0000 = COLORS.argb("colorFFFF0000", "0xFFFF0000"); + public static final ColorResource ARGB_FFFF00FF = COLORS.argb("colorFFFF00FF", "0xFFFF00FF"); + public static final ColorResource ARGB_FFFF5555 = COLORS.argb("colorFFFF5555", "0xFFFF5555"); + public static final ColorResource ARGB_FFFF7777 = COLORS.argb("colorFFFF7777", "0xFFFF7777"); + public static final ColorResource ARGB_FFFF7B72 = COLORS.argb("colorFFFF7B72", "0xFFFF7B72"); + public static final ColorResource ARGB_FFFF8484 = COLORS.argb("colorFFFF8484", "0xFFFF8484"); + public static final ColorResource ARGB_FFFF9999 = COLORS.argb("colorFFFF9999", "0xFFFF9999"); + public static final ColorResource ARGB_FFFFA500 = COLORS.argb("colorFFFFA500", "0xFFFFA500"); + public static final ColorResource ARGB_FFFFA657 = COLORS.argb("colorFFFFA657", "0xFFFFA657"); + public static final ColorResource ARGB_FFFFC07A = COLORS.argb("colorFFFFC07A", "0xFFFFC07A"); + public static final ColorResource ARGB_FFFFCC55 = COLORS.argb("colorFFFFCC55", "0xFFFFCC55"); + public static final ColorResource ARGB_FFFFD254 = COLORS.argb("colorFFFFD254", "0xFFFFD254"); + public static final ColorResource ARGB_FFFFE16A = COLORS.argb("colorFFFFE16A", "0xFFFFE16A"); + public static final ColorResource ARGB_FFFFF1A8 = COLORS.argb("colorFFFFF1A8", "0xFFFFF1A8"); + public static final ColorResource ARGB_FFFFFF00 = COLORS.argb("colorFFFFFF00", "0xFFFFFF00"); + + public static int getColor(ColorResource resource) { + return resource.getColor(); + } + + public static void applyGlColor(int argb) { + GL11.glColor4f(red(argb) / 255.0F, green(argb) / 255.0F, blue(argb) / 255.0F, alpha(argb) / 255.0F); + } + + public static void applyGlColor(float red, float green, float blue, float alpha) { + GL11.glColor4f(red, green, blue, alpha); + } + + public static void applyWhite(float alpha) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, alpha); + } + + public static ConstantColor constant(ColorResource resource) { + return new ConstantColor(resource.getColor()); + } + + public static int alpha(int argb) { + return (argb >>> 24) & 0xFF; + } + + public static int red(int argb) { + return (argb >>> 16) & 0xFF; + } + + public static int green(int argb) { + return (argb >>> 8) & 0xFF; + } + + public static int blue(int argb) { + return argb & 0xFF; + } + + public static int withAlpha(int argb, int alpha) { + return (argb & 0x00FFFFFF) | ((alpha & 0xFF) << 24); + } + + public static int argb(int alpha, int red, int green, int blue) { + return ((alpha & 0xFF) << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF); + } + + public static int rgb(int red, int green, int blue) { + return argb(0xFF, red, green, blue); + } + + public static int mono(int w) { + return rgb(w, w, w); + } + + public static int lerp(float factor, int from, int to) { + return argb( + (int) (alpha(from) + factor * (alpha(to) - alpha(from))), + (int) (red(from) + factor * (red(to) - red(from))), + (int) (green(from) + factor * (green(to) - green(from))), + (int) (blue(from) + factor * (blue(to) - blue(from)))); + } + + /** + * Converts a hexadecimal color string to a packed RGB or ARGB integer. If no alpha is given, assumes alpha 255. The + * order of colors in the hex string follows CSS notations (#RRGGBBAA or #RGBA). + * + * @param hexColor The color string in hex format (with or without #) + * @return The packed RGB value as an integer + * @throws IllegalArgumentException if the input format is invalid + */ + public static int hexToRgb(String hexColor) { + if (!hexColor.isEmpty()) { + int start = 0; + if (hexColor.charAt(0) == '#') { + start++; // Skip leading # + } + + int remainingChars = hexColor.length() - start; + // #rgb + if (remainingChars == 3 || remainingChars == 4) { + int r = fromHexChar(hexColor.charAt(start)); + int g = fromHexChar(hexColor.charAt(start + 1)); + int b = fromHexChar(hexColor.charAt(start + 2)); + int a = 15; + if (remainingChars == 4) { + a = fromHexChar(hexColor.charAt(start + 3)); + } + if (r != -1 && g != -1 && b != -1 && a != -1) { + return argb(a << 4 | a, r << 4 | r, g << 4 | g, b << 4 | b); + } + } else if (remainingChars == 6 || remainingChars == 8) { + int rHi = fromHexChar(hexColor.charAt(start)); + int rLo = fromHexChar(hexColor.charAt(start + 1)); + int gHi = fromHexChar(hexColor.charAt(start + 2)); + int gLo = fromHexChar(hexColor.charAt(start + 3)); + int bHi = fromHexChar(hexColor.charAt(start + 4)); + int bLo = fromHexChar(hexColor.charAt(start + 5)); + int aHi = 15, aLo = 15; + if (remainingChars == 8) { + aHi = fromHexChar(hexColor.charAt(start + 6)); + aLo = fromHexChar(hexColor.charAt(start + 7)); + } + if (rHi != -1 && rLo != -1 + && gHi != -1 + && gLo != -1 + && bHi != -1 + && bLo != -1 + && aHi != -1 + && aLo != -1) { + return argb(aHi << 4 | aLo, rHi << 4 | rLo, gHi << 4 | gLo, bHi << 4 | bLo); + } + } + } + + GuideDebugLog.error("[GuideNH] [Colors] Tried to parse an invalid hexadecimal color string: '{}'", hexColor); + return 0; + } + + public static int fromHexChar(int ch) { + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'a' && ch <= 'f') { + return 0xa + (ch - 'a'); + } else if (ch >= 'A' && ch <= 'F') { + return 0xa + (ch - 'A'); + } else { + return -1; + } + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/ColorValue.java b/src/main/java/com/hfstudio/guidenh/guide/color/ColorValue.java index 1c981474..1f4be98d 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/color/ColorValue.java +++ b/src/main/java/com/hfstudio/guidenh/guide/color/ColorValue.java @@ -5,5 +5,5 @@ public interface ColorValue { /** * Resolve as ARGB 32-bit. */ - int resolve(LightDarkMode lightDarkMode); + int resolve(); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/Colors.java b/src/main/java/com/hfstudio/guidenh/guide/color/Colors.java deleted file mode 100644 index eac6605f..00000000 --- a/src/main/java/com/hfstudio/guidenh/guide/color/Colors.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.hfstudio.guidenh.guide.color; - -import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog; - -public class Colors { - - /** - * Converts a hexadecimal color string to a packed RGB or ARGB integer. If no alpha is given, assumes alpha 255. The - * order of colors in the hex string follows CSS notations (#RRGGBBAA or #RGBA). - * - * @param hexColor The color string in hex format (with or without #) - * @return The packed RGB value as an integer - * @throws IllegalArgumentException if the input format is invalid - */ - public static int hexToRgb(String hexColor) { - if (!hexColor.isEmpty()) { - int start = 0; - if (hexColor.charAt(0) == '#') { - start++; // Skip leading # - } - - int remainingChars = hexColor.length() - start; - // #rgb - if (remainingChars == 3 || remainingChars == 4) { - int r = fromHexChar(hexColor.charAt(start)); - int g = fromHexChar(hexColor.charAt(start + 1)); - int b = fromHexChar(hexColor.charAt(start + 2)); - int a = 15; - if (remainingChars == 4) { - a = fromHexChar(hexColor.charAt(start + 3)); - } - if (r != -1 && g != -1 && b != -1 && a != -1) { - return argb(a << 4 | a, r << 4 | r, g << 4 | g, b << 4 | b); - } - } else if (remainingChars == 6 || remainingChars == 8) { - int rHi = fromHexChar(hexColor.charAt(start)); - int rLo = fromHexChar(hexColor.charAt(start + 1)); - int gHi = fromHexChar(hexColor.charAt(start + 2)); - int gLo = fromHexChar(hexColor.charAt(start + 3)); - int bHi = fromHexChar(hexColor.charAt(start + 4)); - int bLo = fromHexChar(hexColor.charAt(start + 5)); - int aHi = 15, aLo = 15; - if (remainingChars == 8) { - aHi = fromHexChar(hexColor.charAt(start + 6)); - aLo = fromHexChar(hexColor.charAt(start + 7)); - } - if (rHi != -1 && rLo != -1 - && gHi != -1 - && gLo != -1 - && bHi != -1 - && bLo != -1 - && aHi != -1 - && aLo != -1) { - return argb(aHi << 4 | aLo, rHi << 4 | rLo, gHi << 4 | gLo, bHi << 4 | bLo); - } - } - } - - GuideDebugLog.error("[GuideNH] [Colors] Tried to parse an invalid hexadecimal color string: '{}'", hexColor); - return 0; - } - - public static int fromHexChar(int ch) { - if (ch >= '0' && ch <= '9') { - return ch - '0'; - } else if (ch >= 'a' && ch <= 'f') { - return 0xa + (ch - 'a'); - } else if (ch >= 'A' && ch <= 'F') { - return 0xa + (ch - 'A'); - } else { - return -1; - } - } - - public static int argb(int a, int r, int g, int b) { - return ARGB.color(a, r, g, b); - } - - public static int rgb(int r, int g, int b) { - return argb(255, r, g, b); - } - - public static int mono(int w) { - return rgb(w, w, w); - } -} diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/ConstantColor.java b/src/main/java/com/hfstudio/guidenh/guide/color/ConstantColor.java index 0466520b..d7f51dea 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/color/ConstantColor.java +++ b/src/main/java/com/hfstudio/guidenh/guide/color/ConstantColor.java @@ -3,20 +3,16 @@ import com.github.bsideup.jabel.Desugar; @Desugar -public record ConstantColor(int lightModeColor, int darkModeColor) implements ColorValue { +public record ConstantColor(int color) implements ColorValue { - public static ConstantColor WHITE = new ConstantColor(-1, -1); + public static ConstantColor WHITE = ColorUtils.constant(ColorUtils.WHITE); - public static ConstantColor BLACK = new ConstantColor(0xFF000000, 0xFF000000); + public static ConstantColor BLACK = new ConstantColor(ColorUtils.BLACK.getColor()); - public static ConstantColor TRANSPARENT = new ConstantColor(0, 0); - - public ConstantColor(int color) { - this(color, color); - } + public static ConstantColor TRANSPARENT = ColorUtils.constant(ColorUtils.TRANSPARENT); @Override - public int resolve(LightDarkMode lightDarkMode) { - return lightDarkMode == LightDarkMode.LIGHT_MODE ? lightModeColor : darkModeColor; + public int resolve() { + return color; } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/LightDarkMode.java b/src/main/java/com/hfstudio/guidenh/guide/color/LightDarkMode.java deleted file mode 100644 index 93ee3213..00000000 --- a/src/main/java/com/hfstudio/guidenh/guide/color/LightDarkMode.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.hfstudio.guidenh.guide.color; - -public enum LightDarkMode { - - LIGHT_MODE, - DARK_MODE; - - public static LightDarkMode current() { - return DARK_MODE; - } -} diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/LightnessFunction.java b/src/main/java/com/hfstudio/guidenh/guide/color/LightnessFunction.java index 2e8902ad..3237c4c2 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/color/LightnessFunction.java +++ b/src/main/java/com/hfstudio/guidenh/guide/color/LightnessFunction.java @@ -14,8 +14,8 @@ public LightnessFunction(ColorValue color, float percentage) { } @Override - public int resolve(LightDarkMode lightDarkMode) { - var mutableColor = MutableColor.of(color, lightDarkMode); + public int resolve() { + var mutableColor = MutableColor.of(color); if (percentage < 0) { mutableColor.darker(-percentage); } else if (percentage > 0) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/MutableColor.java b/src/main/java/com/hfstudio/guidenh/guide/color/MutableColor.java index 62c767be..2b0c32e7 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/color/MutableColor.java +++ b/src/main/java/com/hfstudio/guidenh/guide/color/MutableColor.java @@ -29,10 +29,10 @@ public MutableColor(float r, float g, float b, float a) { } public static MutableColor ofArgb32(int packedColor) { - var r = ARGB.red(packedColor); - var g = ARGB.green(packedColor); - var b = ARGB.blue(packedColor); - var a = ARGB.alpha(packedColor); + var r = ColorUtils.red(packedColor); + var g = ColorUtils.green(packedColor); + var b = ColorUtils.blue(packedColor); + var a = ColorUtils.alpha(packedColor); return MutableColor.ofBytes(r, g, b, a); } @@ -47,16 +47,12 @@ public static MutableColor ofBytes(int r, int g, int b, int a) { /** * Resolves a symbolic color value and copies it into a new mutable color. */ - public static MutableColor of(ColorValue color, LightDarkMode mode) { - return ofArgb32(color.resolve(mode)); + public static MutableColor of(ColorValue color) { + return ofArgb32(color.resolve()); } public int toArgb32() { - return ARGB.color(alphaByte(), redByte(), greenByte(), blueByte()); - } - - public int toAbgr32() { - return ARGB.color(alphaByte(), redByte(), greenByte(), blueByte()); + return ColorUtils.argb(alphaByte(), redByte(), greenByte(), blueByte()); } public float red() { @@ -194,7 +190,7 @@ public MutableColor copy() { } @Override - public int resolve(LightDarkMode lightDarkMode) { + public int resolve() { return toArgb32(); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/SymbolicColor.java b/src/main/java/com/hfstudio/guidenh/guide/color/SymbolicColor.java deleted file mode 100644 index 00726570..00000000 --- a/src/main/java/com/hfstudio/guidenh/guide/color/SymbolicColor.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.hfstudio.guidenh.guide.color; - -/** - * Symbolic colors can be overridden more easily in styles and define both a light- and dark-themed color variant. - */ -public enum SymbolicColor implements ColorValue { - - LINK(Colors.rgb(0, 213, 255), Colors.rgb(0, 213, 255)), - BODY_TEXT(Colors.rgb(210, 210, 210), Colors.rgb(210, 210, 210)), - ERROR_TEXT(Colors.rgb(255, 0, 0), Colors.rgb(255, 0, 0)), - /** - * Color used for the type of crafting shown in recipe blocks. - */ - CRAFTING_RECIPE_TYPE(Colors.rgb(64, 64, 64), Colors.rgb(64, 64, 64)), - THEMATIC_BREAK(Colors.rgb(55, 55, 55), Colors.rgb(155, 155, 155)), - - HEADER1_SEPARATOR(Colors.argb(127, 255, 255, 255), Colors.argb(127, 255, 255, 255)), - HEADER2_SEPARATOR(Colors.argb(127, 210, 210, 210), Colors.argb(127, 210, 210, 210)), - - NAVBAR_BG_TOP(Colors.rgb(0, 0, 0), Colors.rgb(0, 0, 0)), - NAVBAR_BG_BOTTOM(Colors.argb(127, 0, 0, 0), Colors.argb(127, 0, 0, 0)), - NAVBAR_ROW_HOVER(Colors.rgb(33, 33, 33), Colors.rgb(33, 33, 33)), - NAVBAR_EXPAND_ARROW(Colors.rgb(238, 238, 238), Colors.rgb(238, 238, 238)), - TABLE_BORDER(Colors.rgb(124, 124, 124), Colors.rgb(124, 124, 124)), - - ICON_BUTTON_NORMAL(Colors.mono(200), Colors.mono(200)), - ICON_BUTTON_DISABLED(Colors.mono(64), Colors.mono(64)), - ICON_BUTTON_HOVER(Colors.rgb(0, 213, 255), Colors.rgb(0, 213, 255)), - - IN_WORLD_BLOCK_HIGHLIGHT(Colors.argb(0xcc, 0x99, 0x99, 0x99), Colors.argb(0xcc, 0x99, 0x99, 0x99)), - - SCENE_BACKGROUND(Colors.argb(20, 0, 0, 0), Colors.argb(20, 0, 0, 0)), - - GUIDE_SCREEN_BACKGROUND(Colors.argb(229, 63, 63, 63), Colors.argb(229, 63, 63, 63)), - - BLOCKQUOTE_BACKGROUND(Colors.argb(64, 255, 255, 255), Colors.argb(64, 255, 255, 255)), - - // these are the Minecraft colors - BLACK(Colors.hexToRgb("#000"), Colors.hexToRgb("#000")), - DARK_BLUE(Colors.hexToRgb("#00A"), Colors.hexToRgb("#00A")), - DARK_GREEN(Colors.hexToRgb("#0A0"), Colors.hexToRgb("#0A0")), - DARK_AQUA(Colors.hexToRgb("#0AA"), Colors.hexToRgb("#0AA")), - DARK_RED(Colors.hexToRgb("#A00"), Colors.hexToRgb("#A00")), - DARK_PURPLE(Colors.hexToRgb("#A0A"), Colors.hexToRgb("#A0A")), - GOLD(Colors.hexToRgb("#AA0"), Colors.hexToRgb("#AA0")), - GRAY(Colors.hexToRgb("#AAA"), Colors.hexToRgb("#AAA")), - DARK_GRAY(Colors.hexToRgb("#555"), Colors.hexToRgb("#555")), - BLUE(Colors.hexToRgb("#55F"), Colors.hexToRgb("#55F")), - GREEN(Colors.hexToRgb("#5F5"), Colors.hexToRgb("#5F5")), - AQUA(Colors.hexToRgb("#5FF"), Colors.hexToRgb("#5FF")), - RED(Colors.hexToRgb("#F55"), Colors.hexToRgb("#F55")), - LIGHT_PURPLE(Colors.hexToRgb("#F5F"), Colors.hexToRgb("#F5F")), - YELLOW(Colors.hexToRgb("#FF5"), Colors.hexToRgb("#FF5")), - WHITE(Colors.hexToRgb("#FFF"), Colors.hexToRgb("#FFF")), - - ; - - final int lightMode; - final int darkMode; - - SymbolicColor(int lightMode, int darkMode) { - this.lightMode = lightMode; - this.darkMode = darkMode; - } - - @Override - public int resolve(LightDarkMode lightDarkMode) { - return lightDarkMode == LightDarkMode.LIGHT_MODE ? lightMode : darkMode; - } -} diff --git a/src/main/java/com/hfstudio/guidenh/guide/color/SymbolicColorResolver.java b/src/main/java/com/hfstudio/guidenh/guide/color/SymbolicColorResolver.java index b5dcd266..f5eb3d0a 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/color/SymbolicColorResolver.java +++ b/src/main/java/com/hfstudio/guidenh/guide/color/SymbolicColorResolver.java @@ -1,7 +1,5 @@ package com.hfstudio.guidenh.guide.color; -import java.util.Locale; - import net.minecraft.util.ResourceLocation; import org.jetbrains.annotations.Nullable; @@ -27,16 +25,17 @@ public interface SymbolicColorResolver extends Extension { ColorValue resolve(ResourceLocation id); /** - * Helper to resolve a symbolic color from both the pre-defined colors in {@link SymbolicColor}, as well as + * Helper to resolve a symbolic color from the pre-defined colors in {@link ColorUtils}, as well as * user-supplied symbolic color resolvers. * * @return null when the color cannot be resolved. */ @Nullable static ColorValue resolve(PageCompiler compiler, String id) { - try { - return SymbolicColor.valueOf(id.toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException ignored) {} + ColorValue builtIn = ColorUtils.symbolic(id); + if (builtIn != null) { + return builtIn; + } // See if it's an identifier ResourceLocation identifier; diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/PageCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/PageCompiler.java index 90c2c65b..4c7221a7 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/PageCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/PageCompiler.java @@ -23,8 +23,8 @@ import com.github.bsideup.jabel.Desugar; import com.hfstudio.guidenh.guide.GuidePage; import com.hfstudio.guidenh.guide.PageCollection; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.compiler.tags.CsvTableCompiler; import com.hfstudio.guidenh.guide.compiler.tags.DetailsContentExtractor; import com.hfstudio.guidenh.guide.document.block.LatexRenderOptions; @@ -95,7 +95,7 @@ public class PageCompiler { */ public static final int DEFAULT_ELEMENT_SPACING = 5; public static final MdastOptions PARSE_OPTIONS = GuideMarkdownOptions.runtime(); - public static final int DEFAULT_MARK_BACKGROUND_COLOR = 0xFF8A6A00; + public static final int DEFAULT_MARK_BACKGROUND_COLOR = ColorUtils.ARGB_FF8A6A00.getColor(); private static final Pattern TABLE_ATTRIBUTE_LINE = Pattern.compile("^\\{:\\s*(.+?)\\s*}$"); private static PageLinkResolver pageLinkResolver = PageCompiler::defaultPageExistsForLink; private static final State> SOURCE_SLICE_STACK = new State<>( @@ -751,7 +751,7 @@ private void compileFlowContent(LytFlowParent layoutParent, MdAstAnyContent cont } else if (content instanceof MdxJsxTextElement el) { if ("Spoiler".equals(el.name())) { var span = new LytSpoilerSpan(); - span.modifyStyle(style -> style.backgroundColor(new ConstantColor(0xFF000000))); + span.modifyStyle(style -> style.backgroundColor(new ConstantColor(ColorUtils.BLACK.getColor()))); compileFlowContext(el, span); layoutChild = span; } else if ("span".equals(el.name())) { @@ -981,7 +981,7 @@ public LytBlock createErrorBlock(String text, UnistNode child) { public LytFlowContent createErrorFlowContent(String text, UnistNode child) { LytFlowSpan span = new LytFlowSpan(); span.modifyStyle( - style -> style.color(SymbolicColor.ERROR_TEXT) + style -> style.color(ColorUtils.ERROR_TEXT) .whiteSpace(WhiteSpaceMode.PRE)); // Find the position in the source diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/BlockquoteCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/BlockquoteCompiler.java index 06b6bada..a16d8dda 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/BlockquoteCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/BlockquoteCompiler.java @@ -3,7 +3,7 @@ import java.util.Collections; import java.util.Set; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.document.block.LytAlertBox; import com.hfstudio.guidenh.guide.document.block.LytBlockContainer; @@ -59,10 +59,10 @@ protected void compile(PageCompiler compiler, LytBlockContainer parent, MdxJsxEl // Plain blockquote LytVBox blockquote = new LytVBox(); - blockquote.setBackgroundColor(SymbolicColor.BLOCKQUOTE_BACKGROUND); + blockquote.setBackgroundColor(ColorUtils.BLOCKQUOTE_BACKGROUND); blockquote.setPadding(5); blockquote.setPaddingLeft(10); - blockquote.setBorderLeft(new BorderStyle(SymbolicColor.TABLE_BORDER, 2)); + blockquote.setBorderLeft(new BorderStyle(ColorUtils.TABLE_BORDER, 2)); blockquote.setMarginTop(PageCompiler.DEFAULT_ELEMENT_SPACING); blockquote.setMarginBottom(PageCompiler.DEFAULT_ELEMENT_SPACING); compiler.compileBlockContext(el.children(), blockquote); diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/FloatingImageCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/FloatingImageCompiler.java index f2f50972..eb24f499 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/FloatingImageCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/FloatingImageCompiler.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.compiler.IdUtils; @@ -222,7 +223,8 @@ private static ImageRegionAnnotation parseImageAnnotationRegion(PageCompiler com if (allowBorder && el.getAttribute("borderColor") != null) { borderColor = MdxAttrs.getColor(compiler, parent, el, "borderColor", ConstantColor.WHITE); } else { - borderColor = allowBorder ? new ConstantColor(0xFF000000 | RANDOM.nextInt(0x1000000)) : ConstantColor.WHITE; + borderColor = allowBorder ? new ConstantColor(ColorUtils.BLACK.getColor() | RANDOM.nextInt(0x1000000)) + : ConstantColor.WHITE; } if (wholeImage) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/KbdTagCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/KbdTagCompiler.java index 9039639d..5ac70097 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/KbdTagCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/KbdTagCompiler.java @@ -3,6 +3,7 @@ import java.util.Collections; import java.util.Set; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.document.flow.LytFlowParent; @@ -11,7 +12,7 @@ public class KbdTagCompiler extends FlowTagCompiler { - private static final ConstantColor KEY_COLOR = new ConstantColor(0xFFE8EDF5); + private static final ConstantColor KEY_COLOR = new ConstantColor(ColorUtils.ARGB_FFE8EDF5.getColor()); @Override public Set getTagNames() { diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/LatexTagCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/LatexTagCompiler.java index d9833a28..b01f7df5 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/LatexTagCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/LatexTagCompiler.java @@ -3,6 +3,7 @@ import java.util.Collections; import java.util.Set; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.TagCompiler; import com.hfstudio.guidenh.guide.document.LytErrorSink; @@ -180,7 +181,7 @@ private static int parseColor(PageCompiler compiler, LytErrorSink errorSink, Mdx } try { if (colorStr.length() == 6) { - return 0xFF000000 | Integer.parseUnsignedInt(colorStr, 16); + return ColorUtils.BLACK.getColor() | Integer.parseUnsignedInt(colorStr, 16); } if (colorStr.length() == 8) { return (int) Long.parseLong(colorStr, 16); diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/MdxAttrs.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/MdxAttrs.java index 89dd3aed..309bee91 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/MdxAttrs.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/MdxAttrs.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; -import com.hfstudio.guidenh.guide.color.ARGB; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.compiler.GuideItemReferenceResolver; @@ -227,7 +227,7 @@ public static ColorValue getColor(PageCompiler compiler, LytErrorSink errorSink, g = Integer.valueOf(colorStr.substring(5, 7), 16); b = Integer.valueOf(colorStr.substring(7, 9), 16); } - return new ConstantColor(ARGB.color(a, r, g, b)); + return new ConstantColor(ColorUtils.argb(a, r, g, b)); } return defaultColor; } diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/chart/ChartAttrParser.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/chart/ChartAttrParser.java index aa20af64..5b6084bc 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/chart/ChartAttrParser.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/chart/ChartAttrParser.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.tags.MdxAttrs; import com.hfstudio.guidenh.guide.document.LytErrorSink; @@ -18,16 +19,12 @@ public class ChartAttrParser { /** Default 16-color cyclic palette (opaque). */ - public static final int[] DEFAULT_PALETTE = new int[] { 0xFF4E79A7, 0xFFF28E2B, 0xFFE15759, 0xFF76B7B2, 0xFF59A14F, - 0xFFEDC948, 0xFFB07AA1, 0xFFFF9DA7, 0xFF9C755F, 0xFFBAB0AC, 0xFF1F77B4, 0xFFFF7F0E, 0xFF2CA02C, 0xFFD62728, - 0xFF9467BD, 0xFF8C564B }; - protected ChartAttrParser() {} public static int paletteColor(int index) { - int n = DEFAULT_PALETTE.length; + int n = ColorUtils.CHART_PALETTE.length; int i = ((index % n) + n) % n; - return DEFAULT_PALETTE[i]; + return ColorUtils.getColor(ColorUtils.CHART_PALETTE[i]); } /** @@ -169,10 +166,10 @@ public static int parseColor(String s, int def) { int r = Integer.parseInt(t.substring(0, 1), 16) * 17; int g = Integer.parseInt(t.substring(1, 2), 16) * 17; int b = Integer.parseInt(t.substring(2, 3), 16) * 17; - return 0xFF000000 | (r << 16) | (g << 8) | b; + return ColorUtils.BLACK.getColor() | (r << 16) | (g << 8) | b; } case 6: - return 0xFF000000 | Integer.parseInt(t, 16); + return ColorUtils.BLACK.getColor() | Integer.parseInt(t, 16); case 8: return (int) Long.parseLong(t, 16); default: diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/functiongraph/FunctionGraphAttrs.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/functiongraph/FunctionGraphAttrs.java index 5de2b15c..8dcc2338 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/functiongraph/FunctionGraphAttrs.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/functiongraph/FunctionGraphAttrs.java @@ -1,5 +1,6 @@ package com.hfstudio.guidenh.guide.compiler.tags.functiongraph; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.tags.MdxAttrs; import com.hfstudio.guidenh.guide.compiler.tags.chart.ChartAttrParser; @@ -40,19 +41,19 @@ public static void applyContainerAttrs(LytFunctionGraph graph, PageCompiler comp String bg = MdxAttrs.getString(compiler, sink, el, "background", null); if (bg != null) { - graph.setBackgroundColor(ChartAttrParser.parseColor(bg, 0xFF1B1F23)); + graph.setBackgroundColor(ChartAttrParser.parseColor(bg, ColorUtils.CHART_BACKGROUND.getColor())); } String border = MdxAttrs.getString(compiler, sink, el, "border", null); if (border != null) { - graph.setBorderColor(ChartAttrParser.parseColor(border, 0xFF3A4047)); + graph.setBorderColor(ChartAttrParser.parseColor(border, ColorUtils.CHART_BORDER.getColor())); } String axis = MdxAttrs.getString(compiler, sink, el, "axisColor", null); if (axis != null) { - graph.setAxisColor(ChartAttrParser.parseColor(axis, 0xFFB8C2CF)); + graph.setAxisColor(ChartAttrParser.parseColor(axis, ColorUtils.CHART_LABEL.getColor())); } String grid = MdxAttrs.getString(compiler, sink, el, "gridColor", null); if (grid != null) { - graph.setGridColor(ChartAttrParser.parseColor(grid, 0x33B8C2CF)); + graph.setGridColor(ChartAttrParser.parseColor(grid, ColorUtils.CHART_GRID.getColor())); } graph.setShowGrid(MdxAttrs.getBoolean(compiler, sink, el, "showGrid", true)); graph.setShowAxes(MdxAttrs.getBoolean(compiler, sink, el, "showAxes", true)); @@ -157,7 +158,8 @@ public static FunctionPlot parsePlot(PageCompiler compiler, LytErrorSink sink, M public static MarkedPoint parsePoint(PageCompiler compiler, LytErrorSink sink, MdxJsxElementFields el) { String colorStr = MdxAttrs.getString(compiler, sink, el, "color", null); boolean colorInherit = colorStr == null; - int color = colorStr != null ? ChartAttrParser.parseColor(colorStr, 0xFFFFFFFF) : 0xFFFFFFFF; + int color = colorStr != null ? ChartAttrParser.parseColor(colorStr, ColorUtils.WHITE.getColor()) + : ColorUtils.WHITE.getColor(); String label = MdxAttrs.getString(compiler, sink, el, "label", null); double xValue = parseDouble(MdxAttrs.getString(compiler, sink, el, "x", null), Double.NaN); diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/functiongraph/FunctionGraphFenceParser.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/functiongraph/FunctionGraphFenceParser.java index e82ec46b..a1226745 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/functiongraph/FunctionGraphFenceParser.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/functiongraph/FunctionGraphFenceParser.java @@ -3,6 +3,7 @@ import java.util.LinkedHashMap; import java.util.Map; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.tags.chart.ChartAttrParser; import com.hfstudio.guidenh.guide.document.block.chart.CornerLegendPosition; import com.hfstudio.guidenh.guide.document.block.chart.CornerLegendRenderer; @@ -122,19 +123,19 @@ private static void applyHeader(LytFunctionGraph graph, String line) { } String bg = attrs.stringValue("background"); if (bg != null) { - graph.setBackgroundColor(ChartAttrParser.parseColor(bg, 0xFF1B1F23)); + graph.setBackgroundColor(ChartAttrParser.parseColor(bg, ColorUtils.CHART_BACKGROUND.getColor())); } String border = attrs.stringValue("border"); if (border != null) { - graph.setBorderColor(ChartAttrParser.parseColor(border, 0xFF3A4047)); + graph.setBorderColor(ChartAttrParser.parseColor(border, ColorUtils.CHART_BORDER.getColor())); } String axisColor = attrs.stringValue("axisColor"); if (axisColor != null) { - graph.setAxisColor(ChartAttrParser.parseColor(axisColor, 0xFFB8C2CF)); + graph.setAxisColor(ChartAttrParser.parseColor(axisColor, ColorUtils.CHART_LABEL.getColor())); } String gridColor = attrs.stringValue("gridColor"); if (gridColor != null) { - graph.setGridColor(ChartAttrParser.parseColor(gridColor, 0x33B8C2CF)); + graph.setGridColor(ChartAttrParser.parseColor(gridColor, ColorUtils.CHART_GRID.getColor())); } Boolean showGrid = attrs.boolValue("showGrid"); if (showGrid != null) { @@ -337,7 +338,8 @@ private static MarkedPoint parseExplicitPoint(String body) { return null; } String colorStr = attrs.stringValue("color"); - int color = colorStr != null ? ChartAttrParser.parseColor(colorStr, 0xFFFFFFFF) : 0xFFFFFFFF; + int color = colorStr != null ? ChartAttrParser.parseColor(colorStr, ColorUtils.WHITE.getColor()) + : ColorUtils.WHITE.getColor(); return new MarkedPoint(MarkedPoint.MODE_EXPLICIT, -1, x, y, color, false, attrs.stringValue("label")); } @@ -350,7 +352,8 @@ private static MarkedPoint parsePlotPoint(String body) { } String colorStr = attrs.stringValue("color"); boolean inherit = colorStr == null; - int color = colorStr != null ? ChartAttrParser.parseColor(colorStr, 0xFFFFFFFF) : 0xFFFFFFFF; + int color = colorStr != null ? ChartAttrParser.parseColor(colorStr, ColorUtils.WHITE.getColor()) + : ColorUtils.WHITE.getColor(); String label = attrs.stringValue("label"); double atX = FunctionGraphAttrs.parseDouble(attrs.stringValue("atX"), Double.NaN); if (!Double.isNaN(atX)) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/mediawiki/MediaWikiTagCompilerSupport.java b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/mediawiki/MediaWikiTagCompilerSupport.java index e742373c..388f9bc9 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/mediawiki/MediaWikiTagCompilerSupport.java +++ b/src/main/java/com/hfstudio/guidenh/guide/compiler/tags/mediawiki/MediaWikiTagCompilerSupport.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable; import com.hfstudio.guidenh.guide.Guide; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.IndexingContext; import com.hfstudio.guidenh.guide.compiler.IndexingSink; import com.hfstudio.guidenh.guide.compiler.PageCompiler; @@ -69,8 +69,8 @@ public static MediaWikiGeneratedListBlock createBlock(List e String emptyText) { var block = new MediaWikiGeneratedListBlock(); block.setFullWidth(true); - block.setBorderTop(new BorderStyle(SymbolicColor.TABLE_BORDER, 1)); - block.setBorderBottom(new BorderStyle(SymbolicColor.TABLE_BORDER, 1)); + block.setBorderTop(new BorderStyle(ColorUtils.TABLE_BORDER, 1)); + block.setBorderBottom(new BorderStyle(ColorUtils.TABLE_BORDER, 1)); block.setEntries(entries); block.setRows(MediaWikiListPlanner.sanitizeRows(rows)); block.setEmptyText(emptyText); @@ -137,8 +137,8 @@ public static void indexEntries(IndexingSink sink, UnistNode parent, List style.bold(true) .fontScale(DefaultStyles.HEADING5.fontScale()) - .color(new ConstantColor(0xFFD8E9FF))); + .color(new ConstantColor(ColorUtils.ARGB_FFD8E9FF.getColor()))); append(titleParagraph); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytBox.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytBox.java index 1b3e6b2d..a2c7030a 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytBox.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytBox.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.Nullable; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; import com.hfstudio.guidenh.guide.render.RenderContext; @@ -28,7 +28,7 @@ public abstract class LytBox extends LytBlock implements LytBlockContainer { private final BorderRenderer borderRenderer = new BorderRenderer(); @Nullable - private SymbolicColor backgroundColor; + private ColorValue backgroundColor; @Override public void removeChild(LytNode node) { @@ -113,11 +113,11 @@ public final void setPadding(int padding) { paddingBottom = padding; } - public @Nullable SymbolicColor getBackgroundColor() { + public @Nullable ColorValue getBackgroundColor() { return backgroundColor; } - public void setBackgroundColor(@Nullable SymbolicColor backgroundColor) { + public void setBackgroundColor(@Nullable ColorValue backgroundColor) { this.backgroundColor = backgroundColor; } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytCodeBlockToolbar.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytCodeBlockToolbar.java index 9ee2c4f9..9d6d2108 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytCodeBlockToolbar.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytCodeBlockToolbar.java @@ -4,9 +4,9 @@ import java.util.List; import java.util.Optional; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.document.LytPoint; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.LytSize; @@ -65,7 +65,7 @@ public class LytCodeBlockToolbar extends LytBox implements InteractiveElement { public LytCodeBlockToolbar() { copySourceButton = new LytButton(COPY_SPRITE, new LytSize(16, 16)); copySourceButton.setColor(toolbarText); - copySourceButton.setHoverColor(SymbolicColor.ICON_BUTTON_HOVER); + copySourceButton.setHoverColor(ColorUtils.ICON_BUTTON_HOVER); copySourceButton.setOnClick(screen -> screen.copyCodeBlock(copyText)); copySourceButton.setTooltipFunction((pressed) -> { if (pressed) return GuidebookText.CodeBlockCopySuccess.text(); diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytContentTabsBlock.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytContentTabsBlock.java index 175ad2f6..2850fc23 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytContentTabsBlock.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytContentTabsBlock.java @@ -6,9 +6,9 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.tags.ContentTabsSpec; import com.hfstudio.guidenh.guide.document.LytRect; @@ -38,8 +38,8 @@ public class LytContentTabsBlock extends LytBlock implements InteractiveElement, private static final int ACTIVE_RULE_THICKNESS = 2; private static final int TITLE_GAP = 4; private static final int BODY_GAP = 6; - private static final ConstantColor DEFAULT_ACCENT = new ConstantColor(0xFF7C8795); - private static final int HEADER_RULE_COLOR = 0x66586275; + private static final ConstantColor DEFAULT_ACCENT = new ConstantColor(ColorUtils.ARGB_FF7C8795.getColor()); + private static final int HEADER_RULE_COLOR = ColorUtils.ARGB_66586275.getColor(); private final List tabs = new ArrayList<>(); private final List children = new ArrayList<>(); private final ColorValue accentColor; @@ -59,7 +59,7 @@ public class LytContentTabsBlock extends LytBlock implements InteractiveElement, false, false, "", - new ConstantColor(0xFFF4F7FB), + new ConstantColor(ColorUtils.ARGB_FFF4F7FB.getColor()), WhiteSpaceMode.NORMAL, TextAlignment.LEFT, false, @@ -75,7 +75,7 @@ public class LytContentTabsBlock extends LytBlock implements InteractiveElement, false, false, "", - new ConstantColor(0xFFD5DCE7), + new ConstantColor(ColorUtils.ARGB_FFD5DCE7.getColor()), WhiteSpaceMode.NORMAL, TextAlignment.LEFT, false, @@ -190,7 +190,7 @@ public void render(RenderContext context) { } int safeSelectedIndex = getSafeSelectedIndex(); int accentArgb = context.resolveColor(accentColor); - context.fillRect(bounds, context.resolveColor(SymbolicColor.BLOCKQUOTE_BACKGROUND)); + context.fillRect(bounds, context.resolveColor(ColorUtils.BLOCKQUOTE_BACKGROUND)); context.fillRect(bounds.x(), bounds.y(), ACCENT_WIDTH, bounds.height(), accentArgb); if (titleParagraph != null) { titleParagraph.render(context); diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytDetailsBlock.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytDetailsBlock.java index 2d81bd6d..80b5efe1 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytDetailsBlock.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytDetailsBlock.java @@ -4,8 +4,8 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.interaction.DocumentDragTarget; import com.hfstudio.guidenh.guide.document.interaction.InteractiveElement; @@ -20,7 +20,7 @@ public class LytDetailsBlock extends LytBlock implements InteractiveElement, LytBlockContainer, DocumentDragTarget { - private static final ConstantColor SUMMARY_COLOR = new ConstantColor(0xFFE2E6ED); + private static final ConstantColor SUMMARY_COLOR = new ConstantColor(ColorUtils.ARGB_FFE2E6ED.getColor()); private static final String SUMMARY_OPEN_MARKER = "v"; private static final String SUMMARY_CLOSED_MARKER = ">"; private static final String DEFAULT_SUMMARY_TEXT = "Details"; @@ -31,7 +31,7 @@ public class LytDetailsBlock extends LytBlock implements InteractiveElement, Lyt private static final int SCROLLBAR_GAP = 4; private static final int MIN_SCROLLBAR_THUMB = 14; private static final int MIN_WHEEL_STEP = 16; - private static final BorderStyle DETAILS_BORDER = new BorderStyle(SymbolicColor.TABLE_BORDER, BORDER_WIDTH); + private static final BorderStyle DETAILS_BORDER = new BorderStyle(ColorUtils.TABLE_BORDER, BORDER_WIDTH); private final LytHBox summaryRow = new LytHBox(); private final LytParagraph summaryMarker = new LytParagraph(); @@ -215,7 +215,7 @@ protected void onLayoutMoved(int deltaX, int deltaY) { @Override public void render(RenderContext context) { updateVisualScroll(); - context.fillRect(bounds, SymbolicColor.BLOCKQUOTE_BACKGROUND); + context.fillRect(bounds, ColorUtils.BLOCKQUOTE_BACKGROUND); summaryRow.render(context); if (open) { LytRect viewport = getContentViewportBounds(); @@ -326,10 +326,12 @@ private void renderScrollbar(RenderContext context) { if (trackBounds.isEmpty()) { return; } - context.fillRect(trackBounds, 0x30242B33); + context.fillRect(trackBounds, ColorUtils.ARGB_30242B33.getColor()); LytRect thumbBounds = getScrollbarThumbBounds(); if (!thumbBounds.isEmpty()) { - context.fillRect(thumbBounds, draggingScrollbar ? 0xFFCDD6E1 : 0xA0AAB5C2); + context.fillRect( + thumbBounds, + draggingScrollbar ? ColorUtils.ARGB_FFCDD6E1.getColor() : ColorUtils.ARGB_A0AAB5C2.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytFileTree.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytFileTree.java index eadd7750..37538fae 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytFileTree.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytFileTree.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.Nullable; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.internal.markdown.FileTreeParser.SlotKind; import com.hfstudio.guidenh.guide.layout.LayoutContext; @@ -164,7 +164,7 @@ public void render(RenderContext context) { private void renderConnectors(RenderContext context) { int baseX = bounds.x(); // Resolve symbolic color once per frame instead of on every fillRect. - int connectorColor = context.resolveColor(SymbolicColor.TABLE_BORDER); + int connectorColor = context.resolveColor(ColorUtils.TABLE_BORDER); int halfIndent = indentPx / 2; for (Row row : rows) { int rowY = row.rowY; diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytHeading.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytHeading.java index 51c8cc85..4cfbe859 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytHeading.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytHeading.java @@ -1,6 +1,6 @@ package com.hfstudio.guidenh.guide.document.block; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.DefaultStyles; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; @@ -56,12 +56,12 @@ public void render(RenderContext context) { var bounds = getBounds(); int sepX = bounds.x() + separatorXOffset; int sepW = Math.max(0, separatorWidth); - context.fillRect(sepX, bounds.bottom() - 1, sepW, 1, SymbolicColor.HEADER1_SEPARATOR); + context.fillRect(sepX, bounds.bottom() - 1, sepW, 1, ColorUtils.HEADER1_SEPARATOR); } else if (depth == 2) { var bounds = getBounds(); int sepX = bounds.x() + separatorXOffset; int sepW = Math.max(0, separatorWidth); - context.fillRect(sepX, bounds.bottom() - 1, sepW, 1, SymbolicColor.HEADER2_SEPARATOR); + context.fillRect(sepX, bounds.bottom() - 1, sepW, 1, ColorUtils.HEADER2_SEPARATOR); } } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytLatexBlock.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytLatexBlock.java index 8ea7490e..e45fe4f1 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytLatexBlock.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytLatexBlock.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable; import com.hfstudio.guidenh.guide.document.LytRect; +import com.hfstudio.guidenh.guide.document.flow.LytFlowInlineBlock; import com.hfstudio.guidenh.guide.document.interaction.GuideTooltip; import com.hfstudio.guidenh.guide.document.interaction.InteractiveElement; import com.hfstudio.guidenh.guide.latex.GuideLatexRenderer; @@ -15,7 +16,7 @@ /** * Inline-flow LaTeX block. When placed inside a - * {@link com.hfstudio.guidenh.guide.document.flow.LytFlowInlineBlock}, it renders a LaTeX formula at a + * {@link LytFlowInlineBlock}, it renders a LaTeX formula at a * size proportional to the surrounding text, automatically expanding the line height when the formula is * taller than a single character (e.g. fractions). * diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytListItem.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytListItem.java index 0077bfff..fb234d01 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytListItem.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytListItem.java @@ -1,6 +1,6 @@ package com.hfstudio.guidenh.guide.document.block; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.DefaultStyles; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; @@ -52,7 +52,7 @@ public void render(RenderContext context) { var bounds = getBounds(); var markerLine = getMarkerLineBounds(context); int bulletY = markerLine.y() + (markerLine.height() - BULLET_SIZE) / 2; - context.fillRect(bounds.x() + BULLET_X_OFFSET, bulletY, BULLET_SIZE, BULLET_SIZE, SymbolicColor.BODY_TEXT); + context.fillRect(bounds.x() + BULLET_X_OFFSET, bulletY, BULLET_SIZE, BULLET_SIZE, ColorUtils.BODY_TEXT); } super.render(context); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidCanvas.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidCanvas.java index ec0f84f3..575b3918 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidCanvas.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidCanvas.java @@ -14,9 +14,9 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.flow.LytFlowContent; import com.hfstudio.guidenh.guide.document.interaction.DocumentDragTarget; @@ -41,8 +41,8 @@ public abstract class LytMermaidCanvas> extends Ly private static final float ZOOM_STEP = 1.1f; private static final float MIN_ZOOM = 0.5f; private static final float MAX_ZOOM = 2.5f; - static final ConstantColor PANEL_BACKGROUND = new ConstantColor(0x1A0C1117); - static final ConstantColor PANEL_BORDER = new ConstantColor(0x66434C57); + static final ConstantColor PANEL_BACKGROUND = new ConstantColor(ColorUtils.ARGB_1A0C1117.getColor()); + static final ConstantColor PANEL_BORDER = new ConstantColor(ColorUtils.ARGB_66434C57.getColor()); private int contentOffsetX; private int contentOffsetY; @@ -677,11 +677,6 @@ public NodeContentRenderContext(RenderContext delegate, LytRect viewport, int or this.scale = Math.max(0.0001f, scale); } - @Override - public LightDarkMode lightDarkMode() { - return delegate.lightDarkMode(); - } - @Override public LytRect viewport() { return viewport; diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidFlowchart.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidFlowchart.java index c85b1035..b64b8f8a 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidFlowchart.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidFlowchart.java @@ -4,7 +4,7 @@ import java.util.Map; import java.util.Optional; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytSize; import com.hfstudio.guidenh.guide.document.interaction.GuideTooltip; import com.hfstudio.guidenh.guide.document.interaction.InteractiveElement; @@ -38,8 +38,8 @@ public LytMermaidFlowchart(FlowchartDocument flowchart, String sourceText, Map canvas.resetView()); button.setTooltipText(GuidebookText.ResetView.text()); - button.setHoverColor(SymbolicColor.ICON_BUTTON_HOVER); + button.setHoverColor(ColorUtils.ICON_BUTTON_HOVER); return button; } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidFlowchartCanvas.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidFlowchartCanvas.java index be4e3e2d..c5557d7c 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidFlowchartCanvas.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidFlowchartCanvas.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.block.shapes.FlowchartShapes; @@ -43,14 +44,20 @@ public class LytMermaidFlowchartCanvas extends LytMermaidCanvas canvas.resetView()); button.setTooltipText(GuidebookText.ResetView.text()); - button.setHoverColor(SymbolicColor.ICON_BUTTON_HOVER); + button.setHoverColor(ColorUtils.ICON_BUTTON_HOVER); return button; } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidMindmapCanvas.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidMindmapCanvas.java index 6498a35d..7d245b8f 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidMindmapCanvas.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytMermaidMindmapCanvas.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.interaction.DocumentInteractionSnapshot; @@ -35,9 +36,9 @@ public class LytMermaidMindmapCanvas extends LytMermaidCanvas= node.centerX(); int parentEdgeX = scaled(baseX, rightSide ? node.right() : node.x, activeZoom); @@ -464,7 +465,7 @@ private void renderConnectors(RenderContext context, NodeLayout node, int baseX, scaled(baseY, node.centerY(), activeZoom), childEdgeX, scaled(baseY, child.centerY(), activeZoom), - 0xFF5D6C7C); + ColorUtils.ARGB_FF5D6C7C.getColor()); } renderConnectors(context, child, baseX, baseY); } @@ -498,8 +499,8 @@ private void renderNodes(RenderContext context, NodeLayout node, int baseX, int textY, badgeWidth, Math.max(1, context.getLineHeight(badgeStyle) + badgePaddingY * 2)); - context.fillRect(badge, 0x262A3340); - context.drawBorder(badge, 0x66434C57, 1); + context.fillRect(badge, ColorUtils.ARGB_262A3340.getColor()); + context.drawBorder(badge, ColorUtils.ARGB_66434C57.getColor(), 1); context.drawText(node.badgeText, badge.x() + badgePaddingX, badge.y() + badgePaddingY, badgeStyle); textY = badge.bottom() + iconGapY; } @@ -642,38 +643,39 @@ private int resolveNodeBadgeHeightUnscaled(NodeLayout node) { } private NodeColors resolveColors(MindmapNode node) { - int accent = 0xFF7AA2F7; + int accent = ColorUtils.ARGB_FF7AA2F7.getColor(); for (String className : node.getClasses()) { String lower = className.toLowerCase(); if (lower.contains("danger") || lower.contains("error") || lower.contains("urgent") || lower.contains("red")) { - accent = 0xFFF7768E; + accent = ColorUtils.ARGB_FFF7768E.getColor(); break; } if (lower.contains("success") || lower.contains("green") || lower.contains("done")) { - accent = 0xFF9ECE6A; + accent = ColorUtils.ARGB_FF9ECE6A.getColor(); break; } if (lower.contains("warn") || lower.contains("yellow") || lower.contains("amber")) { - accent = 0xFFE0AF68; + accent = ColorUtils.ARGB_FFE0AF68.getColor(); break; } if (lower.contains("muted") || lower.contains("gray") || lower.contains("grey")) { - accent = 0xFF8B949E; + accent = ColorUtils.ARGB_FF8B949E.getColor(); } } accent = switch (node.getShape()) { - case CIRCLE -> 0xFF7DCFFF; - case HEXAGON -> 0xFFE0AF68; - case CLOUD -> 0xFF73DACA; - case BANG -> 0xFFF7768E; + case CIRCLE -> ColorUtils.ARGB_FF7DCFFF.getColor(); + case HEXAGON -> ColorUtils.ARGB_FFE0AF68.getColor(); + case CLOUD -> ColorUtils.ARGB_FF73DACA.getColor(); + case BANG -> ColorUtils.ARGB_FFF7768E.getColor(); default -> accent; }; int border = accent; - int background = node == mindmap.getRoot() ? 0xFF1F2A38 : 0xFF111922; + int background = node == mindmap.getRoot() ? ColorUtils.ARGB_FF1F2A38.getColor() + : ColorUtils.ARGB_FF111922.getColor(); return new NodeColors(background, border, accent); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytParagraph.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytParagraph.java index ff4c68b5..8ecc8174 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytParagraph.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytParagraph.java @@ -6,8 +6,8 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.flow.LytFlowContainer; import com.hfstudio.guidenh.guide.document.flow.LytFlowContent; @@ -180,7 +180,7 @@ public static LytParagraph of(String text) { public static final TextStyle LOADING_STYLE = TextStyle.builder() .italic(true) .obfuscated(true) - .color(new ConstantColor(0xFF808080)) + .color(new ConstantColor(ColorUtils.ARGB_FF808080.getColor())) .build(); /** @@ -197,12 +197,12 @@ public static LytParagraph loading(String text) { /** Warm amber-yellow italic text for placeholder blocks awaiting async materialization. */ public static final TextStyle PLACEHOLDER_STYLE = TextStyle.builder() .italic(true) - .color(new ConstantColor(0xFFE8A317)) + .color(new ConstantColor(ColorUtils.ARGB_FFE8A317.getColor())) .build(); /** Red text style for inline error messages. */ public static final TextStyle ERROR_STYLE = TextStyle.builder() - .color(SymbolicColor.ERROR_TEXT) + .color(ColorUtils.ERROR_TEXT) .build(); /** Creates a placeholder paragraph (amber, italic) for deferred content. */ diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytQuoteBox.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytQuoteBox.java index 5f22d742..7017433e 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytQuoteBox.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytQuoteBox.java @@ -4,9 +4,9 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.flow.LytFlowContent; import com.hfstudio.guidenh.guide.layout.LayoutContext; @@ -15,7 +15,7 @@ public class LytQuoteBox extends LytBlock implements LytBlockContainer { - private static final ColorValue DEFAULT_ACCENT = new ConstantColor(0xFF4FA3FF); + private static final ColorValue DEFAULT_ACCENT = new ConstantColor(ColorUtils.ARGB_FF4FA3FF.getColor()); private final LytVBox root = new LytVBox(); private final LytParagraph titleParagraph = new LytParagraph(); @@ -28,7 +28,7 @@ public LytQuoteBox() { root.setPadding(6); root.setGap(4); root.setFullWidth(true); - root.setBackgroundColor(SymbolicColor.BLOCKQUOTE_BACKGROUND); + root.setBackgroundColor(ColorUtils.BLOCKQUOTE_BACKGROUND); root.setBorderLeft(new BorderStyle(DEFAULT_ACCENT, 3)); titleParagraph.setMarginTop(0); diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytSizeBox.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytSizeBox.java index 36e1e7d6..80ba52f1 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytSizeBox.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytSizeBox.java @@ -2,6 +2,7 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.interaction.DocumentDragTarget; import com.hfstudio.guidenh.guide.internal.editor.gui.SceneEditorVerticalScrollbar; @@ -183,10 +184,12 @@ private void renderScrollbar(RenderContext context) { return; } - context.fillRect(trackBounds, 0x30242B33); + context.fillRect(trackBounds, ColorUtils.ARGB_30242B33.getColor()); LytRect thumbBounds = getScrollbarThumbBounds(); if (!thumbBounds.isEmpty()) { - context.fillRect(thumbBounds, draggingScrollbar ? 0xFFCDD6E1 : 0xA0AAB5C2); + context.fillRect( + thumbBounds, + draggingScrollbar ? ColorUtils.ARGB_FFCDD6E1.getColor() : ColorUtils.ARGB_A0AAB5C2.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytSlot.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytSlot.java index 5c5989ea..f20ee811 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytSlot.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytSlot.java @@ -6,6 +6,7 @@ import net.minecraft.item.ItemStack; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.interaction.GuideTooltip; import com.hfstudio.guidenh.guide.document.interaction.InteractiveElement; @@ -29,9 +30,9 @@ public class LytSlot extends LytBlock implements InteractiveElement { /** Precomputed nanosecond period for item cycling to avoid repeated TimeUnit conversion. */ private static final long CYCLE_NANOS = TimeUnit.MILLISECONDS.toNanos(CYCLE_TIME); - private static final int SLOT_BORDER_DARK = 0xFF373737; - private static final int SLOT_BORDER_LIGHT = 0xFFFFFFFF; - private static final int SLOT_INNER_BG = 0xFF8B8B8B; + private static final int SLOT_BORDER_DARK = ColorUtils.ARGB_FF373737.getColor(); + private static final int SLOT_BORDER_LIGHT = ColorUtils.WHITE.getColor(); + private static final int SLOT_INNER_BG = ColorUtils.ARGB_FF8B8B8B.getColor(); @Getter @Setter diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytStructureView.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytStructureView.java index a9a98a9f..216cae86 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytStructureView.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytStructureView.java @@ -6,6 +6,7 @@ import net.minecraft.item.ItemStack; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; import com.hfstudio.guidenh.guide.render.RenderContext; @@ -70,8 +71,8 @@ protected void onLayoutMoved(int deltaX, int deltaY) {} @Override public void render(RenderContext context) { var bounds = getBounds(); - context.fillRect(bounds, 0xFF1E1E1E); - context.drawBorder(bounds, 0xFF555555, 1); + context.fillRect(bounds, ColorUtils.ARGB_FF1E1E1E.getColor()); + context.drawBorder(bounds, ColorUtils.ARGB_FF555555.getColor(), 1); if (blocks.isEmpty()) { return; diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytTaskListItem.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytTaskListItem.java index 11eced30..27aac945 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytTaskListItem.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytTaskListItem.java @@ -1,6 +1,6 @@ package com.hfstudio.guidenh.guide.document.block; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; import com.hfstudio.guidenh.guide.render.RenderContext; @@ -27,9 +27,9 @@ public void render(RenderContext context) { int boxSize = 7; int boxX = bounds.x() + 1; int boxY = bounds.y() + 1; - context.drawBorder(new LytRect(boxX, boxY, boxSize, boxSize), context.resolveColor(SymbolicColor.BODY_TEXT), 1); + context.drawBorder(new LytRect(boxX, boxY, boxSize, boxSize), context.resolveColor(ColorUtils.BODY_TEXT), 1); if (checked) { - context.fillRect(boxX + 2, boxY + 2, 3, 3, SymbolicColor.LINK); + context.fillRect(boxX + 2, boxY + 2, 3, 3, ColorUtils.LINK); } super.render(context); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytThematicBreak.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytThematicBreak.java index e46771a5..d9be5dcf 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/LytThematicBreak.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/LytThematicBreak.java @@ -1,6 +1,6 @@ package com.hfstudio.guidenh.guide.document.block; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; import com.hfstudio.guidenh.guide.render.RenderContext; @@ -20,6 +20,6 @@ public void render(RenderContext context) { var line = bounds.withHeight(2) .centerVerticallyIn(bounds); - context.fillRect(line, SymbolicColor.THEMATIC_BREAK); + context.fillRect(line, ColorUtils.THEMATIC_BREAK); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/MermaidNodeRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/MermaidNodeRenderer.java index ac7e1af5..487b26ad 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/MermaidNodeRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/MermaidNodeRenderer.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.internal.mermaid.MermaidNodeShape; import com.hfstudio.guidenh.guide.internal.util.GuideStringLines; @@ -16,19 +17,19 @@ public final class MermaidNodeRenderer { private MermaidNodeRenderer() {} - public static final int DEFAULT_ACCENT = 0xFF7AA2F7; - public static final int ACCENT_DANGER = 0xFFF7768E; - public static final int ACCENT_SUCCESS = 0xFF9ECE6A; - public static final int ACCENT_WARN = 0xFFE0AF68; - public static final int ACCENT_MUTED = 0xFF8B949E; - public static final int ACCENT_CIRCLE = 0xFF7DCFFF; - public static final int ACCENT_CLOUD = 0xFF73DACA; + public static final int DEFAULT_ACCENT = ColorUtils.ARGB_FF7AA2F7.getColor(); + public static final int ACCENT_DANGER = ColorUtils.ARGB_FFF7768E.getColor(); + public static final int ACCENT_SUCCESS = ColorUtils.ARGB_FF9ECE6A.getColor(); + public static final int ACCENT_WARN = ColorUtils.ARGB_FFE0AF68.getColor(); + public static final int ACCENT_MUTED = ColorUtils.ARGB_FF8B949E.getColor(); + public static final int ACCENT_CIRCLE = ColorUtils.ARGB_FF7DCFFF.getColor(); + public static final int ACCENT_CLOUD = ColorUtils.ARGB_FF73DACA.getColor(); - public static final int DEFAULT_BACKGROUND = 0xFF1F2A38; - public static final int ALT_BACKGROUND = 0xFF111922; + public static final int DEFAULT_BACKGROUND = ColorUtils.ARGB_FF1F2A38.getColor(); + public static final int ALT_BACKGROUND = ColorUtils.ARGB_FF111922.getColor(); - public static final int BADGE_BACKGROUND = 0x262A3340; - public static final int BADGE_BORDER = 0x66434C57; + public static final int BADGE_BACKGROUND = ColorUtils.ARGB_262A3340.getColor(); + public static final int BADGE_BORDER = ColorUtils.ARGB_66434C57.getColor(); public record NodeColors(int background, int border, int accent) {} diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/CartesianChartRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/CartesianChartRenderer.java index f91fefd0..9d26b13f 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/CartesianChartRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/CartesianChartRenderer.java @@ -1,5 +1,6 @@ package com.hfstudio.guidenh.guide.document.block.chart; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.render.RenderContext; import com.hfstudio.guidenh.guide.style.ResolvedTextStyle; @@ -14,7 +15,7 @@ protected CartesianChartRenderer() {} /** Compute insets reserved for axis labels; returns [left, top, right, bottom] (pixels). */ public static int[] computeAxisInsets(RenderContext context, ChartAxisOptions xAxis, ChartAxisOptions yAxis, AxisRange xRange, AxisRange yRange, String[] xCategories, boolean showXTicks, boolean showYTicks) { - ResolvedTextStyle style = LytChartBase.textStyle(0xFFCCCCCC); + ResolvedTextStyle style = LytChartBase.textStyle(ColorUtils.ARGB_FFCCCCCC.getColor()); int lineH = context.getLineHeight(style); int left = 4; int top = 4; diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/ChartAxisOptions.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/ChartAxisOptions.java index be5b27fb..01b48ef7 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/ChartAxisOptions.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/ChartAxisOptions.java @@ -2,6 +2,8 @@ import java.util.IllegalFormatException; +import com.hfstudio.guidenh.guide.color.ColorUtils; + import lombok.Getter; import lombok.Setter; @@ -19,9 +21,9 @@ public class ChartAxisOptions { private String tickFormat; private String unit; private boolean gridVisible; - private int gridColor = 0x33FFFFFF; - private int axisColor = 0xFF7A7A7A; - private int labelColor = 0xFFCCCCCC; + private int gridColor = ColorUtils.ARGB_33FFFFFF.getColor(); + private int axisColor = ColorUtils.ARGB_FF7A7A7A.getColor(); + private int labelColor = ColorUtils.ARGB_FFCCCCCC.getColor(); /** * Format a numeric value using the configured tickFormat and unit; when tickFormat is unspecified, diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/ChartLegendRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/ChartLegendRenderer.java index edf6ad2e..e2e594ab 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/ChartLegendRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/ChartLegendRenderer.java @@ -5,6 +5,7 @@ import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; import com.hfstudio.guidenh.guide.render.RenderContext; @@ -78,7 +79,7 @@ public static Layout computeLayout(RenderContext context, List entr contentBottom); } - ResolvedTextStyle textStyle = LytChartBase.textStyle(0xFFCCCCCC); + ResolvedTextStyle textStyle = LytChartBase.textStyle(ColorUtils.ARGB_FFCCCCCC.getColor()); int lineHeight = context.getLineHeight(textStyle); int swatch = LytChartBase.LEGEND_SWATCH_SIZE; int gap = LytChartBase.LEGEND_GAP; @@ -144,7 +145,7 @@ public static void render(RenderContext context, Layout layout, ResolvedTextStyl if (layout.position == ChartLegendPosition.NONE || layout.entries.isEmpty()) { return; } - ResolvedTextStyle textStyle = LytChartBase.textStyle(0xFFCCCCCC); + ResolvedTextStyle textStyle = LytChartBase.textStyle(ColorUtils.ARGB_FFCCCCCC.getColor()); int lineHeight = context.getLineHeight(textStyle); int swatch = LytChartBase.LEGEND_SWATCH_SIZE; LytRect rect = layout.legendRect; @@ -208,7 +209,7 @@ public static int measureHeight(LayoutContext context, List entries if (position != ChartLegendPosition.TOP && position != ChartLegendPosition.BOTTOM) { return 0; } - ResolvedTextStyle textStyle = LytChartBase.textStyle(0xFFCCCCCC); + ResolvedTextStyle textStyle = LytChartBase.textStyle(ColorUtils.ARGB_FFCCCCCC.getColor()); return measureHorizontalLegendHeight( entries, position, diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/CornerLegendRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/CornerLegendRenderer.java index 70a198de..f53dcc97 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/CornerLegendRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/chart/CornerLegendRenderer.java @@ -2,6 +2,7 @@ import java.util.List; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.render.RenderContext; import com.hfstudio.guidenh.guide.style.ResolvedTextStyle; @@ -10,7 +11,7 @@ public class CornerLegendRenderer { public static final int DEFAULT_WIDTH = 120; public static final int DEFAULT_HEIGHT = 64; - public static final int DEFAULT_BACKGROUND = 0xAA111922; + public static final int DEFAULT_BACKGROUND = ColorUtils.ARGB_AA111922.getColor(); private static final int PADDING_X = 5; private static final int PADDING_Y = 4; @@ -20,7 +21,7 @@ public class CornerLegendRenderer { private static final int MARKER_HEIGHT = 6; private static final int MIN_WIDTH = 24; private static final int MIN_HEIGHT = 12; - private static final ResolvedTextStyle TEXT_STYLE = LytChartBase.textStyle(0xFFFFFFFF); + private static final ResolvedTextStyle TEXT_STYLE = LytChartBase.textStyle(ColorUtils.WHITE.getColor()); protected CornerLegendRenderer() {} @@ -70,7 +71,7 @@ public static void render(RenderContext context, LytRect plotRect, List newSlices) { slices.clear(); diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/AutoPointSpec.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/AutoPointSpec.java index 3138d76a..93b4adca 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/AutoPointSpec.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/AutoPointSpec.java @@ -1,6 +1,7 @@ package com.hfstudio.guidenh.guide.document.block.functiongraph; import com.github.bsideup.jabel.Desugar; +import com.hfstudio.guidenh.guide.color.ColorUtils; @Desugar public record AutoPointSpec(double everyX, double everyY, AutoPointLabelMode labelMode, int color, @@ -10,7 +11,7 @@ public record AutoPointSpec(double everyX, double everyY, AutoPointLabelMode lab Double.NaN, Double.NaN, AutoPointLabelMode.NONE, - 0xFFFFFFFF, + ColorUtils.WHITE.getColor(), true); public AutoPointSpec { diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/FunctionGraphPalette.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/FunctionGraphPalette.java index 77cee5bb..4808a951 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/FunctionGraphPalette.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/FunctionGraphPalette.java @@ -1,19 +1,18 @@ package com.hfstudio.guidenh.guide.document.block.functiongraph; +import com.hfstudio.guidenh.guide.color.ColorUtils; + /** * Deterministic palette used when {@link FunctionPlot} authors omit an explicit colour. Colours are * picked by plot index so re-rendering the same page does not flicker. */ public class FunctionGraphPalette { - private static final int[] COLORS = new int[] { 0xFFE15759, 0xFF4E79A7, 0xFF59A14F, 0xFFF28E2B, 0xFF76B7B2, - 0xFFB07AA1, 0xFFEDC948, 0xFF9C755F, 0xFFFF9DA7, 0xFF1F77B4, 0xFFFF7F0E, 0xFF2CA02C, 0xFFD62728, 0xFF9467BD }; - protected FunctionGraphPalette() {} public static int color(int index) { - int n = COLORS.length; + int n = ColorUtils.FUNCTION_GRAPH_PALETTE.length; int i = ((index % n) + n) % n; - return COLORS[i]; + return ColorUtils.getColor(ColorUtils.FUNCTION_GRAPH_PALETTE[i]); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/LytFunctionGraph.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/LytFunctionGraph.java index c784e539..dad1f23c 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/LytFunctionGraph.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/functiongraph/LytFunctionGraph.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Optional; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.block.LytBlock; @@ -66,10 +67,10 @@ public class LytFunctionGraph extends LytBlock implements InteractiveElement, Do private static final int MIN_PLOT_HEIGHT = 88; private static final float LABEL_LATEX_SOURCE_SCALE = 100f; - private static final ResolvedTextStyle TITLE_STYLE = makeStyle(0xFFE6E6E6, true); - private static final ResolvedTextStyle AXIS_LABEL_STYLE = makeStyle(0xFFB8C2CF, false); - private static final ResolvedTextStyle TOOLTIP_BODY_STYLE = makeStyle(0xFFD7DEE7, false); - private static final ResolvedTextStyle LEGEND_LABEL_STYLE = makeStyle(0xFFD7DEE7, false); + private static final ResolvedTextStyle TITLE_STYLE = makeStyle(ColorUtils.ARGB_FFE6E6E6.getColor(), true); + private static final ResolvedTextStyle AXIS_LABEL_STYLE = makeStyle(ColorUtils.CHART_LABEL.getColor(), false); + private static final ResolvedTextStyle TOOLTIP_BODY_STYLE = makeStyle(ColorUtils.ARGB_FFD7DEE7.getColor(), false); + private static final ResolvedTextStyle LEGEND_LABEL_STYLE = makeStyle(ColorUtils.ARGB_FFD7DEE7.getColor(), false); @Getter private final List plots = new ArrayList<>(); @@ -91,16 +92,16 @@ public class LytFunctionGraph extends LytBlock implements InteractiveElement, Do private int explicitHeight = -1; @Getter @Setter - private int backgroundColor = 0xFF1B1F23; + private int backgroundColor = ColorUtils.CHART_BACKGROUND.getColor(); @Getter @Setter - private int borderColor = 0xFF3A4047; + private int borderColor = ColorUtils.CHART_BORDER.getColor(); @Getter @Setter - private int axisColor = 0xFFB8C2CF; + private int axisColor = ColorUtils.CHART_LABEL.getColor(); @Getter @Setter - private int gridColor = 0x33B8C2CF; + private int gridColor = ColorUtils.CHART_GRID.getColor(); @Getter @Setter private boolean showGrid = true; @@ -646,7 +647,7 @@ private void renderMarkedPoints(RenderContext context, LytRect plotRect) { if (sy < plotRect.y() - POINT_RADIUS || sy > plotRect.bottom() + POINT_RADIUS) { continue; } - context.fillCircle(sx, sy, POINT_RADIUS + POINT_OUTER_RING, 0xFFFFFFFF); + context.fillCircle(sx, sy, POINT_RADIUS + POINT_OUTER_RING, ColorUtils.WHITE.getColor()); context.fillCircle(sx, sy, POINT_RADIUS, color); } } @@ -865,7 +866,7 @@ private boolean drawAutoPoint(RenderContext context, LytRect plotRect, double da return false; } autoPointHitCache.add(new double[] { sx, sy, dataX, dataY, (double) color, (double) plotIndex }); - context.fillCircle(sx, sy, POINT_RADIUS + POINT_OUTER_RING, 0xFFFFFFFF); + context.fillCircle(sx, sy, POINT_RADIUS + POINT_OUTER_RING, ColorUtils.WHITE.getColor()); context.fillCircle(sx, sy, POINT_RADIUS, color); if (labelMode != null && labelMode != AutoPointLabelMode.NONE) { String label = autoPointLabel(labelMode, dataX, dataY); @@ -943,7 +944,7 @@ private void renderActiveOverlay(RenderContext context, LytRect plotRect) { if (sx < plotRect.x() || sx > plotRect.right() || sy < plotRect.y() || sy > plotRect.bottom()) { return; } - context.fillCircle(sx, sy, POINT_RADIUS + POINT_OUTER_RING, 0xFFFFFFFF); + context.fillCircle(sx, sy, POINT_RADIUS + POINT_OUTER_RING, ColorUtils.WHITE.getColor()); context.fillCircle(sx, sy, POINT_RADIUS, plot.getColor()); } @@ -958,8 +959,8 @@ private void renderMarkedPointOverlay(RenderContext context, LytRect plotRect) { return; } // Larger highlight for marked points. - context.fillCircle(sx, sy, POINT_RADIUS + 2f, 0xFFFFFFFF); - context.drawCircleOutline(sx, sy, POINT_RADIUS + 2f, 1f, 0xFF000000); + context.fillCircle(sx, sy, POINT_RADIUS + 2f, ColorUtils.WHITE.getColor()); + context.drawCircleOutline(sx, sy, POINT_RADIUS + 2f, 1f, ColorUtils.BLACK.getColor()); context.fillCircle(sx, sy, POINT_RADIUS, color); } @@ -973,8 +974,8 @@ private void renderAutoPointOverlay(RenderContext context, LytRect plotRect) { if (sx < plotRect.x() || sx > plotRect.right() || sy < plotRect.y() || sy > plotRect.bottom()) { return; } - context.fillCircle(sx, sy, POINT_RADIUS + 2f, 0xFFFFFFFF); - context.drawCircleOutline(sx, sy, POINT_RADIUS + 2f, 1f, 0xFF000000); + context.fillCircle(sx, sy, POINT_RADIUS + 2f, ColorUtils.WHITE.getColor()); + context.drawCircleOutline(sx, sy, POINT_RADIUS + 2f, 1f, ColorUtils.BLACK.getColor()); context.fillCircle(sx, sy, POINT_RADIUS, color); } @@ -1120,7 +1121,7 @@ private void drawRichText(RenderContext context, String text, int x, int y, Reso int lineHeight = context.getLineHeight(style); int totalHeight = measureRichTextHeight(context, text, style); int cursorX = x; - int fillColor = style == TITLE_STYLE ? 0xFFE6E6E6 : 0xFFB8C2CF; + int fillColor = style == TITLE_STYLE ? ColorUtils.ARGB_FFE6E6E6.getColor() : ColorUtils.CHART_LABEL.getColor(); for (MarkdownLatexShorthand.Segment segment : MarkdownLatexShorthand.split(text)) { if (!segment.isFormula()) { context.drawText(segment.getValue(), cursorX, y + (totalHeight - lineHeight) / 2, style); @@ -1150,7 +1151,8 @@ private void drawRichText(RenderContext context, String text, int x, int y, Reso } private static LatexMetrics measureLatex(String formula, int lineHeight) { - int[] source = GuideLatexRenderer.INSTANCE.measureSize(formula, 0xFFFFFFFF, LABEL_LATEX_SOURCE_SCALE); + int[] source = GuideLatexRenderer.INSTANCE + .measureSize(formula, ColorUtils.WHITE.getColor(), LABEL_LATEX_SOURCE_SCALE); if (source == null) { return null; } @@ -1289,7 +1291,7 @@ private void renderLegend(RenderContext context, int left, int top, int availabl int swatchY = y + (rowHeight - LEGEND_SWATCH_SIZE) / 2; LytRect swatch = new LytRect(x, swatchY, LEGEND_SWATCH_SIZE, LEGEND_SWATCH_SIZE); context.fillRect(swatch, plot.getColor()); - context.drawBorder(swatch, 0xFF000000, 1); + context.drawBorder(swatch, ColorUtils.BLACK.getColor(), 1); int textY = y + (rowHeight - context.getLineHeight(LEGEND_LABEL_STYLE)) / 2; context.drawText(label, x + LEGEND_SWATCH_SIZE + LEGEND_SWATCH_TEXT_GAP, textY, LEGEND_LABEL_STYLE); x += itemWidth; diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/recipes/LytGenericRecipeBox.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/recipes/LytGenericRecipeBox.java index 5878df27..1412acad 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/recipes/LytGenericRecipeBox.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/recipes/LytGenericRecipeBox.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.DefaultStyles; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.block.LytBox; @@ -16,7 +17,7 @@ public class LytGenericRecipeBox extends LytBox { public static final int TITLE_HEIGHT = 10; - public static final int TITLE_COLOR = 0xFFAAAAAA; + public static final int TITLE_COLOR = ColorUtils.ARGB_FFAAAAAA.getColor(); public static final int SLOT_INSET = (LytSlot.OUTER_SIZE - 16) / 2; private final String title; diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/block/table/LytTable.java b/src/main/java/com/hfstudio/guidenh/guide/document/block/table/LytTable.java index 3ffc890d..5fa1a8f2 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/block/table/LytTable.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/block/table/LytTable.java @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.block.LytBlock; import com.hfstudio.guidenh.guide.layout.LayoutContext; @@ -67,12 +67,12 @@ public void render(RenderContext context) { for (int i = 0; i < columns.size() - 1; i++) { var column = columns.get(i); var colRight = column.x + column.width; - context.fillRect(colRight, bounds.y(), 1, bounds.height(), SymbolicColor.TABLE_BORDER); + context.fillRect(colRight, bounds.y(), 1, bounds.height(), ColorUtils.TABLE_BORDER); } for (int i = 0; i < rows.size() - 1; i++) { var row = rows.get(i); - context.fillRect(bounds.x(), row.bounds.bottom(), bounds.width(), 1, SymbolicColor.TABLE_BORDER); + context.fillRect(bounds.x(), row.bounds.bottom(), bounds.width(), 1, ColorUtils.TABLE_BORDER); } for (var row : rows) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/document/flow/LytFlowLink.java b/src/main/java/com/hfstudio/guidenh/guide/document/flow/LytFlowLink.java index b637b9f6..c3ba65fe 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/document/flow/LytFlowLink.java +++ b/src/main/java/com/hfstudio/guidenh/guide/document/flow/LytFlowLink.java @@ -9,7 +9,7 @@ import com.hfstudio.guidenh.guide.GuideAnchor; import com.hfstudio.guidenh.guide.PageAnchor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.sound.GuideSoundPlayback; import com.hfstudio.guidenh.guide.sound.GuideSoundSpec; import com.hfstudio.guidenh.guide.ui.GuideUiHost; @@ -30,7 +30,7 @@ public class LytFlowLink extends LytTooltipSpan { private boolean playedCustomClickSound; public LytFlowLink() { - modifyStyle(style -> style.color(SymbolicColor.LINK)); + modifyStyle(style -> style.color(ColorUtils.LINK)); modifyHoverStyle(style -> style.underlined(true)); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorActionContext.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorActionContext.java new file mode 100644 index 00000000..d3fd8fa4 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorActionContext.java @@ -0,0 +1,48 @@ +package com.hfstudio.guidenh.guide.editor; + +import com.hfstudio.guidenh.guide.internal.editor.SceneEditorSession; + +/** + * The client-side operations and state that GuideNH exposes to a registered Scene Editor action. + * + *

+ * The context is valid only while the action is being invoked. Actions should use the supplied + * session and operations instead of retaining the context or reaching into the editor screen. Calls + * are expected to run on the Minecraft client thread, which is also the thread that owns the editor + * UI and preview world. + *

+ */ +public interface SceneEditorActionContext { + + /** Returns the current editor session, including the document and scene selection state. */ + SceneEditorSession session(); + + /** Returns the editor viewport width in screen pixels. */ + int width(); + + /** Returns the editor viewport height in screen pixels. */ + int height(); + + /** Rebuilds the scene preview from the current editor document. */ + void rebuildPreview(); + + /** Saves the current editor document through the editor's normal save path. */ + void save(); + + /** Exports the current scene as SNBT and applies the configured post-export folder behavior. */ + default void exportSnbt() { + save(); + } + + /** Copies the current scene as a {@code GameScene} document fragment. */ + void copyGameScene(); + + /** Copies the currently selected block as a {@code BlockImage} document fragment. */ + void copyBlockImage(); + + /** Opens the folder containing the current scene export destination. */ + void openExportFolder(); + + /** Closes the active editor dropdowns and transient menus. */ + void closeMenus(); +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorIcon.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorIcon.java new file mode 100644 index 00000000..6b012e36 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorIcon.java @@ -0,0 +1,76 @@ +package com.hfstudio.guidenh.guide.editor; + +import java.util.Objects; + +import net.minecraft.util.ResourceLocation; + +/** + * Identifies a rectangular sprite in a texture atlas used by a Scene Editor toolbar button. + * + *

+ * All source coordinates and dimensions are measured in atlas pixels. The atlas dimensions are + * supplied separately because the renderer uses them to convert the source rectangle to texture + * coordinates; they do not imply that the resource must be a particular image size. + *

+ */ +public class SceneEditorIcon { + + protected ResourceLocation texture; + protected int textureWidth; + protected int textureHeight; + protected int sourceX; + protected int sourceY; + protected int sourceWidth; + protected int sourceHeight; + + protected SceneEditorIcon() {} + + public SceneEditorIcon(ResourceLocation texture, int textureWidth, int textureHeight, int sourceX, int sourceY, + int sourceWidth, int sourceHeight) { + this.texture = Objects.requireNonNull(texture, "texture"); + if (textureWidth <= 0 || textureHeight <= 0 || sourceWidth <= 0 || sourceHeight <= 0) { + throw new IllegalArgumentException("Icon dimensions must be positive"); + } + this.textureWidth = textureWidth; + this.textureHeight = textureHeight; + this.sourceX = sourceX; + this.sourceY = sourceY; + this.sourceWidth = sourceWidth; + this.sourceHeight = sourceHeight; + } + + /** Returns the texture resource containing this sprite. */ + public ResourceLocation texture() { + return texture; + } + + /** Returns the full texture width in pixels used for UV conversion. */ + public int textureWidth() { + return textureWidth; + } + + /** Returns the full texture height in pixels used for UV conversion. */ + public int textureHeight() { + return textureHeight; + } + + /** Returns the sprite's left coordinate in the texture atlas. */ + public int sourceX() { + return sourceX; + } + + /** Returns the sprite's top coordinate in the texture atlas. */ + public int sourceY() { + return sourceY; + } + + /** Returns the sprite width in atlas pixels. */ + public int sourceWidth() { + return sourceWidth; + } + + /** Returns the sprite height in atlas pixels. */ + public int sourceHeight() { + return sourceHeight; + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuItem.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuItem.java new file mode 100644 index 00000000..4b688913 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuItem.java @@ -0,0 +1,107 @@ +package com.hfstudio.guidenh.guide.editor; + +import java.util.Objects; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * Describes one item contributed to a registered Scene Editor dropdown menu. + * + *

+ * An item is identified by its id within the menu it is registered under. The registry evaluates + * the visibility and enabled suppliers when it builds a menu, orders visible items by {@link #order()}, + * and invokes {@link #activate(SceneEditorActionContext)} for an accepted interaction. A non-null + * checked supplier makes the item a checkable menu entry; a non-null {@link #widget()} replaces the + * normal text-only interaction with an embedded control while retaining the item's registration and + * enabled state. + *

+ * + *

+ * Suppliers and the action may be evaluated on the client thread more than once. Implementations + * should therefore keep them side-effect free except for the action itself, and should use the action + * context for all editor state changes. + *

+ */ +public class SceneEditorMenuItem { + + protected String id; + protected Supplier label; + protected int order; + protected BooleanSupplier visible; + protected BooleanSupplier enabled; + protected BooleanSupplier checked; + protected boolean checkBox; + protected SceneEditorMenuWidget widget; + protected Consumer action; + + protected SceneEditorMenuItem() {} + + public SceneEditorMenuItem(String id, Supplier label, Consumer action) { + this(id, label, 0, () -> true, () -> true, null, null, action); + } + + public SceneEditorMenuItem(String id, Supplier label, int order, BooleanSupplier visible, + BooleanSupplier enabled, BooleanSupplier checked, Consumer action) { + this(id, label, order, visible, enabled, checked, null, action); + } + + public SceneEditorMenuItem(String id, Supplier label, int order, BooleanSupplier visible, + BooleanSupplier enabled, BooleanSupplier checked, SceneEditorMenuWidget widget, + Consumer action) { + this.id = SceneEditorToolbarButton.requireId(id); + this.label = Objects.requireNonNull(label, "label"); + this.order = order; + this.visible = Objects.requireNonNull(visible, "visible"); + this.enabled = Objects.requireNonNull(enabled, "enabled"); + this.checked = checked; + this.checkBox = checked != null; + this.widget = widget; + this.action = Objects.requireNonNull(action, "action"); + } + + public String id() { + return id; + } + + public String label() { + String value = label.get(); + return value == null ? id : value; + } + + public int order() { + return order; + } + + public boolean visible() { + return visible.getAsBoolean(); + } + + public boolean enabled() { + return enabled.getAsBoolean(); + } + + public boolean checked() { + return checked != null && checked.getAsBoolean(); + } + + public boolean hasCheckBox() { + return checkBox; + } + + public SceneEditorMenuWidget widget() { + return widget; + } + + public void activate(SceneEditorActionContext context) { + action.accept(context); + } + + public void triggerClick(SceneEditorActionContext context) { + activate(context); + } + + public void triggerSelection(SceneEditorActionContext context) { + activate(context); + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuRegistry.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuRegistry.java new file mode 100644 index 00000000..2eb7b5d8 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuRegistry.java @@ -0,0 +1,59 @@ +package com.hfstudio.guidenh.guide.editor; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Global registry for contributions to the Scene Editor's named dropdown menus. + * + *

+ * Menu ids identify existing editor menus; registering an item does not create a new visual menu. + * An item id must be unique within its menu. {@link #snapshot(String)} returns a new immutable, + * order-sorted list containing only items visible at the time of the call, so callers may safely + * render it without holding the registry lock. + *

+ */ +public class SceneEditorMenuRegistry { + + public static final String MENU_EXPORT = "export"; + public static final String MENU_SNAP = "snap"; + + private static final Object LOCK = new Object(); + private static final Map ITEMS = new ConcurrentHashMap<>(); + + /** Registers an item and returns a handle that removes that exact contribution when closed. */ + public static SceneEditorRegistration register(String menuId, SceneEditorMenuItem item) { + if (menuId == null || menuId.trim() + .isEmpty()) throw new IllegalArgumentException("menuId must not be blank"); + if (item == null) throw new NullPointerException("item"); + String key = menuId + "\n" + SceneEditorToolbarButton.requireId(item.id()); + synchronized (LOCK) { + if (ITEMS.putIfAbsent(key, item) != null) { + throw new IllegalArgumentException("Scene Editor menu id already registered: " + key); + } + } + return () -> ITEMS.remove(key, item); + } + + /** Returns the currently visible items for a menu, sorted by order and then id. */ + public static List snapshot(String menuId) { + synchronized (LOCK) { + List result = new ArrayList<>(); + String prefix = menuId + "\n"; + for (Map.Entry entry : ITEMS.entrySet()) { + if (entry.getKey() + .startsWith(prefix) + && entry.getValue() + .visible()) + result.add(entry.getValue()); + } + result.sort( + Comparator.comparingInt(SceneEditorMenuItem::order) + .thenComparing(SceneEditorMenuItem::id)); + return List.copyOf(result); + } + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuWidget.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuWidget.java new file mode 100644 index 00000000..7451c425 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuWidget.java @@ -0,0 +1,60 @@ +package com.hfstudio.guidenh.guide.editor; + +/** + * Client-side rendering and input contract for an embedded control in a Scene Editor menu item. + * + *

+ * The editor allocates one row for the widget and calls {@link #render(SceneEditorMenuWidgetContext, int, int, + * int, int, boolean, boolean)} with the row's pixel bounds. The widget owns its visual state and decides whether + * a mouse event belongs to the control. Returning {@code true} from {@link #mouseClicked(SceneEditorActionContext, + * int, int, int, int, int, int, int)} or {@link #mouseDragged(SceneEditorActionContext, int, int, int, int, int, + * int, int)} consumes that event and prevents the menu from handling it as a regular item. + *

+ * + *

+ * Override {@link #height()} and {@link #preferredWidth()} when the control needs more space than the default + * row. The default {@link #triggerClick(SceneEditorActionContext, int, int, int, int, int, int, int)} and + * {@link #triggerDrag(SceneEditorActionContext, int, int, int, int, int, int, int)} methods deliberately delegate + * to the corresponding mouse methods so custom controls can expose the same behavior to programmatic menu actions. + *

+ */ +public interface SceneEditorMenuWidget { + + /** Returns the pixel height reserved for this widget's menu row. */ + default int height() { + return 18; + } + + /** Returns a preferred row width, or zero when the menu may choose the width. */ + default int preferredWidth() { + return 0; + } + + /** Draws the widget for the supplied row bounds and current hover/enabled state. */ + void render(SceneEditorMenuWidgetContext context, int x, int y, int width, int height, boolean hovered, + boolean enabled); + + /** Handles a mouse click and returns whether the widget consumed it. */ + default boolean mouseClicked(SceneEditorActionContext actionContext, int x, int y, int width, int height, + int mouseX, int mouseY, int button) { + return false; + } + + /** Handles a mouse drag and returns whether the widget consumed it. */ + default boolean mouseDragged(SceneEditorActionContext actionContext, int x, int y, int width, int height, + int mouseX, int mouseY, int button) { + return false; + } + + /** Programmatically dispatches a click using the same path as a mouse click. */ + default boolean triggerClick(SceneEditorActionContext actionContext, int x, int y, int width, int height, + int mouseX, int mouseY, int button) { + return mouseClicked(actionContext, x, y, width, height, mouseX, mouseY, button); + } + + /** Programmatically dispatches a drag using the same path as a mouse drag. */ + default boolean triggerDrag(SceneEditorActionContext actionContext, int x, int y, int width, int height, int mouseX, + int mouseY, int button) { + return mouseDragged(actionContext, x, y, width, height, mouseX, mouseY, button); + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuWidgetContext.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuWidgetContext.java new file mode 100644 index 00000000..d914f3b4 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorMenuWidgetContext.java @@ -0,0 +1,31 @@ +package com.hfstudio.guidenh.guide.editor; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; + +/** + * Rendering services supplied by the Scene Editor to a {@link SceneEditorMenuWidget}. + * + *

+ * The context is created for a menu draw pass and provides the client font renderer, Minecraft + * instance, and the primitive operations permitted to a registered widget. Coordinates passed to + * drawing methods are screen pixels in the widget's menu coordinate space. + *

+ */ +public interface SceneEditorMenuWidgetContext { + + /** Returns the active Minecraft client instance. */ + Minecraft minecraft(); + + /** Returns the font renderer used by the editor menu. */ + FontRenderer fontRenderer(); + + /** Draws a filled, half-open rectangle. */ + void drawRect(int left, int top, int right, int bottom, int color); + + /** Draws a one-pixel border around a rectangle. */ + void drawBorder(int left, int top, int width, int height, int color); + + /** Draws a string at the supplied pixel position. */ + void drawString(String text, int x, int y, int color); +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorRegistration.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorRegistration.java new file mode 100644 index 00000000..7753c380 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorRegistration.java @@ -0,0 +1,17 @@ +package com.hfstudio.guidenh.guide.editor; + +/** + * Reversible handle for one Scene Editor toolbar or dropdown registration. + * + *

+ * Calling {@link #close()} removes the exact registered object from its registry. The operation + * is safe to call more than once and does not affect a later registration that reuses the same id. + * Extensions should retain this handle for their own lifecycle cleanup. + *

+ */ +public interface SceneEditorRegistration extends AutoCloseable { + + /** Unregisters the associated contribution. */ + @Override + void close(); +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorSliderWidget.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorSliderWidget.java new file mode 100644 index 00000000..d208c211 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorSliderWidget.java @@ -0,0 +1,94 @@ +package com.hfstudio.guidenh.guide.editor; + +import java.util.function.DoubleConsumer; +import java.util.function.DoubleSupplier; + +import com.hfstudio.guidenh.guide.color.ColorUtils; + +/** + * Reusable horizontal slider implementation for a registered Scene Editor dropdown item. + * + *

+ * The value supplier is read during rendering and the consumer is called with a clamped value + * whenever the track is clicked or dragged. Slider coordinates are expressed in the row supplied by + * the menu; subclasses may override the sizing and hit-test methods to provide a different layout. + *

+ */ +public class SceneEditorSliderWidget implements SceneEditorMenuWidget { + + protected DoubleSupplier value; + protected DoubleConsumer valueConsumer; + protected double minimum; + protected double maximum; + protected String label; + + /** Creates a slider whose emitted values are clamped to the inclusive minimum/maximum range. */ + public SceneEditorSliderWidget(DoubleSupplier value, DoubleConsumer valueConsumer, double minimum, double maximum, + String label) { + if (minimum > maximum) throw new IllegalArgumentException("minimum must not exceed maximum"); + this.value = value; + this.valueConsumer = valueConsumer; + this.minimum = minimum; + this.maximum = maximum; + this.label = label == null ? "" : label; + } + + /** Returns the pixel height reserved for this slider row. */ + @Override + public int height() { + return 26; + } + + /** Returns the preferred pixel width for this slider row. */ + @Override + public int preferredWidth() { + return 150; + } + + @Override + public void render(SceneEditorMenuWidgetContext context, int x, int y, int width, int height, boolean hovered, + boolean enabled) { + int color = enabled ? ColorUtils.PANEL_MUTED_TEXT.getColor() : ColorUtils.ARGB_FF737A82.getColor(); + context.drawString(label, x + 6, y + 3, color); + int trackY = y + 16; + int trackLeft = x + 6; + int trackRight = x + width - 6; + context.drawRect(trackLeft, trackY, trackRight, trackY + 3, ColorUtils.INPUT_BORDER.getColor()); + double current = value.getAsDouble(); + double fraction = maximum <= minimum ? 0d : (current - minimum) / (maximum - minimum); + fraction = Math.max(0d, Math.min(1d, fraction)); + int thumbX = trackLeft + (int) Math.round((trackRight - trackLeft) * fraction); + context.drawRect( + thumbX - 2, + trackY - 2, + thumbX + 3, + trackY + 5, + enabled ? ColorUtils.ACCENT.getColor() : ColorUtils.ARGB_FF737A82.getColor()); + } + + @Override + public boolean mouseClicked(SceneEditorActionContext actionContext, int x, int y, int width, int height, int mouseX, + int mouseY, int button) { + if (button != 0 || !insideTrack(x, y, width, height, mouseX, mouseY)) return false; + applyAt(x, width, mouseX); + return true; + } + + @Override + public boolean mouseDragged(SceneEditorActionContext actionContext, int x, int y, int width, int height, int mouseX, + int mouseY, int button) { + if (button != 0) return false; + applyAt(x, width, mouseX); + return true; + } + + protected boolean insideTrack(int x, int y, int width, int height, int mouseX, int mouseY) { + return mouseX >= x + 2 && mouseX < x + width - 2 && mouseY >= y + 12 && mouseY < y + height; + } + + protected void applyAt(int x, int width, int mouseX) { + double fraction = (mouseX - (x + 6d)) / Math.max(1d, width - 12d); + fraction = Math.max(0d, Math.min(1d, fraction)); + valueConsumer.accept(minimum + (maximum - minimum) * fraction); + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorToolbarButton.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorToolbarButton.java new file mode 100644 index 00000000..835916e3 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorToolbarButton.java @@ -0,0 +1,116 @@ +package com.hfstudio.guidenh.guide.editor; + +import java.util.Objects; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * Describes a toolbar button contributed to the Scene Editor. + * + *

+ * The button is identified by a unique id, displayed with an atlas {@link SceneEditorIcon}, and + * sorted with its order value after built-in controls. Visibility and enabled state are evaluated when + * the toolbar is laid out or interacted with. When {@code menuId} is non-null, clicking the button + * opens that dropdown menu instead of requiring the action to perform the menu behavior itself. + *

+ * + *

+ * Registered actions run on the client thread and receive the current {@link SceneEditorActionContext}. + * Suppliers may be evaluated repeatedly and should not mutate editor state. + *

+ */ +public class SceneEditorToolbarButton { + + protected String id; + protected Supplier label; + protected SceneEditorIcon icon; + protected String menuId; + protected int order; + protected BooleanSupplier visible; + protected BooleanSupplier enabled; + protected Consumer action; + + protected SceneEditorToolbarButton() {} + + public SceneEditorToolbarButton(String id, Supplier label, SceneEditorIcon icon, + Consumer action) { + this(id, label, icon, null, 0, () -> true, () -> true, action); + } + + public SceneEditorToolbarButton(String id, Supplier label, SceneEditorIcon icon, BooleanSupplier enabled, + Consumer action) { + this(id, label, icon, null, 0, () -> true, enabled, action); + } + + public SceneEditorToolbarButton(String id, Supplier label, SceneEditorIcon icon, int order, + BooleanSupplier visible, BooleanSupplier enabled, Consumer action) { + this(id, label, icon, null, order, visible, enabled, action); + } + + public SceneEditorToolbarButton(String id, Supplier label, SceneEditorIcon icon, String menuId, int order, + BooleanSupplier visible, BooleanSupplier enabled, Consumer action) { + this.id = requireId(id); + this.label = Objects.requireNonNull(label, "label"); + this.icon = Objects.requireNonNull(icon, "icon"); + this.menuId = menuId; + this.order = order; + this.visible = Objects.requireNonNull(visible, "visible"); + this.enabled = Objects.requireNonNull(enabled, "enabled"); + this.action = Objects.requireNonNull(action, "action"); + } + + /** Returns this button's registry-unique identifier. */ + public String id() { + return id; + } + + /** Resolves and returns the current display label, falling back to the id when the supplier returns null. */ + public String label() { + String value = label.get(); + return value == null ? id : value; + } + + /** Returns the texture-atlas sprite rendered for this button. */ + public SceneEditorIcon icon() { + return icon; + } + + /** Returns the dropdown menu id opened by this button, or null for a direct action. */ + public String menuId() { + return menuId; + } + + /** Returns the relative ordering among contributed toolbar buttons. */ + public int order() { + return order; + } + + /** Returns whether this button should currently be included in the toolbar. */ + public boolean visible() { + return visible.getAsBoolean(); + } + + /** Returns whether this button currently accepts clicks. */ + public boolean enabled() { + return enabled.getAsBoolean(); + } + + /** Invokes the contributed action with the supplied editor context. */ + public void activate(SceneEditorActionContext context) { + action.accept(context); + } + + /** Dispatches a toolbar click to the contributed action. */ + public void triggerClick(SceneEditorActionContext context) { + activate(context); + } + + protected static String requireId(String id) { + if (id == null || id.trim() + .isEmpty()) { + throw new IllegalArgumentException("Scene Editor registration id must not be blank"); + } + return id; + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorToolbarRegistry.java b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorToolbarRegistry.java new file mode 100644 index 00000000..c40852a7 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/editor/SceneEditorToolbarRegistry.java @@ -0,0 +1,53 @@ +package com.hfstudio.guidenh.guide.editor; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Global registry for toolbar buttons contributed to the Scene Editor. + * + *

+ * Contributions are keyed by button id and are independent of the lifetime of an individual + * editor screen. The screen obtains a fresh immutable snapshot for each layout pass; registrations + * can therefore be added or removed while no screen is open without retaining screen instances. + *

+ */ +public class SceneEditorToolbarRegistry { + + private static final Object LOCK = new Object(); + private static final Map BUTTONS = new ConcurrentHashMap<>(); + private static final AtomicInteger BUTTON_IDS = new AtomicInteger(-1000); + + /** Registers a button and returns a handle that removes that exact contribution when closed. */ + public static SceneEditorRegistration register(SceneEditorToolbarButton button) { + if (button == null) throw new NullPointerException("button"); + String id = SceneEditorToolbarButton.requireId(button.id()); + synchronized (LOCK) { + if (BUTTONS.putIfAbsent(id, button) != null) { + throw new IllegalArgumentException("Scene Editor toolbar id already registered: " + id); + } + } + return () -> BUTTONS.remove(id, button); + } + + /** Returns visible buttons sorted by order and then id. */ + public static List snapshot() { + synchronized (LOCK) { + List result = new ArrayList<>(BUTTONS.values()); + result.removeIf(button -> !button.visible()); + result.sort( + Comparator.comparingInt(SceneEditorToolbarButton::order) + .thenComparing(SceneEditorToolbarButton::id)); + return List.copyOf(result); + } + } + + /** Returns a negative id suitable for editor-owned transient button widgets. */ + public static int nextButtonId() { + return BUTTON_IDS.getAndDecrement(); + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreen.java b/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreen.java index 259d057e..451d4911 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreen.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreen.java @@ -57,9 +57,7 @@ import com.hfstudio.guidenh.guide.GuidePage; import com.hfstudio.guidenh.guide.GuidePageIcon; import com.hfstudio.guidenh.guide.PageAnchor; -import com.hfstudio.guidenh.guide.color.Colors; -import com.hfstudio.guidenh.guide.color.LightDarkMode; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.AnchorIndexer; import com.hfstudio.guidenh.guide.compiler.Frontmatter; import com.hfstudio.guidenh.guide.compiler.FrontmatterPageMeta; @@ -161,8 +159,8 @@ public class GuideScreen extends GuiContainer public static final int PANEL_MARGIN = 20; public static final int PANEL_PADDING = 8; - public static final int BG_COLOR = 0xE0101010; - public static final int BG_BORDER = 0xFF5A5A5A; + public static final int BG_COLOR = ColorUtils.ARGB_E0101010.getColor(); + public static final int BG_BORDER = ColorUtils.PANEL_BORDER.getColor(); public static final ResourceLocation BG_TEXTURE = new ResourceLocation( "guidenh", @@ -171,7 +169,7 @@ public class GuideScreen extends GuiContainer public static final String HOME_LOGO_RESOURCE_PATH = "/assets/logo.png"; public static float BACKGROUND_ALPHA = 0.7f; - public static int BACKGROUND_DIM_COLOR = 0x34101018; + public static int BACKGROUND_DIM_COLOR = ColorUtils.ARGB_34101018.getColor(); @Nullable private static ResourceLocation homeLogoTexture; @@ -257,7 +255,7 @@ private static LytDocument buildLoadingDocument() { LytParagraph para = new LytParagraph(); para.setStyle( TextStyle.builder() - .color(SymbolicColor.GRAY) + .color(ColorUtils.MC_GRAY) .build()); para.appendText("Loading..."); doc.append(para); @@ -278,14 +276,8 @@ private static LytDocument buildLoadingDocument() { private final GuideScreenEditorFileStore guideEditorFileStore = GuideScreenEditorFileStore.createDefault(); private final Map guideEditorActionButtons = new LinkedHashMap<>(); - private final VanillaRenderContext reusableRenderCtx = new VanillaRenderContext( - LightDarkMode.LIGHT_MODE, - LytRect.empty(), - 0); - private final VanillaRenderContext reusableContentTooltipCtx = new VanillaRenderContext( - LightDarkMode.LIGHT_MODE, - LytRect.empty(), - 0); + private final VanillaRenderContext reusableRenderCtx = new VanillaRenderContext(LytRect.empty(), 0); + private final VanillaRenderContext reusableContentTooltipCtx = new VanillaRenderContext(LytRect.empty(), 0); // Reuse rect records on hot render paths when geometry has not changed. @Nullable private LytRect cachedViewportRect; @@ -2893,7 +2885,12 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawRect(panelX, panelY, panelX + panelW, panelY + panelH, BG_COLOR); drawBorder(panelX, panelY, panelW, panelH, BG_BORDER); - drawRect(panelX, panelY + TOOLBAR_H, panelX + panelW, panelY + TOOLBAR_H + 1, 0xFF2A2A2A); + drawRect( + panelX, + panelY + TOOLBAR_H, + panelX + panelW, + panelY + TOOLBAR_H + 1, + ColorUtils.ARGB_FF2A2A2A.getColor()); if (!isHomeRoute() && !isGuideEditorActive()) { updateSceneHover(contentMouseX, contentMouseY); @@ -2929,7 +2926,12 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawSpecialSearchField(); } drawRect(panelX, panelY, panelX + panelW, panelY + TOOLBAR_H, BG_COLOR); - drawRect(panelX, panelY + TOOLBAR_H, panelX + panelW, panelY + TOOLBAR_H + 1, 0xFF2A2A2A); + drawRect( + panelX, + panelY + TOOLBAR_H, + panelX + panelW, + panelY + TOOLBAR_H + 1, + ColorUtils.ARGB_FF2A2A2A.getColor()); drawPageTitle(); if (searchField != null) { drawSearchField(); @@ -3070,7 +3072,7 @@ private void drawBottomBar() { int barY = panelY + panelH - TOOLBAR_H; drawRect(panelX, barY, panelX + panelW, panelY + panelH, BG_COLOR); - drawRect(panelX, barY, panelX + panelW, barY + 1, 0xFF2A2A2A); + drawRect(panelX, barY, panelX + panelW, barY + 1, ColorUtils.ARGB_FF2A2A2A.getColor()); FontRenderer fr = mc.fontRenderer; if (cachedBottomBarText == null || cachedBottomBarPage != currentPage || cachedBottomBarWidth != this.width) { @@ -3085,7 +3087,7 @@ private void drawBottomBar() { int textW = fr.getStringWidth(text); int textX = textRightX - textW; int textY = barY + (TOOLBAR_H - fr.FONT_HEIGHT) / 2 + 1; - fr.drawString(text, textX, textY, 0xFFAAAAAA, false); + fr.drawString(text, textX, textY, ColorUtils.ARGB_FFAAAAAA.getColor(), false); } private void drawHomeContent(int mouseX, int mouseY) { @@ -3180,13 +3182,14 @@ private void drawGuideEditorScreen(int mouseX, int mouseY) { private int resolveGuideEditorDividerColor() { if (guideEditorDraggingDivider) { - return 0xFF5EA8FF; + return ColorUtils.ARGB_FF5EA8FF.getColor(); } if (guideEditorDividerHoverStartedAtMillis <= 0L) { - return 0xFF4A4A4A; + return ColorUtils.ARGB_FF4A4A4A.getColor(); } long elapsed = System.currentTimeMillis() - guideEditorDividerHoverStartedAtMillis; - return elapsed >= GUIDE_EDITOR_DIVIDER_HOVER_DELAY_MILLIS ? 0xFF5EA8FF : 0xFF4A4A4A; + return elapsed >= GUIDE_EDITOR_DIVIDER_HOVER_DELAY_MILLIS ? ColorUtils.ARGB_FF5EA8FF.getColor() + : ColorUtils.ARGB_FF4A4A4A.getColor(); } private void updateGuideEditorPreviewHover(int mouseX, int mouseY) { @@ -3331,7 +3334,6 @@ private void renderGuideEditorPreview(int x, int y, int width, int height) { layoutWidth, renderHeight); cachedPreviewScissor = cachedRect(cachedPreviewScissor, x, y, renderWidth, renderHeight); - reusableRenderCtx.setLightDarkMode(LightDarkMode.LIGHT_MODE); reusableRenderCtx.setViewport(cachedPreviewViewport); reusableRenderCtx.setScreenHeight(this.height); reusableRenderCtx.setDocumentOrigin(x, y); @@ -3352,7 +3354,7 @@ private void renderGuideEditorPreview(int x, int y, int width, int height) { reusableRenderCtx.restoreExternalRenderState(); GL11.glDisable(GL11.GL_SCISSOR_TEST); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } drawGuideEditorPreviewScrollbar( x + renderWidth - SCROLLBAR_W, @@ -3366,12 +3368,12 @@ private void drawGuideEditorPreviewScrollbar(int barX, int barY, int barH, int c return; } int barW = SCROLLBAR_W; - drawRect(barX, barY, barX + barW, barY + barH, 0x35101010); + drawRect(barX, barY, barX + barW, barY + barH, ColorUtils.SCROLLBAR_TRACK.getColor()); int thumbH = Math.max(16, (int) ((long) barH * barH / contentH)); int maxScroll = Math.max(0, contentH - barH); int thumbY = maxScroll > 0 ? barY + (int) ((long) (barH - thumbH) * guideEditorPreviewScrollY / maxScroll) : barY; - drawRect(barX, thumbY, barX + barW, thumbY + thumbH, 0xA0D8D8D8); + drawRect(barX, thumbY, barX + barW, thumbY + thumbH, ColorUtils.SCROLLBAR_THUMB.getColor()); } private boolean handleGuideEditorKey(char typedChar, int keyCode) { @@ -3619,7 +3621,7 @@ private boolean handleGuideEditorMouseReleased(int mouseX, int mouseY, int state return false; } - private boolean handleGuideEditorWheel(int mouseX, int mouseY, int dwheel) { + public boolean handleGuideEditorWheel(int mouseX, int mouseY, int dwheel) { if (!isGuideEditorActive()) { return false; } @@ -3635,6 +3637,9 @@ private boolean handleGuideEditorWheel(int mouseX, int mouseY, int dwheel) { return true; } if (isInsideGuideEditorPreview(mouseX, mouseY)) { + if (handleGuideEditorPreviewSceneWheel(mouseX, mouseY, dwheel)) { + return true; + } scrollGuideEditorPreview(dwheel); syncGuideEditorEditorScrollFromPreview(); return true; @@ -3642,7 +3647,18 @@ private boolean handleGuideEditorWheel(int mouseX, int mouseY, int dwheel) { return false; } - private void updateGuideEditorDividerFromMouse(int mouseX) { + public boolean handleGuideEditorPreviewSceneWheel(int mouseX, int mouseY, int dwheel) { + DocumentInteractionState interaction = getGuideEditorPreviewInteractionState(mouseX, mouseY); + LytGuidebookScene scene = interaction != null ? interaction.scene : null; + if (scene == null || !scene.isInteractive() + || !(scene.containsBottomControlSlider(mouseX, mouseY) || ModConfig.ui.sceneWheelZoom)) { + return false; + } + scene.scroll(mouseX, mouseY, dwheel); + return true; + } + + public void updateGuideEditorDividerFromMouse(int mouseX) { if (guideEditorLayoutMode != GuideScreenEditorLayoutMode.SPLIT) { return; } @@ -4158,7 +4174,6 @@ private void drawPageTitle() { var ctx = reusableContentTooltipCtx; cachedTitleViewport = cachedRect(cachedTitleViewport, 0, 0, availableW, Math.max(titleH, TOOLBAR_H)); - ctx.setLightDarkMode(LightDarkMode.LIGHT_MODE); ctx.setViewport(cachedTitleViewport); ctx.setScreenHeight(this.height); ctx.setDocumentOrigin(titleX, titleY); @@ -4172,7 +4187,7 @@ private void drawPageTitle() { ctx.restoreExternalRenderState(); GL11.glDisable(GL11.GL_SCISSOR_TEST); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } @@ -4424,9 +4439,9 @@ private void drawContentTooltip(ContentTooltip ct, int mouseX, int mouseY, GL11.glDisable(GL11.GL_DEPTH_TEST); this.zLevel = 300.0F; itemRender.zLevel = 300.0F; - int ctBgColor = 0xF0100010; - int ctBorderTop = 0x505000FF; - int ctBorderBottom = 0x5028007F; + int ctBgColor = ColorUtils.ARGB_F0100010.getColor(); + int ctBorderTop = ColorUtils.ARGB_505000FF.getColor(); + int ctBorderBottom = ColorUtils.ARGB_5028007F.getColor(); drawGradientRect(x - pad, y - pad, x + w + pad, y + h + pad, ctBgColor, ctBgColor); drawGradientRect(x - pad, y - pad - 1, x + w + pad, y - pad, ctBgColor, ctBgColor); drawGradientRect(x - pad, y + h + pad, x + w + pad, y + h + pad + 1, ctBgColor, ctBgColor); @@ -4439,7 +4454,6 @@ private void drawContentTooltip(ContentTooltip ct, int mouseX, int mouseY, var ctx = reusableContentTooltipCtx; cachedContentTooltipViewport = cachedRect(cachedContentTooltipViewport, 0, 0, w, h); - ctx.setLightDarkMode(LightDarkMode.LIGHT_MODE); ctx.setViewport(cachedContentTooltipViewport); ctx.setScreenHeight(this.height); ctx.setDocumentOrigin(x, y); @@ -4643,7 +4657,6 @@ private void renderDocument(int mouseX, int mouseY) { var interaction = getDocumentInteractionState(mouseX, mouseY); activeDocument.setHoveredElement(interaction != null ? interaction.hit : null); var ctx = reusableRenderCtx; - ctx.setLightDarkMode(LightDarkMode.LIGHT_MODE); int documentRenderOffsetY = getDocumentRenderOffsetY(activeDocument); int renderedScrollY = Math.round(visualScrollY); int viewportTopInDocument = Math.max(0, renderedScrollY - documentRenderOffsetY); @@ -4695,7 +4708,7 @@ private void drawSearchField() { GuidebookText.SearchPlaceholder.text(), searchField.xPosition, searchField.yPosition, - 0xFF666666); + ColorUtils.ARGB_FF666666.getColor()); } } @@ -4709,11 +4722,26 @@ private void drawSpecialSearchField() { int backgroundRight = specialSearchFieldBounds.right(); int backgroundBottom = specialSearchFieldBounds.bottom() - SPECIAL_SEARCH_DIVIDER_GAP - SPECIAL_SEARCH_DIVIDER_HEIGHT; - drawRect(backgroundLeft, backgroundTop, backgroundRight, backgroundBottom, 0xCC0F0F12); - drawRect(backgroundLeft, backgroundTop, backgroundRight, backgroundTop + 1, 0xFF5A5A5A); - drawRect(backgroundLeft, backgroundBottom - 1, backgroundRight, backgroundBottom, 0xFF5A5A5A); - drawRect(backgroundLeft, backgroundTop, backgroundLeft + 1, backgroundBottom, 0xFF5A5A5A); - drawRect(backgroundRight - 1, backgroundTop, backgroundRight, backgroundBottom, 0xFF5A5A5A); + drawRect(backgroundLeft, backgroundTop, backgroundRight, backgroundBottom, ColorUtils.ARGB_CC0F0F12.getColor()); + drawRect(backgroundLeft, backgroundTop, backgroundRight, backgroundTop + 1, ColorUtils.PANEL_BORDER.getColor()); + drawRect( + backgroundLeft, + backgroundBottom - 1, + backgroundRight, + backgroundBottom, + ColorUtils.PANEL_BORDER.getColor()); + drawRect( + backgroundLeft, + backgroundTop, + backgroundLeft + 1, + backgroundBottom, + ColorUtils.PANEL_BORDER.getColor()); + drawRect( + backgroundRight - 1, + backgroundTop, + backgroundRight, + backgroundBottom, + ColorUtils.PANEL_BORDER.getColor()); pushGuiScissor( backgroundLeft + 1, backgroundTop + 1, @@ -4730,10 +4758,15 @@ private void drawSpecialSearchField() { GuidebookText.SearchPlaceholder.text(), specialSearchField.xPosition + 2, specialSearchField.yPosition + 2, - 0xFF666666); + ColorUtils.ARGB_FF666666.getColor()); } int dividerY = specialSearchFieldBounds.bottom() - SPECIAL_SEARCH_DIVIDER_HEIGHT; - drawRect(contentX, dividerY, contentX + contentW, dividerY + SPECIAL_SEARCH_DIVIDER_HEIGHT, 0x665A5A5A); + drawRect( + contentX, + dividerY, + contentX + contentW, + dividerY + SPECIAL_SEARCH_DIVIDER_HEIGHT, + ColorUtils.ARGB_665A5A5A.getColor()); } private boolean shouldDrawSearchPlaceholder() { @@ -4765,8 +4798,7 @@ private void drawCenteredSearchStateMessage(LytDocument activeDocument) { int textW = fontRendererObj.getStringWidth(message); int textX = areaX + Math.max(0, (areaW - textW) / 2); int textY = areaY + Math.max(0, (areaH - fontRendererObj.FONT_HEIGHT) / 2); - fontRendererObj - .drawString(message, textX, textY, SymbolicColor.BODY_TEXT.resolve(LightDarkMode.LIGHT_MODE), false); + fontRendererObj.drawString(message, textX, textY, ColorUtils.BODY_TEXT.resolve(), false); } public static LytRect cachedRect(@Nullable LytRect current, int x, int y, int w, int h) { @@ -4783,7 +4815,11 @@ private void drawPageMissingMessage() { FontRenderer fr = mc.fontRenderer; String msg = GuidebookText.PageNotFound.text(currentAnchor.pageId()); int tw = fr.getStringWidth(msg); - fr.drawStringWithShadow(msg, panelX + (panelW - tw) / 2, panelY + panelH / 2 - fr.FONT_HEIGHT / 2, 0xFFFF5555); + fr.drawStringWithShadow( + msg, + panelX + (panelW - tw) / 2, + panelY + panelH / 2 - fr.FONT_HEIGHT / 2, + ColorUtils.ARGB_FFFF5555.getColor()); } private void drawLoadingMessage() { @@ -4797,7 +4833,7 @@ private void drawLoadingMessage() { message, contentX + (contentW - tw) / 2, documentY + documentH / 2 - fr.FONT_HEIGHT / 2, - 0xFFCCCCCC); + ColorUtils.ARGB_FFCCCCCC.getColor()); } private String buildAnimatedLoadingLabel(String baseText) { @@ -4847,7 +4883,7 @@ private void drawTiledBackground() { GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, Math.clamp(BACKGROUND_ALPHA, 0f, 1f)); + ColorUtils.applyWhite(Math.clamp(BACKGROUND_ALPHA, 0f, 1f)); final float tile = 16f; float uMax = this.width / tile; float vMax = this.height / tile; @@ -4858,7 +4894,7 @@ private void drawTiledBackground() { tess.addVertexWithUV(this.width, 0, 0, uMax, 0); tess.addVertexWithUV(0, 0, 0, 0, 0); tess.draw(); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } private void drawBorder(int x, int y, int w, int h, int color) { @@ -4870,7 +4906,12 @@ private void drawBorder(int x, int y, int w, int h, int color) { private void drawScrollbar() { var bounds = scrollbarBounds(); - drawRect(bounds.x(), bounds.y(), bounds.x() + bounds.width(), bounds.y() + bounds.height(), 0x40FFFFFF); + drawRect( + bounds.x(), + bounds.y(), + bounds.x() + bounds.width(), + bounds.y() + bounds.height(), + ColorUtils.ARGB_40FFFFFF.getColor()); var renderState = scrollbarOutline.update( currentPage, getActiveDocument(), @@ -4892,7 +4933,7 @@ private void drawScrollbar() { int thumbY = bounds.maxScroll() > 0 ? bounds.y() + (int) ((long) (bounds.height() - thumbH) * Math.round(visualScrollY) / bounds.maxScroll()) : bounds.y(); - int thumbColor = draggingScrollbar ? 0xFFFFFFFF : 0xFFCCCCCC; + int thumbColor = draggingScrollbar ? ColorUtils.WHITE.getColor() : ColorUtils.ARGB_FFCCCCCC.getColor(); drawRect(bounds.x(), thumbY, bounds.x() + bounds.width(), thumbY + thumbH, thumbColor); drawScrollbarOutlineLabel(renderState, mc.fontRenderer); } @@ -7155,13 +7196,17 @@ private void drawScrollbarOutlineLabel(GuideScreenScrollbarOutline.RenderState r } int bubbleWidth = label.width() + SCROLLBAR_OUTLINE_LABEL_PADDING_X * 2; int bubbleHeight = label.height() + SCROLLBAR_OUTLINE_LABEL_PADDING_Y * 2; - int background = Colors.argb(label.alpha(), 16, 16, 16); - int border = Colors.argb(label.alpha(), 216, 216, 216); + int background = ColorUtils.argb(label.alpha(), 16, 16, 16); + int border = ColorUtils.argb(label.alpha(), 216, 216, 216); drawRect(label.x(), label.y(), label.x() + bubbleWidth, label.y() + bubbleHeight, background); drawBorder(label.x(), label.y(), bubbleWidth, bubbleHeight, border); int textY = label.y() + SCROLLBAR_OUTLINE_LABEL_PADDING_Y; for (String line : label.lines()) { - fontRenderer.drawStringWithShadow(line, label.x() + SCROLLBAR_OUTLINE_LABEL_PADDING_X, textY, 0xFFFFFF); + fontRenderer.drawStringWithShadow( + line, + label.x() + SCROLLBAR_OUTLINE_LABEL_PADDING_X, + textY, + ColorUtils.RGB_WHITE.getColor()); textY += fontRenderer.FONT_HEIGHT; } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreenContextMenu.java b/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreenContextMenu.java index 6472b981..19abea99 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreenContextMenu.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreenContextMenu.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.util.DisplayScale; import lombok.Getter; @@ -21,10 +22,10 @@ public class GuideScreenContextMenu { private static final int PADDING_Y = 4; private static final int TEXT_Y_OFFSET = 2; private static final int MIN_WIDTH = 72; - private static final int BACKGROUND_COLOR = 0xF0181C22; - private static final int BORDER_COLOR = 0xFF4D5661; - private static final int HOVER_COLOR = 0xCC2A3A46; - private static final int TEXT_COLOR = 0xFFF0F0F0; + private static final int BACKGROUND_COLOR = ColorUtils.DIALOG.getColor(); + private static final int BORDER_COLOR = ColorUtils.ARGB_FF4D5661.getColor(); + private static final int HOVER_COLOR = ColorUtils.ARGB_CC2A3A46.getColor(); + private static final int TEXT_COLOR = ColorUtils.TEXT.getColor(); public interface Listener { @@ -226,6 +227,6 @@ private void pushScissor(int x, int y, int width, int height) { private void popScissor() { GL11.glDisable(GL11.GL_SCISSOR_TEST); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreenScrollbarOutline.java b/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreenScrollbarOutline.java index 07d34ffd..c787f30d 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreenScrollbarOutline.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/GuideScreenScrollbarOutline.java @@ -10,8 +10,8 @@ import org.jetbrains.annotations.Nullable; import com.hfstudio.guidenh.guide.GuidePage; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.document.DefaultStyles; import com.hfstudio.guidenh.guide.document.block.LytDocument; import com.hfstudio.guidenh.guide.document.block.LytHeading; @@ -110,7 +110,19 @@ public void setAnchorsForTest(List testAnchors) { } public HeadingEntry testEntry(String text, int depth, int documentY) { - return testEntry(text, depth, documentY, 0xFFFFFFFF, 100, 50, markerWidth(depth), MARKER_HEIGHT, 98, 48, 16, 6); + return testEntry( + text, + depth, + documentY, + ColorUtils.WHITE.getColor(), + 100, + 50, + markerWidth(depth), + MARKER_HEIGHT, + 98, + 48, + 16, + 6); } public HeadingEntry testEntry(String text, int depth, int documentY, int colorArgb, int markerX, int markerY, @@ -330,7 +342,7 @@ private int resolveHeadingColor(int depth) { default -> baseStyle; }; ColorValue colorValue = headingStyle.color() != null ? headingStyle.color() : baseStyle.color(); - return colorValue.resolve(LightDarkMode.LIGHT_MODE); + return colorValue.resolve(); } private static int markerWidth(int depth) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/GuidebookText.java b/src/main/java/com/hfstudio/guidenh/guide/internal/GuidebookText.java index 9f703075..bca6d831 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/GuidebookText.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/GuidebookText.java @@ -28,6 +28,7 @@ public enum GuidebookText implements LocalizationEnum { SceneEditorShowElement, SceneEditorExport, SceneEditorExportSnbt, + SceneEditorExportSnbtOpenFolder, SceneEditorCopyGameScene, SceneEditorCopyBlockImage, SceneEditorImportStructure, diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/debug/DebugControlPanel.java b/src/main/java/com/hfstudio/guidenh/guide/internal/debug/DebugControlPanel.java index 66439f65..41cff606 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/debug/DebugControlPanel.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/debug/DebugControlPanel.java @@ -10,6 +10,7 @@ import org.lwjgl.opengl.GL11; import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.color.ColorUtils; import lombok.Setter; @@ -113,7 +114,13 @@ public void render(int mouseX, int mouseY, FontRenderer fontRenderer) { GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - drawRoundedRect(panelX, panelY, PANEL_WIDTH, PANEL_HEIGHT, 0x80000000, 0xFFAAAAAA); + drawRoundedRect( + panelX, + panelY, + PANEL_WIDTH, + PANEL_HEIGHT, + ColorUtils.ARGB_80000000.getColor(), + ColorUtils.ARGB_FFAAAAAA.getColor()); GL11.glEnable(GL11.GL_TEXTURE_2D); String label = fontRenderer.trimStringToWidth(translateKey("guidenh.debug.menu.options"), PANEL_WIDTH - 4); @@ -121,7 +128,7 @@ public void render(int mouseX, int mouseY, FontRenderer fontRenderer) { label, panelX + (PANEL_WIDTH - fontRenderer.getStringWidth(label)) / 2, panelY + (PANEL_HEIGHT - 8) / 2, - 0xFFFFFF); + ColorUtils.RGB_WHITE.getColor()); if (expanded || expandedMenu != null) { renderExpandedMenu(mouseX, mouseY, fontRenderer); @@ -135,7 +142,13 @@ private void renderExpandedMenu(int mouseX, int mouseY, FontRenderer fontRendere int menuHeight = menuItems.size() * DROPDOWN_ITEM_HEIGHT + 4; GL11.glDisable(GL11.GL_TEXTURE_2D); - drawRoundedRect(panelX, menuY, PANEL_WIDTH, menuHeight, 0xD0000000, 0xFFCCCCCC); + drawRoundedRect( + panelX, + menuY, + PANEL_WIDTH, + menuHeight, + ColorUtils.ARGB_D0000000.getColor(), + ColorUtils.ARGB_FFCCCCCC.getColor()); GL11.glEnable(GL11.GL_TEXTURE_2D); hoveredItem = null; @@ -150,7 +163,7 @@ private void renderExpandedMenu(int mouseX, int mouseY, FontRenderer fontRendere if (isHovered) { hoveredItem = item; GL11.glDisable(GL11.GL_TEXTURE_2D); - drawRect(panelX + 2, itemY, PANEL_WIDTH - 4, DROPDOWN_ITEM_HEIGHT, 0x80FFFFFF); + drawRect(panelX + 2, itemY, PANEL_WIDTH - 4, DROPDOWN_ITEM_HEIGHT, ColorUtils.ARGB_80FFFFFF.getColor()); GL11.glEnable(GL11.GL_TEXTURE_2D); } @@ -164,7 +177,7 @@ private void renderExpandedMenu(int mouseX, int mouseY, FontRenderer fontRendere displayText = "✓ " + displayText; } - fontRenderer.drawStringWithShadow(displayText, panelX + 6, itemY + 3, 0xFFFFFF); + fontRenderer.drawStringWithShadow(displayText, panelX + 6, itemY + 3, ColorUtils.RGB_WHITE.getColor()); } if (expandedMenu != null && expandedMenu.hasSubmenu()) { @@ -183,7 +196,13 @@ private void renderSubmenu(DebugMenuItem parentItem, int mouseX, int mouseY, Fon int submenuHeight = submenuItems.size() * DROPDOWN_ITEM_HEIGHT + 4; GL11.glDisable(GL11.GL_TEXTURE_2D); - drawRoundedRect(submenuX, submenuY, PANEL_WIDTH, submenuHeight, 0xD0000000, 0xFFCCCCCC); + drawRoundedRect( + submenuX, + submenuY, + PANEL_WIDTH, + submenuHeight, + ColorUtils.ARGB_D0000000.getColor(), + ColorUtils.ARGB_FFCCCCCC.getColor()); GL11.glEnable(GL11.GL_TEXTURE_2D); @@ -197,13 +216,18 @@ private void renderSubmenu(DebugMenuItem parentItem, int mouseX, int mouseY, Fon if (isHovered) { hoveredItem = item; GL11.glDisable(GL11.GL_TEXTURE_2D); - drawRect(submenuX + 2, itemY, PANEL_WIDTH - 4, DROPDOWN_ITEM_HEIGHT, 0x80FFFFFF); + drawRect( + submenuX + 2, + itemY, + PANEL_WIDTH - 4, + DROPDOWN_ITEM_HEIGHT, + ColorUtils.ARGB_80FFFFFF.getColor()); GL11.glEnable(GL11.GL_TEXTURE_2D); } boolean checkState = getCheckState(item.getAction()); String displayText = (checkState ? "✓ " : " ") + translateKey(item.getTranslationKey()); - fontRenderer.drawStringWithShadow(displayText, submenuX + 6, itemY + 3, 0xFFFFFF); + fontRenderer.drawStringWithShadow(displayText, submenuX + 6, itemY + 3, ColorUtils.RGB_WHITE.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/debug/DebugInfoPanel.java b/src/main/java/com/hfstudio/guidenh/guide/internal/debug/DebugInfoPanel.java index 7287b999..6846b3df 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/debug/DebugInfoPanel.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/debug/DebugInfoPanel.java @@ -11,6 +11,7 @@ import org.lwjgl.opengl.GL11; import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.color.ColorUtils; /** * Renders debug information panel at the left-bottom corner of the screen. @@ -132,7 +133,7 @@ private void collectParentInfo(List lines, HoveredElementInfo parent) { private void renderLines(List lines, int screenHeight, FontRenderer fontRenderer) { float scale = ModConfig.debug.debugTextScale; - int textColor = ModConfig.debug.debugTextColor; + int textColor = ColorUtils.DEBUG_TEXT.getColor(); GL11.glPushMatrix(); GL11.glTranslatef(0.0F, 0.0F, GuideDebugOverlay.INFO_PANEL_Z); @@ -156,9 +157,9 @@ private void renderLines(List lines, int screenHeight, FontRenderer font } private void renderHoveredOutline(HoveredElementInfo info, int screenWidth) { - int color = ModConfig.debug.debugOutlineColor; + int color = ColorUtils.DEBUG_OUTLINE.getColor(); if (color == 0) { - color = ModConfig.debug.debugTextColor; + color = ColorUtils.DEBUG_TEXT.getColor(); } borderRenderer.renderDashedBorder( info.getScreenX(), @@ -170,9 +171,9 @@ private void renderHoveredOutline(HoveredElementInfo info, int screenWidth) { } private void renderParentOutline(HoveredElementInfo parent) { - int color = ModConfig.debug.debugOutlineColor; + int color = ColorUtils.DEBUG_OUTLINE.getColor(); if (color == 0) { - color = ModConfig.debug.debugTextColor; + color = ColorUtils.DEBUG_TEXT.getColor(); } int alphaColor = (color & 0x00FFFFFF) | 0x4D000000; borderRenderer.renderDashedBorder( @@ -202,10 +203,10 @@ private void renderClassNameLabel(int x, int y, String className, int screenWidt GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - drawRect(labelX - 2, labelY - 1, textWidth + 4, textHeight + 2, 0xD0000000); + drawRect(labelX - 2, labelY - 1, textWidth + 4, textHeight + 2, ColorUtils.ARGB_D0000000.getColor()); GL11.glEnable(GL11.GL_TEXTURE_2D); - fontRenderer.drawStringWithShadow(displayName, labelX, labelY, 0xFFFFFFFF); + fontRenderer.drawStringWithShadow(displayName, labelX, labelY, ColorUtils.WHITE.getColor()); GL11.glPopMatrix(); } @@ -215,7 +216,7 @@ private void drawRect(int x, int y, int width, int height, int color) { float green = ((color >> 8) & 0xFF) / 255.0f; float blue = (color & 0xFF) / 255.0f; - GL11.glColor4f(red, green, blue, alpha); + ColorUtils.applyGlColor(red, green, blue, alpha); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x, y + height); GL11.glVertex2f(x + width, y + height); diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/debug/GuideDebugOverlay.java b/src/main/java/com/hfstudio/guidenh/guide/internal/debug/GuideDebugOverlay.java index 6463949c..5f0a2a53 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/debug/GuideDebugOverlay.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/debug/GuideDebugOverlay.java @@ -11,6 +11,7 @@ import org.lwjgl.opengl.GL11; import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.block.LytDocument; import lombok.Getter; @@ -118,7 +119,7 @@ public void render(int screenWidth, int screenHeight, int mouseX, int mouseY, in GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glTranslatef(0.0F, 0.0F, OVERLAY_Z); HoveredElementInfo documentHoveredInfo = null; @@ -251,14 +252,14 @@ private void toggleDebugMode() { } private void renderCursorDot(int mouseX, int mouseY) { - int color = ModConfig.debug.debugCursorColor; + int color = ColorUtils.DEBUG_CURSOR.getColor(); float alpha = ((color >> 24) & 0xFF) / 255.0f; float red = ((color >> 16) & 0xFF) / 255.0f; float green = ((color >> 8) & 0xFF) / 255.0f; float blue = (color & 0xFF) / 255.0f; GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(red, green, blue, alpha); + ColorUtils.applyGlColor(red, green, blue, alpha); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(mouseX, mouseY); GL11.glVertex2f(mouseX + 1, mouseY); diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/debug/GuideDebugOverlayRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/internal/debug/GuideDebugOverlayRenderer.java index 5ee71a36..4d3e95c8 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/debug/GuideDebugOverlayRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/debug/GuideDebugOverlayRenderer.java @@ -9,6 +9,7 @@ import org.lwjgl.opengl.GL11; import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.mixins.early.forge.AccessorGuiIngameForge; public class GuideDebugOverlayRenderer { @@ -50,7 +51,7 @@ public void render(Minecraft minecraft, float partialTicks, int mouseX, int mous minecraft.entityRenderer.setupOverlayRendering(); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); accessor.setScaledResolution(scaledResolution); accessor.setFontRenderer(minecraft.fontRenderer); diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/SceneEditorDefaultControlRegistry.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/SceneEditorDefaultControlRegistry.java new file mode 100644 index 00000000..0ae7b836 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/SceneEditorDefaultControlRegistry.java @@ -0,0 +1,152 @@ +package com.hfstudio.guidenh.guide.internal.editor; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BooleanSupplier; + +import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.editor.SceneEditorActionContext; +import com.hfstudio.guidenh.guide.editor.SceneEditorMenuItem; +import com.hfstudio.guidenh.guide.internal.GuidebookText; +import com.hfstudio.guidenh.guide.internal.screen.GuideIconButton; + +/** Owns the built-in Scene Editor toolbar and dropdown registration definitions. */ +public class SceneEditorDefaultControlRegistry { + + public static List createToolbarButtons(int x, int y) { + List buttons = new ArrayList<>(); + buttons + .add(new GuideIconButton(SceneEditorScreen.CLOSE_BUTTON_ID, x, y, GuideIconButton.Role.SCENE_EDITOR_CLOSE)); + buttons.add( + new GuideIconButton( + SceneEditorScreen.RESET_PREVIEW_BUTTON_ID, + x + 20, + y, + GuideIconButton.Role.SCENE_EDITOR_RESET_PREVIEW)); + buttons.add( + new GuideIconButton(SceneEditorScreen.SNAP_BUTTON_ID, x + 40, y, GuideIconButton.Role.SCENE_EDITOR_SNAP)); + buttons.add( + new GuideIconButton( + SceneEditorScreen.AUTO_PICK_BUTTON_ID, + x + 60, + y, + GuideIconButton.Role.SCENE_EDITOR_AUTO_PICK)); + buttons.add( + new GuideIconButton( + SceneEditorScreen.IMPORT_STRUCTURE_BUTTON_ID, + x + 80, + y, + GuideIconButton.Role.SCENE_EDITOR_IMPORT_STRUCTURE)); + buttons.add( + new GuideIconButton( + SceneEditorScreen.EXPORT_BUTTON_ID, + x + 100, + y, + GuideIconButton.Role.SCENE_EDITOR_EXPORT)); + buttons.add( + new GuideIconButton( + SceneEditorScreen.SCREENSHOT_BUTTON_ID, + x + 120, + y, + GuideIconButton.Role.SCENE_EDITOR_SCREENSHOT)); + return buttons; + } + + public List createExportItems(SceneEditorActionContext context, + BooleanSupplier blockImageAvailable) { + List items = new ArrayList<>(); + items.add( + new SceneEditorMenuItem( + "snbt", + GuidebookText.SceneEditorExportSnbt::text, + 0, + () -> true, + () -> true, + null, + ignored -> context.exportSnbt())); + items.add( + new SceneEditorMenuItem( + "snbt-open-folder-after-export", + GuidebookText.SceneEditorExportSnbtOpenFolder::text, + 10, + () -> true, + () -> true, + () -> ModConfig.ui.sceneEditorExportOpenFolderAfterExport, + ignored -> { + ModConfig.ui.sceneEditorExportOpenFolderAfterExport = !ModConfig.ui.sceneEditorExportOpenFolderAfterExport; + ModConfig.save(); + })); + items.add( + new SceneEditorMenuItem( + "game-scene", + GuidebookText.SceneEditorCopyGameScene::text, + 20, + blockImageAvailable, + () -> true, + null, + ignored -> context.copyGameScene())); + items.add( + new SceneEditorMenuItem( + "block-image", + GuidebookText.SceneEditorCopyBlockImage::text, + 30, + blockImageAvailable, + () -> true, + null, + ignored -> context.copyBlockImage())); + return items; + } + + public List createSnapItems(SceneEditorActionContext context) { + List items = new ArrayList<>(); + items.add( + new SceneEditorMenuItem( + "line", + GuidebookText.SceneEditorSnapLine::text, + 0, + () -> true, + () -> true, + () -> ModConfig.ui.sceneEditorSnapLineEnabled, + ignored -> { + ModConfig.ui.sceneEditorSnapLineEnabled = !ModConfig.ui.sceneEditorSnapLineEnabled; + ModConfig.save(); + })); + items.add( + new SceneEditorMenuItem( + "point", + GuidebookText.SceneEditorSnapPoint::text, + 10, + () -> true, + () -> true, + () -> ModConfig.ui.sceneEditorSnapPointEnabled, + ignored -> { + ModConfig.ui.sceneEditorSnapPointEnabled = !ModConfig.ui.sceneEditorSnapPointEnabled; + ModConfig.save(); + })); + items.add( + new SceneEditorMenuItem( + "face", + GuidebookText.SceneEditorSnapFace::text, + 20, + () -> true, + () -> true, + () -> ModConfig.ui.sceneEditorSnapFaceEnabled, + ignored -> { + ModConfig.ui.sceneEditorSnapFaceEnabled = !ModConfig.ui.sceneEditorSnapFaceEnabled; + ModConfig.save(); + })); + items.add( + new SceneEditorMenuItem( + "center", + GuidebookText.SceneEditorSnapCenter::text, + 30, + () -> true, + () -> true, + () -> ModConfig.ui.sceneEditorSnapCenterEnabled, + ignored -> { + ModConfig.ui.sceneEditorSnapCenterEnabled = !ModConfig.ui.sceneEditorSnapCenterEnabled; + ModConfig.save(); + })); + return items; + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/SceneEditorScreen.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/SceneEditorScreen.java index 646b3024..7c5e1370 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/SceneEditorScreen.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/SceneEditorScreen.java @@ -1,16 +1,21 @@ package com.hfstudio.guidenh.guide.internal.editor; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Random; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.function.BooleanSupplier; +import java.util.function.Supplier; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; @@ -34,7 +39,7 @@ import com.hfstudio.guidenh.client.command.GuideNhClientBridgeController; import com.hfstudio.guidenh.config.ModConfig; -import com.hfstudio.guidenh.guide.color.LightDarkMode; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.GuideItemReferenceResolver; import com.hfstudio.guidenh.guide.compiler.GuideItemReferenceResolver.ResolvedBlockReference; import com.hfstudio.guidenh.guide.document.LytRect; @@ -42,6 +47,13 @@ import com.hfstudio.guidenh.guide.document.interaction.GuideTooltip; import com.hfstudio.guidenh.guide.document.interaction.ItemTooltip; import com.hfstudio.guidenh.guide.document.interaction.TextTooltip; +import com.hfstudio.guidenh.guide.editor.SceneEditorActionContext; +import com.hfstudio.guidenh.guide.editor.SceneEditorMenuItem; +import com.hfstudio.guidenh.guide.editor.SceneEditorMenuRegistry; +import com.hfstudio.guidenh.guide.editor.SceneEditorMenuWidget; +import com.hfstudio.guidenh.guide.editor.SceneEditorMenuWidgetContext; +import com.hfstudio.guidenh.guide.editor.SceneEditorToolbarButton; +import com.hfstudio.guidenh.guide.editor.SceneEditorToolbarRegistry; import com.hfstudio.guidenh.guide.internal.GuidebookText; import com.hfstudio.guidenh.guide.internal.debug.GuideDebugOverlay; import com.hfstudio.guidenh.guide.internal.editor.gui.SceneEditorDraftTextController; @@ -67,6 +79,7 @@ import com.hfstudio.guidenh.guide.internal.editor.gui.SceneEditorUndoUiState; import com.hfstudio.guidenh.guide.internal.editor.gui.SceneEditorVerticalScrollbar; import com.hfstudio.guidenh.guide.internal.editor.io.SceneEditorClipboardExporter; +import com.hfstudio.guidenh.guide.internal.editor.io.SceneEditorFolderOpener; import com.hfstudio.guidenh.guide.internal.editor.io.SceneEditorSaveService; import com.hfstudio.guidenh.guide.internal.editor.io.SceneEditorScreenshotExportService; import com.hfstudio.guidenh.guide.internal.editor.io.SceneEditorScreenshotFormat; @@ -118,32 +131,30 @@ public class SceneEditorScreen extends GuiScreen { public static final int TOOLBAR_MARGIN_X = 10; public static final int TOOLBAR_Y = SceneEditorScreenLayout.TOOLBAR_Y; - public static final int PANEL_COLOR = 0xB418181C; - public static final int PANEL_INNER_COLOR = 0x70121216; - public static final int PANEL_BORDER_COLOR = 0xFF5A5A5A; - public static final int PANEL_HEADER_COLOR = 0xFFDEE6F0; - public static final int PANEL_MUTED_TEXT = 0xFFB9C2CE; - public static final int PANEL_SUBTLE_TEXT = 0xFF8F98A3; - public static final int INPUT_BORDER_COLOR = 0xFF3E434A; - public static final int INPUT_FOCUSED_BORDER_COLOR = 0xFF7FC8FF; - public static final int INPUT_ERROR_BORDER_COLOR = 0xFFFF6767; - public static final int INPUT_BACKGROUND_COLOR = 0x80101012; - public static final int CHECKBOX_BACKGROUND_COLOR = 0xA0141418; - public static final int CHECKBOX_CHECK_COLOR = 0xFF00CAF2; + public static final int PANEL_COLOR = ColorUtils.PANEL.getColor(); + public static final int PANEL_INNER_COLOR = ColorUtils.PANEL_INNER.getColor(); + public static final int PANEL_BORDER_COLOR = ColorUtils.PANEL_BORDER.getColor(); + public static final int PANEL_HEADER_COLOR = ColorUtils.PANEL_HEADER.getColor(); + public static final int PANEL_MUTED_TEXT = ColorUtils.PANEL_MUTED_TEXT.getColor(); + public static final int PANEL_SUBTLE_TEXT = ColorUtils.TEXT_DISABLED.getColor(); + public static final int INPUT_BORDER_COLOR = ColorUtils.INPUT_BORDER.getColor(); + public static final int INPUT_FOCUSED_BORDER_COLOR = ColorUtils.INPUT_FOCUSED_BORDER.getColor(); + public static final int INPUT_ERROR_BORDER_COLOR = ColorUtils.ERROR.getColor(); + public static final int INPUT_BACKGROUND_COLOR = ColorUtils.INPUT_BACKGROUND.getColor(); + public static final int CHECKBOX_BACKGROUND_COLOR = ColorUtils.CHECKBOX_BACKGROUND.getColor(); + public static final int CHECKBOX_CHECK_COLOR = ColorUtils.ACCENT.getColor(); public static final int SETTINGS_BOX_PADDING = 8; public static final int PARAMETER_ROW_HEIGHT = 18; public static final int PARAMETER_LABEL_WIDTH = 52; public static final int PARAMETER_INPUT_WIDTH = 46; public static final int PARAMETER_INPUT_HEIGHT = 14; public static final int PARAMETER_GAP = 4; - public static final int PARAMETER_SLIDER_HEIGHT = GuideSliderRenderer.TRACK_HEIGHT; - public static final int PARAMETER_SLIDER_THUMB_WIDTH = GuideSliderRenderer.THUMB_WIDTH; public static final int PARAMETER_SLIDER_Y_OFFSET = 5; public static final int SETTINGS_TAB_HEIGHT = 18; public static final int SETTINGS_TAB_GAP = 4; - public static final int SETTINGS_TAB_ACTIVE_COLOR = 0xD6202C36; - public static final int SETTINGS_TAB_INACTIVE_COLOR = 0x6612181C; - public static final int SETTINGS_TAB_HOVER_COLOR = 0xA61C252E; + public static final int SETTINGS_TAB_ACTIVE_COLOR = ColorUtils.TAB_ACTIVE.getColor(); + public static final int SETTINGS_TAB_INACTIVE_COLOR = ColorUtils.TAB_INACTIVE.getColor(); + public static final int SETTINGS_TAB_HOVER_COLOR = ColorUtils.TAB_HOVER.getColor(); public static final int INTERACTIVE_ROW_HEIGHT = 18; public static final int INTERACTIVE_CHECKBOX_SIZE = 12; public static final int PREVIEW_FRAME_BUTTON_WIDTH = 74; @@ -152,15 +163,9 @@ public class SceneEditorScreen extends GuiScreen { public static final int ACTION_ROW_BUTTON_GAP = 8; public static final int ELEMENT_ROW_HEIGHT = 20; public static final int ELEMENT_ROW_GAP = 4; - public static final int ELEMENT_EXPANDED_HEIGHT = 154; public static final int ELEMENT_ICON_SIZE = 14; public static final int ELEMENT_MENU_WIDTH = 102; public static final int ELEMENT_MENU_ROW_HEIGHT = 18; - public static final int ELEMENT_ROW_BACKGROUND = 0x6A121418; - public static final int ELEMENT_ROW_SELECTED = 0x9A1C222A; - public static final int ELEMENT_ROW_EXPANDED = 0x7A101216; - public static final int ELEMENT_MENU_BACKGROUND = 0xEE121418; - public static final int ELEMENT_MENU_HOVER = 0xCC1A222A; public static final int ELEMENT_FIELD_ROW_HEIGHT = 18; public static final int ELEMENT_FIELD_LABEL_WIDTH = 62; public static final int ELEMENT_TOOLTIP_HEIGHT = 44; @@ -170,17 +175,16 @@ public class SceneEditorScreen extends GuiScreen { public static final int ELEMENT_CONTEXT_MENU_WIDTH = 132; public static final int MARKDOWN_CONTEXT_MENU_WIDTH = 148; public static final int MARKDOWN_CONTEXT_MENU_ROW_HEIGHT = 18; - public static final int SNAP_MENU_WIDTH = 118; - public static final int EXPORT_MENU_WIDTH = 152; + public static final int MENU_HORIZONTAL_PADDING = 16; public static final long CLIENT_SELECTION_EXPORT_BUDGET_NANOS = 3_000_000L; public static final int CLOSE_DIALOG_WIDTH = 248; public static final int CLOSE_DIALOG_HEIGHT = 104; public static final int CLOSE_DIALOG_BUTTON_WIDTH = 68; public static final int CLOSE_DIALOG_BUTTON_HEIGHT = 20; public static final int CLOSE_DIALOG_BUTTON_GAP = 10; - public static final int CLOSE_DIALOG_OVERLAY_COLOR = 0x8A050608; - public static final int CLOSE_DIALOG_COLOR = 0xF0181C22; - public static final int CLOSE_DIALOG_HOVER = 0xCC24303A; + public static final int CLOSE_DIALOG_OVERLAY_COLOR = ColorUtils.DIALOG_OVERLAY.getColor(); + public static final int CLOSE_DIALOG_COLOR = ColorUtils.DIALOG.getColor(); + public static final int CLOSE_DIALOG_HOVER = ColorUtils.DIALOG_HOVER.getColor(); public static final int CLOSE_BUTTON_ID = 0; public static final int RESET_PREVIEW_BUTTON_ID = 1; @@ -201,6 +205,7 @@ public class SceneEditorScreen extends GuiScreen { private final SceneEditorElementReorderController elementReorderController; private final SceneEditorLinkedSelectionController linkedSelectionController; private final SceneEditorPreviewBridge previewBridge; + private final SceneEditorDefaultControlRegistry defaultControlRegistry = new SceneEditorDefaultControlRegistry(); private final SceneEditorPreviewCameraController previewCameraController; private final SceneEditorPickingService pickingService; private final SceneEditorHandleOverlay handleOverlay; @@ -230,6 +235,17 @@ public class SceneEditorScreen extends GuiScreen { private GuideIconButton importStructureButton; private GuideIconButton screenshotButton; private GuideIconButton addElementButton; + private final Map registeredToolbarButtons = new HashMap<>(); + private final Map registeredToolbarButtonWidgets = new HashMap<>(); + @Nullable + private String registeredMenuOpen; + private int registeredMenuAnchorId; + @Nullable + private MenuEntry activeRegisteredWidget; + @Nullable + private MenuEntry activeBuiltInWidget; + @Nullable + private String activeBuiltInWidgetMenu; private SceneEditorMultilineTextArea markdownTextArea; @Nullable private GuiTextField screenshotScaleField; @@ -381,8 +397,8 @@ public SceneEditorScreen(SceneEditorSession session) { }); this.structureImportService = new SceneEditorStructureImportService(structureCache); this.previewLayoutContext = new LayoutContext(new MinecraftFontMetrics()); - this.previewRenderContext = new VanillaRenderContext(LightDarkMode.LIGHT_MODE, LytRect.empty(), 0); - this.previewTooltipRenderContext = new VanillaRenderContext(LightDarkMode.LIGHT_MODE, LytRect.empty(), 0); + this.previewRenderContext = new VanillaRenderContext(LytRect.empty(), 0); + this.previewTooltipRenderContext = new VanillaRenderContext(LytRect.empty(), 0); this.numericParameterRows = new ArrayList<>(); this.elementPanelScrollState = new SceneEditorScrollState(); this.addElementMenuState = new SceneEditorHoverMenuState(); @@ -490,41 +506,14 @@ public void initGui() { this.buttonList.clear(); int toolbarX = TOOLBAR_MARGIN_X; - closeButton = new GuideIconButton( - CLOSE_BUTTON_ID, - toolbarX, - TOOLBAR_Y, - GuideIconButton.Role.SCENE_EDITOR_CLOSE); - resetPreviewButton = new GuideIconButton( - RESET_PREVIEW_BUTTON_ID, - toolbarX + 20, - TOOLBAR_Y, - GuideIconButton.Role.SCENE_EDITOR_RESET_PREVIEW); - snapButton = new GuideIconButton( - SNAP_BUTTON_ID, - toolbarX + 40, - TOOLBAR_Y, - GuideIconButton.Role.SCENE_EDITOR_SNAP); - autoPickButton = new GuideIconButton( - AUTO_PICK_BUTTON_ID, - toolbarX + 60, - TOOLBAR_Y, - GuideIconButton.Role.SCENE_EDITOR_AUTO_PICK); - importStructureButton = new GuideIconButton( - IMPORT_STRUCTURE_BUTTON_ID, - toolbarX + 80, - TOOLBAR_Y, - GuideIconButton.Role.SCENE_EDITOR_IMPORT_STRUCTURE); - exportButton = new GuideIconButton( - EXPORT_BUTTON_ID, - toolbarX + 100, - TOOLBAR_Y, - GuideIconButton.Role.SCENE_EDITOR_EXPORT); - screenshotButton = new GuideIconButton( - SCREENSHOT_BUTTON_ID, - toolbarX + 120, - TOOLBAR_Y, - GuideIconButton.Role.SCENE_EDITOR_SCREENSHOT); + List defaultButtons = defaultControlRegistry.createToolbarButtons(toolbarX, TOOLBAR_Y); + closeButton = defaultButtons.get(0); + resetPreviewButton = defaultButtons.get(1); + snapButton = defaultButtons.get(2); + autoPickButton = defaultButtons.get(3); + importStructureButton = defaultButtons.get(4); + exportButton = defaultButtons.get(5); + screenshotButton = defaultButtons.get(6); if (screenshotScaleField == null) { screenshotScaleField = new GuiTextField(this.fontRendererObj, 0, 0, 0, PARAMETER_INPUT_HEIGHT); @@ -540,6 +529,23 @@ public void initGui() { this.buttonList.add(importStructureButton); this.buttonList.add(exportButton); this.buttonList.add(screenshotButton); + registeredToolbarButtons.clear(); + registeredToolbarButtonWidgets.clear(); + int extensionToolbarX = toolbarX + 140; + for (SceneEditorToolbarButton descriptor : SceneEditorToolbarRegistry.snapshot()) { + int buttonId = SceneEditorToolbarRegistry.nextButtonId(); + GuideIconButton extensionButton = new GuideIconButton( + buttonId, + extensionToolbarX, + TOOLBAR_Y, + descriptor.icon(), + descriptor.label()); + extensionButton.enabled = descriptor.enabled(); + registeredToolbarButtons.put(buttonId, descriptor); + registeredToolbarButtonWidgets.put(buttonId, extensionButton); + this.buttonList.add(extensionButton); + extensionToolbarX += GuideIconButton.WIDTH + 4; + } addElementButton = new GuideIconButton( ADD_ELEMENT_BUTTON_ID, elementsBoxX + elementsBoxWidth - GuideIconButton.WIDTH - 6, @@ -722,6 +728,22 @@ private void pollContinuousMouseDrag(int mouseX, int mouseY) { @Override protected void actionPerformed(GuiButton button) { + SceneEditorToolbarButton registeredButton = registeredToolbarButtons.get(button.id); + if (registeredButton != null) { + if (registeredButton.enabled()) { + if (registeredButton.menuId() != null && !registeredButton.menuId() + .trim() + .isEmpty()) { + registeredMenuOpen = registeredButton.menuId(); + registeredMenuAnchorId = button.id; + activeRegisteredWidget = null; + closeBuiltInMenus(); + } else { + registeredButton.triggerClick(createActionContext()); + } + } + return; + } if (button.id == CLOSE_BUTTON_ID) { requestCloseEditor(); return; @@ -752,7 +774,7 @@ protected void actionPerformed(GuiButton button) { if (GuiScreen.isShiftKeyDown()) { copyGameScene(); } else { - attemptSaveWithoutClose(); + attemptExportSnbt(); } return; } @@ -763,6 +785,83 @@ protected void actionPerformed(GuiButton button) { if (button.id == ADD_ELEMENT_BUTTON_ID) {} } + private SceneEditorActionContext createActionContext() { + return new SceneEditorActionContext() { + + @Override + public SceneEditorSession session() { + return session; + } + + @Override + public int width() { + return SceneEditorScreen.this.width; + } + + @Override + public int height() { + return SceneEditorScreen.this.height; + } + + @Override + public void rebuildPreview() { + rebuildPreviewScene(true); + } + + @Override + public void save() { + attemptSaveWithoutClose(); + } + + @Override + public void exportSnbt() { + attemptExportSnbt(); + } + + @Override + public void copyGameScene() { + SceneEditorScreen.this.copyGameScene(); + } + + @Override + public void copyBlockImage() { + SceneEditorScreen.this.copyBlockImage(); + } + + @Override + public void openExportFolder() { + SceneEditorScreen.this.saveAndOpenStructureFolder(); + } + + @Override + public void closeMenus() { + closeSceneEditorMenus(); + } + }; + } + + private void closeSceneEditorMenus() { + exportMenuOpen = false; + snapModeMenuOpen = false; + screenshotMenuController.close(); + activeBuiltInWidget = null; + activeBuiltInWidgetMenu = null; + closeRegisteredMenu(); + } + + private void closeBuiltInMenus() { + exportMenuOpen = false; + snapModeMenuOpen = false; + screenshotMenuController.close(); + activeBuiltInWidget = null; + activeBuiltInWidgetMenu = null; + } + + private void closeRegisteredMenu() { + registeredMenuOpen = null; + activeRegisteredWidget = null; + } + @Override protected void keyTyped(char typedChar, int keyCode) { if (debugOverlay.handleKeyPress(typedChar, keyCode)) { @@ -841,6 +940,7 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { addElementButton.visible = !rightPanelCollapsed; } syncToolbarToggleState(); + syncRegisteredToolbarButtons(); pollContinuousMouseDrag(mouseX, mouseY); pollActivePreviewSceneDrag(); @@ -865,6 +965,9 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { if (exportMenuOpen) { drawExportMenu(mouseX, mouseY); } + if (registeredMenuOpen != null) { + drawRegisteredMenu(mouseX, mouseY); + } if (closeConfirmDialogOpen) { drawCloseConfirmDialog(mouseX, mouseY); @@ -997,6 +1100,9 @@ protected void mouseClicked(int mouseX, int mouseY, int button) { if (handleScreenshotMenuClick(mouseX, mouseY, button)) { return; } + if (handleRegisteredMenuClick(mouseX, mouseY, button)) { + return; + } if (handleExportMenuClick(mouseX, mouseY, button)) { return; } @@ -1004,6 +1110,8 @@ protected void mouseClicked(int mouseX, int mouseY, int button) { exportMenuOpen = !exportMenuOpen; snapModeMenuOpen = false; screenshotMenuController.close(); + activeBuiltInWidget = null; + activeBuiltInWidgetMenu = null; return; } if (exportMenuOpen && !isInsideExportButton(mouseX, mouseY) && !isInsideExportMenu(mouseX, mouseY)) { @@ -1022,6 +1130,8 @@ protected void mouseClicked(int mouseX, int mouseY, int button) { snapModeMenuOpen = !snapModeMenuOpen; screenshotMenuController.close(); exportMenuOpen = false; + activeBuiltInWidget = null; + activeBuiltInWidgetMenu = null; return; } if (snapModeMenuOpen && !isInsideSnapButton(mouseX, mouseY) && !isInsideSnapModeMenu(mouseX, mouseY)) { @@ -1175,6 +1285,42 @@ protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, lo } return; } + if (activeRegisteredWidget != null && registeredMenuOpen != null && clickedMouseButton == 0) { + LytRect bounds = getRegisteredMenuBounds(); + MenuEntry entry = activeRegisteredWidget; + int entryY = registeredMenuEntryY(entry, bounds); + if (entryY >= 0 && entry.widget() != null + && entry.widget() + .triggerDrag( + createActionContext(), + bounds.x(), + entryY, + bounds.width(), + entry.height(), + mouseX, + mouseY, + clickedMouseButton)) { + return; + } + } + if (activeBuiltInWidget != null && activeBuiltInWidgetMenu != null && clickedMouseButton == 0) { + List entries = builtInMenuEntries(activeBuiltInWidgetMenu); + LytRect bounds = builtInMenuBounds(activeBuiltInWidgetMenu); + int entryY = menuEntryY(entries, activeBuiltInWidget, bounds.y()); + if (entryY >= 0 && activeBuiltInWidget.widget() != null + && activeBuiltInWidget.widget() + .triggerDrag( + createActionContext(), + bounds.x(), + entryY, + bounds.width(), + activeBuiltInWidget.height(), + mouseX, + mouseY, + clickedMouseButton)) { + return; + } + } if (clickedMouseButton == 0 && activePointDrag != null && previewScene != null) { if (pointDragService.updateHandleDrag( elementPropertyController, @@ -1221,6 +1367,15 @@ protected void mouseMovedOrUp(int mouseX, int mouseY, int state) { draggingScreenshotScaleSlider = false; return; } + if (activeRegisteredWidget != null && state != -1) { + activeRegisteredWidget = null; + return; + } + if (activeBuiltInWidget != null && state != -1) { + activeBuiltInWidget = null; + activeBuiltInWidgetMenu = null; + return; + } if (draggingMarkdownResize && state != -1) { draggingMarkdownResize = false; markdownPanelState.persistOpenWidth(); @@ -1304,12 +1459,17 @@ private void drawToolbarTitle() { String structureSource = session.getSceneModel() .getStructureSource(); boolean hasImportedStructure = structureSource != null && !structureSource.isEmpty(); - int titleX = TOOLBAR_MARGIN_X + 152; + int titleX = TOOLBAR_MARGIN_X + 152 + registeredToolbarButtons.size() * (GuideIconButton.WIDTH + 4); int sessionLabelY = TOOLBAR_Y + 16; - this.drawString(this.fontRendererObj, GuidebookText.SceneEditorTitle.text(), titleX, TOOLBAR_Y + 4, 0xFFFFFF); + this.drawString( + this.fontRendererObj, + GuidebookText.SceneEditorTitle.text(), + titleX, + TOOLBAR_Y + 4, + ColorUtils.RGB_WHITE.getColor()); String sessionLabel = hasImportedStructure ? GuidebookText.SceneEditorImportedSession.text() : GuidebookText.SceneEditorBlankSession.text(); - this.drawString(this.fontRendererObj, sessionLabel, titleX, sessionLabelY, 0xFF8FC7FF); + this.drawString(this.fontRendererObj, sessionLabel, titleX, sessionLabelY, ColorUtils.ARGB_FF8FC7FF.getColor()); } private void syncToolbarToggleState() { @@ -1347,7 +1507,7 @@ private void drawLeftPanel(int mouseX, int mouseY) { == SceneEditorTextSyncController.ValidationKind.UNSUPPORTED ? GuidebookText.SceneEditorUnsupportedSyntax.text() : GuidebookText.SceneEditorSyntaxError.text(); - this.drawString(this.fontRendererObj, title, headerX, statusY, 0xFFFF8484); + this.drawString(this.fontRendererObj, title, headerX, statusY, ColorUtils.ARGB_FFFF8484.getColor()); this.drawString( this.fontRendererObj, GuidebookText.SceneEditorTextSyncHint.text(), @@ -1380,7 +1540,7 @@ private void drawMarkdownResizeHandle(int mouseX, int mouseY) { handleBounds.y() + 8, lineLeft + 2, handleBounds.bottom() - 8, - highlighted ? 0xFF00CAF2 : 0x66464A50); + highlighted ? ColorUtils.ACCENT.getColor() : ColorUtils.ARGB_66464A50.getColor()); } private void drawCenterPanel(int mouseX, int mouseY) { @@ -1595,9 +1755,9 @@ private void drawPreviewContentTooltip(ContentTooltip tooltip, int mouseX, int m GL11.glDisable(GL11.GL_DEPTH_TEST); this.zLevel = 300.0F; itemRender.zLevel = 300.0F; - int bgColor = 0xF0100010; - int borderTop = 0x505000FF; - int borderBottom = 0x5028007F; + int bgColor = ColorUtils.ARGB_F0100010.getColor(); + int borderTop = ColorUtils.ARGB_505000FF.getColor(); + int borderBottom = ColorUtils.ARGB_5028007F.getColor(); drawGradientRect( tooltipX - pad, tooltipY - pad, @@ -1661,8 +1821,6 @@ private void drawPreviewContentTooltip(ContentTooltip tooltip, int mouseX, int m tooltipY + tooltipHeight + pad - 1, borderTop, borderBottom); - - previewTooltipRenderContext.setLightDarkMode(LightDarkMode.LIGHT_MODE); previewTooltipRenderContext.setViewport(new LytRect(0, 0, tooltipWidth, tooltipHeight)); previewTooltipRenderContext.setScreenHeight(this.height); previewTooltipRenderContext.setDocumentOrigin(tooltipX, tooltipY); @@ -1718,10 +1876,20 @@ private void drawPreviewFrameOverlay() { if (frameRect.isEmpty()) { return; } - drawRect(frameRect.x(), frameRect.y(), frameRect.right(), frameRect.y() + 1, 0xFF00CAF2); - drawRect(frameRect.x(), frameRect.bottom() - 1, frameRect.right(), frameRect.bottom(), 0xFF00CAF2); - drawRect(frameRect.x(), frameRect.y(), frameRect.x() + 1, frameRect.bottom(), 0xFF00CAF2); - drawRect(frameRect.right() - 1, frameRect.y(), frameRect.right(), frameRect.bottom(), 0xFF00CAF2); + drawRect(frameRect.x(), frameRect.y(), frameRect.right(), frameRect.y() + 1, ColorUtils.ACCENT.getColor()); + drawRect( + frameRect.x(), + frameRect.bottom() - 1, + frameRect.right(), + frameRect.bottom(), + ColorUtils.ACCENT.getColor()); + drawRect(frameRect.x(), frameRect.y(), frameRect.x() + 1, frameRect.bottom(), ColorUtils.ACCENT.getColor()); + drawRect( + frameRect.right() - 1, + frameRect.y(), + frameRect.right(), + frameRect.bottom(), + ColorUtils.ACCENT.getColor()); this.drawString( this.fontRendererObj, session.getSceneModel() @@ -1749,7 +1917,12 @@ private void drawRightPanel(int mouseX, int mouseY) { settingsBoxX + settingsBoxWidth, settingsBoxY + settingsBoxHeight, PANEL_INNER_COLOR); - drawBorder(settingsBoxX, settingsBoxY, settingsBoxWidth, settingsBoxHeight, 0xFF464A50); + drawBorder( + settingsBoxX, + settingsBoxY, + settingsBoxWidth, + settingsBoxHeight, + ColorUtils.ARGB_FF464A50.getColor()); drawSettingsTabs(mouseX, mouseY); for (NumericParameterRow row : getVisibleParameterRows()) { @@ -1776,14 +1949,14 @@ private void drawPanelHeader(int x, int y, String title) { private void drawRightPanelToggle(int mouseX, int mouseY) { LytRect toggleBounds = screenLayout.rightToggle(); boolean hovered = toggleBounds.contains(mouseX, mouseY); - int backgroundColor = hovered ? 0xC824303A : 0xA014161A; + int backgroundColor = hovered ? ColorUtils.ARGB_C824303A.getColor() : ColorUtils.ARGB_A014161A.getColor(); drawRect(toggleBounds.x(), toggleBounds.y(), toggleBounds.right(), toggleBounds.bottom(), backgroundColor); drawBorder( toggleBounds.x(), toggleBounds.y(), toggleBounds.width(), toggleBounds.height(), - hovered ? 0xFF00CAF2 : INPUT_BORDER_COLOR); + hovered ? ColorUtils.ACCENT.getColor() : INPUT_BORDER_COLOR); String arrow = rightPanelCollapsed ? "<" : ">"; int arrowX = toggleBounds.x() + (toggleBounds.width() - this.fontRendererObj.getStringWidth(arrow)) / 2; int arrowY = toggleBounds.y() + toggleBounds.height() / 2 - 4; @@ -1793,14 +1966,14 @@ private void drawRightPanelToggle(int mouseX, int mouseY) { private void drawMarkdownToggle(int mouseX, int mouseY) { LytRect toggleBounds = screenLayout.markdownToggle(); boolean hovered = toggleBounds.contains(mouseX, mouseY); - int backgroundColor = hovered ? 0xC824303A : 0xA014161A; + int backgroundColor = hovered ? ColorUtils.ARGB_C824303A.getColor() : ColorUtils.ARGB_A014161A.getColor(); drawRect(toggleBounds.x(), toggleBounds.y(), toggleBounds.right(), toggleBounds.bottom(), backgroundColor); drawBorder( toggleBounds.x(), toggleBounds.y(), toggleBounds.width(), toggleBounds.height(), - hovered ? 0xFF00CAF2 : INPUT_BORDER_COLOR); + hovered ? ColorUtils.ACCENT.getColor() : INPUT_BORDER_COLOR); String arrow = markdownPanelState.isExpanded() ? "<" : ">"; int arrowX = toggleBounds.x() + (toggleBounds.width() - this.fontRendererObj.getStringWidth(arrow)) / 2; int arrowY = toggleBounds.y() + toggleBounds.height() / 2 - 4; @@ -1819,7 +1992,12 @@ private void drawSettingsTabs(int mouseX, int mouseY) { int backgroundColor = active ? SETTINGS_TAB_ACTIVE_COLOR : hovered ? SETTINGS_TAB_HOVER_COLOR : SETTINGS_TAB_INACTIVE_COLOR; drawRect(tabX, tabY, tabX + tabWidth, tabY + SETTINGS_TAB_HEIGHT, backgroundColor); - drawBorder(tabX, tabY, tabWidth, SETTINGS_TAB_HEIGHT, active ? 0xFF00CAF2 : 0xFF3E434A); + drawBorder( + tabX, + tabY, + tabWidth, + SETTINGS_TAB_HEIGHT, + active ? ColorUtils.ACCENT.getColor() : ColorUtils.INPUT_BORDER.getColor()); String label = this.fontRendererObj.trimStringToWidth( tab.getTextKey() .text(), @@ -1835,14 +2013,14 @@ private void drawSettingsTabs(int mouseX, int mouseY) { } private void drawTiledBackground() { - drawRect(0, 0, this.width, this.height, 0x34101018); + drawRect(0, 0, this.width, this.height, ColorUtils.ARGB_34101018.getColor()); mc.getTextureManager() .bindTexture(BG_TEXTURE); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 0.7f); + ColorUtils.applyGlColor(ColorUtils.WHITE_70.getColor()); float tile = 16f; float uMax = this.width / tile; float vMax = this.height / tile; @@ -1853,7 +2031,7 @@ private void drawTiledBackground() { tess.addVertexWithUV(this.width, 0, 0, uMax, 0); tess.addVertexWithUV(0, 0, 0, 0, 0); tess.draw(); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } private void drawBorder(int x, int y, int width, int height, int color) { @@ -1872,7 +2050,8 @@ private void drawCompactTextFieldValue(GuiTextField inputField, String text) { return; } String visibleText = this.fontRendererObj.trimStringToWidth(text, Math.max(0, inputField.width)); - this.fontRendererObj.drawString(visibleText, inputField.xPosition, inputField.yPosition, 0xF0F0F0); + this.fontRendererObj + .drawString(visibleText, inputField.xPosition, inputField.yPosition, ColorUtils.ARGB_F0F0F0.getColor()); } private void requestCloseEditor() { @@ -1922,7 +2101,14 @@ private void attemptSaveAndClose() { } private void attemptSaveWithoutClose() { - performSave(); + performSaveResult(); + } + + private void attemptExportSnbt() { + SceneEditorSaveService.SaveResult result = performSaveResult(); + if (result != null && ModConfig.ui.sceneEditorExportOpenFolderAfterExport) { + openStructureFolder(result); + } } private void copyGameScene() { @@ -2031,8 +2217,28 @@ private void appendBlockImageAttribute(StringBuilder builder, String name, @Null } private boolean performSave() { + return performSaveResult() != null; + } + + private void syncRegisteredToolbarButtons() { + for (Object buttonObject : this.buttonList) { + if (!(buttonObject instanceof GuideIconButton button)) { + continue; + } + SceneEditorToolbarButton descriptor = registeredToolbarButtons.get(button.id); + if (descriptor != null) { + button.visible = descriptor.visible(); + button.enabled = descriptor.enabled(); + button.setCustomTooltip(descriptor.label()); + button.setCustomIcon(descriptor.icon()); + } + } + } + + @Nullable + private SceneEditorSaveService.SaveResult performSaveResult() { if (!commitPendingEditorsForClose()) { - return false; + return null; } SceneEditorSaveService.SaveResult result = saveService.save(session, this.mc.thePlayer); if (result.isSuccess()) { @@ -2041,10 +2247,26 @@ private boolean performSave() { new ChatComponentTranslation(GuidebookText.SceneEditorMarkdownInvalidSaveHint.getTranslationKey())); } closeConfirmErrorText = null; - return true; + return result; } closeConfirmErrorText = GuidebookText.SceneEditorSaveFailure.text(extractErrorMessage(result.getError())); - return false; + return null; + } + + private void saveAndOpenStructureFolder() { + SceneEditorSaveService.SaveResult result = performSaveResult(); + if (result == null) { + return; + } + openStructureFolder(result); + } + + private void openStructureFolder(SceneEditorSaveService.SaveResult result) { + result.getStructurePath() + .map(Path::getParent) + .filter(Objects::nonNull) + .filter(Files::isDirectory) + .ifPresent(SceneEditorFolderOpener::open); } private String extractErrorMessage(@Nullable Throwable throwable) { @@ -2208,8 +2430,13 @@ private void drawCloseConfirmButton(CloseConfirmAction action, int mouseX, int m bounds.y(), bounds.right(), bounds.bottom(), - hovered ? CLOSE_DIALOG_HOVER : ELEMENT_ROW_BACKGROUND); - drawBorder(bounds.x(), bounds.y(), bounds.width(), bounds.height(), hovered ? 0xFF00CAF2 : INPUT_BORDER_COLOR); + hovered ? CLOSE_DIALOG_HOVER : ColorUtils.ELEMENT_ROW.getColor()); + drawBorder( + bounds.x(), + bounds.y(), + bounds.width(), + bounds.height(), + hovered ? ColorUtils.ACCENT.getColor() : INPUT_BORDER_COLOR); this.drawCenteredString( this.fontRendererObj, action.text() @@ -2794,7 +3021,8 @@ private void drawInteractiveToggle() { private void drawPreviewFrameButton() { boolean hovered = isInsidePreviewFrameButton(currentMouseX(), currentMouseY()); - int backgroundColor = previewFrameOverlayVisible ? 0xA61C252E : hovered ? 0x7A1C252E : 0x5512181C; + int backgroundColor = previewFrameOverlayVisible ? ColorUtils.TAB_HOVER.getColor() + : hovered ? ColorUtils.ARGB_7A1C252E.getColor() : ColorUtils.ARGB_5512181C.getColor(); drawRect( previewFrameButtonX, previewFrameButtonY, @@ -2806,7 +3034,7 @@ private void drawPreviewFrameButton() { previewFrameButtonY, PREVIEW_FRAME_BUTTON_WIDTH, PREVIEW_FRAME_BUTTON_HEIGHT, - previewFrameOverlayVisible ? 0xFF00CAF2 : INPUT_BORDER_COLOR); + previewFrameOverlayVisible ? ColorUtils.ACCENT.getColor() : INPUT_BORDER_COLOR); this.drawCenteredString( this.fontRendererObj, GuidebookText.SceneEditorPreviewFrame.text(), @@ -2816,9 +3044,9 @@ private void drawPreviewFrameButton() { } private void drawTextActionButton(int x, int y, int width, int height, String text, boolean hovered) { - int backgroundColor = hovered ? 0x7A1C252E : 0x5512181C; + int backgroundColor = hovered ? ColorUtils.ARGB_7A1C252E.getColor() : ColorUtils.ARGB_5512181C.getColor(); drawRect(x, y, x + width, y + height, backgroundColor); - drawBorder(x, y, width, height, hovered ? 0xFF00CAF2 : INPUT_BORDER_COLOR); + drawBorder(x, y, width, height, hovered ? ColorUtils.ACCENT.getColor() : INPUT_BORDER_COLOR); this.drawCenteredString(this.fontRendererObj, text, x + width / 2, y + 3, PANEL_HEADER_COLOR); } @@ -2931,7 +3159,12 @@ private void drawElementPanel(int mouseX, int mouseY) { elementsBoxX + elementsBoxWidth, elementsBoxY + elementsBoxHeight, PANEL_INNER_COLOR); - drawBorder(elementsBoxX, elementsBoxY, elementsBoxWidth, elementsBoxHeight, 0xFF464A50); + drawBorder( + elementsBoxX, + elementsBoxY, + elementsBoxWidth, + elementsBoxHeight, + ColorUtils.ARGB_FF464A50.getColor()); this.drawString( this.fontRendererObj, @@ -3040,13 +3273,13 @@ private void drawMarkdownContextMenu(int mouseX, int mouseY) { markdownContextMenuY, markdownContextMenuX + MARKDOWN_CONTEXT_MENU_WIDTH, markdownContextMenuY + MARKDOWN_CONTEXT_MENU_ROW_HEIGHT, - ELEMENT_MENU_BACKGROUND); + ColorUtils.ELEMENT_MENU.getColor()); drawBorder( markdownContextMenuX, markdownContextMenuY, MARKDOWN_CONTEXT_MENU_WIDTH, MARKDOWN_CONTEXT_MENU_ROW_HEIGHT, - 0xFF3E434A); + ColorUtils.INPUT_BORDER.getColor()); LytRect menuBounds = new LytRect( markdownContextMenuX, markdownContextMenuY, @@ -3071,9 +3304,14 @@ private void drawElementRow(SceneEditorElementModel element, int x, int y, int w .getSelectedElementId()); boolean expanded = element.getId() .equals(expandedElementId); - int rowColor = selected ? ELEMENT_ROW_SELECTED : ELEMENT_ROW_BACKGROUND; + int rowColor = selected ? ColorUtils.ELEMENT_ROW_SELECTED.getColor() : ColorUtils.ELEMENT_ROW.getColor(); drawRect(x, y, x + width, y + ELEMENT_ROW_HEIGHT, rowColor); - drawBorder(x, y, width, ELEMENT_ROW_HEIGHT, selected ? 0xFF00CAF2 : 0xFF3E434A); + drawBorder( + x, + y, + width, + ELEMENT_ROW_HEIGHT, + selected ? ColorUtils.ACCENT.getColor() : ColorUtils.INPUT_BORDER.getColor()); int arrowX = x + 4; int arrowY = y + 6; @@ -3093,8 +3331,14 @@ private void drawElementRow(SceneEditorElementModel element, int x, int y, int w int deleteX = x + width - 30; int eyeX = x + width - 14; - GuideIconButton - .drawIcon(this.mc, GuideIconButton.Role.SCENE_EDITOR_DELETE_ELEMENT, deleteX, y + 2, 12, 12, 0xC0FFFFFF); + GuideIconButton.drawIcon( + this.mc, + GuideIconButton.Role.SCENE_EDITOR_DELETE_ELEMENT, + deleteX, + y + 2, + 12, + 12, + ColorUtils.ARGB_C0FFFFFF.getColor()); GuideIconButton.drawIcon( this.mc, element.isVisible() ? GuideIconButton.Role.SCENE_EDITOR_HIDE_ELEMENT @@ -3103,7 +3347,7 @@ private void drawElementRow(SceneEditorElementModel element, int x, int y, int w y + 2, 12, 12, - 0xC0FFFFFF); + ColorUtils.ARGB_C0FFFFFF.getColor()); if (!expanded) { return; @@ -3111,8 +3355,8 @@ private void drawElementRow(SceneEditorElementModel element, int x, int y, int w int expandedY = y + ELEMENT_ROW_HEIGHT; int expandedHeight = Math.max(0, totalHeight - ELEMENT_ROW_HEIGHT); - drawRect(x, expandedY, x + width, expandedY + expandedHeight, ELEMENT_ROW_EXPANDED); - drawBorder(x, expandedY, width, expandedHeight, 0xFF2D3137); + drawRect(x, expandedY, x + width, expandedY + expandedHeight, ColorUtils.ELEMENT_ROW_EXPANDED.getColor()); + drawBorder(x, expandedY, width, expandedHeight, ColorUtils.ARGB_FF2D3137.getColor()); if (expandedElementEditor != null && element.getId() .equals(expandedElementEditor.elementId)) { expandedElementEditor.setBounds(x, expandedY, width, expandedHeight); @@ -3725,8 +3969,18 @@ private SceneEditorElementType addElementMenuTypeAt(int mouseX, int mouseY) { private void drawAddElementMenu(int mouseX, int mouseY) { LytRect menuBounds = getAddElementMenuBounds(); - drawRect(menuBounds.x(), menuBounds.y(), menuBounds.right(), menuBounds.bottom(), ELEMENT_MENU_BACKGROUND); - drawBorder(menuBounds.x(), menuBounds.y(), menuBounds.width(), menuBounds.height(), 0xFF3E434A); + drawRect( + menuBounds.x(), + menuBounds.y(), + menuBounds.right(), + menuBounds.bottom(), + ColorUtils.ELEMENT_MENU.getColor()); + drawBorder( + menuBounds.x(), + menuBounds.y(), + menuBounds.width(), + menuBounds.height(), + ColorUtils.INPUT_BORDER.getColor()); List elementTypes = SceneEditorElementType.values(); for (int i = 0; i < elementTypes.size(); i++) { SceneEditorElementType type = elementTypes.get(i); @@ -3757,14 +4011,14 @@ private boolean isInsideExportButton(int mouseX, int mouseY) { } private LytRect getExportMenuBounds() { + List entries = exportMenuEntries(); if (exportButton == null) { - return new LytRect(TOOLBAR_MARGIN_X, TOOLBAR_Y + GuideIconButton.HEIGHT, EXPORT_MENU_WIDTH, 0); + return new LytRect(TOOLBAR_MARGIN_X, TOOLBAR_Y + GuideIconButton.HEIGHT, menuWidth(entries), 0); } - int rows = hasBlockImageExport() ? 3 : 2; return SceneEditorPopupLayout.placeBelowAnchor( new LytRect(exportButton.xPosition, exportButton.yPosition, exportButton.width, exportButton.height), - EXPORT_MENU_WIDTH, - rows * ELEMENT_MENU_ROW_HEIGHT, + menuWidth(entries), + menuHeight(entries), this.width, this.height, 4); @@ -3775,20 +4029,27 @@ private boolean isInsideExportMenu(int mouseX, int mouseY) { } @Nullable - private ExportMenuOption exportMenuOptionAt(int mouseX, int mouseY) { + private MenuEntry exportMenuOptionAt(int mouseX, int mouseY) { if (!isInsideExportMenu(mouseX, mouseY)) { return null; } - int index = (mouseY - getExportMenuBounds().y()) / ELEMENT_MENU_ROW_HEIGHT; - ExportMenuOption[] options = exportMenuOptions(); - return index >= 0 && index < options.length ? options[index] : null; + List options = exportMenuEntries(); + return menuEntryAtY(options, getExportMenuBounds().y(), mouseY); } - private ExportMenuOption[] exportMenuOptions() { - return hasBlockImageExport() - ? new ExportMenuOption[] { ExportMenuOption.SNBT, ExportMenuOption.GAME_SCENE, - ExportMenuOption.BLOCK_IMAGE } - : new ExportMenuOption[] { ExportMenuOption.SNBT, ExportMenuOption.GAME_SCENE }; + private List exportMenuEntries() { + List entries = new ArrayList<>(); + SceneEditorActionContext context = createActionContext(); + for (SceneEditorMenuItem item : defaultControlRegistry.createExportItems(context, this::hasBlockImageExport)) { + entries.add(MenuEntry.external(item, context)); + } + for (SceneEditorMenuItem item : SceneEditorMenuRegistry.snapshot(SceneEditorMenuRegistry.MENU_EXPORT)) { + entries.add(MenuEntry.external(item, context)); + } + entries.sort( + Comparator.comparingInt(MenuEntry::order) + .thenComparing(entry -> entry.id)); + return entries; } private boolean hasBlockImageExport() { @@ -3851,7 +4112,252 @@ private void drawMenuHover(LytRect menuBounds, int mouseX, int mouseY, int rowY, int top = Math.max(menuBounds.y() + 1, rowY); int bottom = Math.min(menuBounds.bottom() - 1, rowY + rowHeight); if (bottom > top) { - drawRect(menuBounds.x() + 1, top, menuBounds.right() - 1, bottom, ELEMENT_MENU_HOVER); + drawRect(menuBounds.x() + 1, top, menuBounds.right() - 1, bottom, ColorUtils.ELEMENT_MENU_HOVER.getColor()); + } + } + + private int menuWidth(List entries) { + int width = GuideIconButton.WIDTH + MENU_HORIZONTAL_PADDING; + for (MenuEntry entry : entries) { + int leftPadding = entry.hasCheckBox() ? 30 : 8; + int widgetWidth = entry.widget() == null ? 0 + : entry.widget() + .preferredWidth(); + width = Math.max( + width, + Math.max(widgetWidth, this.fontRendererObj.getStringWidth(entry.label()) + leftPadding + 8)); + } + return Math.min(Math.max(width, GuideIconButton.WIDTH), Math.max(GuideIconButton.WIDTH, this.width - 8)); + } + + private int menuHeight(List entries) { + int height = 0; + for (MenuEntry entry : entries) { + height += entry.height(); + } + return height; + } + + @Nullable + private MenuEntry menuEntryAtY(List entries, int top, int mouseY) { + int rowY = top; + for (MenuEntry entry : entries) { + int height = entry.height(); + if (mouseY >= rowY && mouseY < rowY + height) { + return entry; + } + rowY += height; + } + return null; + } + + private int menuEntryY(List entries, MenuEntry target, int top) { + int rowY = top; + for (MenuEntry entry : entries) { + if (entry == target || entry.id.equals(target.id)) { + return rowY; + } + rowY += entry.height(); + } + return -1; + } + + private List builtInMenuEntries(String menuId) { + if (SceneEditorMenuRegistry.MENU_EXPORT.equals(menuId)) { + return exportMenuEntries(); + } + if (SceneEditorMenuRegistry.MENU_SNAP.equals(menuId)) { + return snapModeMenuEntries(); + } + return List.of(); + } + + private LytRect builtInMenuBounds(String menuId) { + return SceneEditorMenuRegistry.MENU_EXPORT.equals(menuId) ? getExportMenuBounds() : getSnapModeMenuBounds(); + } + + private List registeredMenuEntries() { + if (registeredMenuOpen == null) return List.of(); + List entries = new ArrayList<>(); + for (SceneEditorMenuItem item : SceneEditorMenuRegistry.snapshot(registeredMenuOpen)) { + entries.add(MenuEntry.external(item, createActionContext())); + } + return entries; + } + + private LytRect getRegisteredMenuBounds() { + List entries = registeredMenuEntries(); + GuideIconButton anchor = registeredToolbarButtonWidgets.get(registeredMenuAnchorId); + if (anchor == null) + return new LytRect(TOOLBAR_MARGIN_X, TOOLBAR_Y + GuideIconButton.HEIGHT, menuWidth(entries), 0); + return SceneEditorPopupLayout.placeBelowAnchor( + new LytRect(anchor.xPosition, anchor.yPosition, anchor.width, anchor.height), + menuWidth(entries), + menuHeight(entries), + this.width, + this.height, + 4); + } + + private int registeredMenuEntryY(MenuEntry target, LytRect bounds) { + return menuEntryY(registeredMenuEntries(), target, bounds.y()); + } + + private boolean handleRegisteredMenuClick(int mouseX, int mouseY, int button) { + if (registeredMenuOpen == null) return false; + LytRect bounds = getRegisteredMenuBounds(); + GuideIconButton anchor = registeredToolbarButtonWidgets.get(registeredMenuAnchorId); + boolean inside = bounds.contains(mouseX, mouseY); + if (button == 0 && inside) { + int y = bounds.y(); + for (MenuEntry entry : registeredMenuEntries()) { + int height = entry.height(); + if (mouseY >= y && mouseY < y + height) { + if (entry.widget() != null) { + if (entry.enabled() && entry.widget() + .triggerClick( + createActionContext(), + bounds.x(), + y, + bounds.width(), + height, + mouseX, + mouseY, + button)) { + activeRegisteredWidget = entry; + return true; + } + } else if (entry.enabled()) { + entry.activate(); + closeRegisteredMenu(); + return true; + } + return true; + } + y += height; + } + } + if (button == 1 && anchor != null + && anchor.visible + && anchor.xPosition <= mouseX + && mouseX < anchor.xPosition + anchor.width + && anchor.yPosition <= mouseY + && mouseY < anchor.yPosition + anchor.height) { + closeRegisteredMenu(); + return true; + } + if (!inside && (anchor == null || mouseX < anchor.xPosition + || mouseX >= anchor.xPosition + anchor.width + || mouseY < anchor.yPosition + || mouseY >= anchor.yPosition + anchor.height)) { + closeRegisteredMenu(); + } + return false; + } + + private void drawRegisteredMenu(int mouseX, int mouseY) { + List entries = registeredMenuEntries(); + LytRect bounds = getRegisteredMenuBounds(); + drawRect(bounds.x(), bounds.y(), bounds.right(), bounds.bottom(), ColorUtils.ELEMENT_MENU.getColor()); + drawBorder(bounds.x(), bounds.y(), bounds.width(), bounds.height(), ColorUtils.INPUT_BORDER.getColor()); + int y = bounds.y(); + for (MenuEntry entry : entries) { + drawMenuHover(bounds, mouseX, mouseY, y, entry.height()); + drawMenuEntry(bounds, entry, y, mouseX, mouseY); + y += entry.height(); + } + } + + private SceneEditorMenuWidgetContext menuWidgetContext() { + return new SceneEditorMenuWidgetContext() { + + public Minecraft minecraft() { + return mc; + } + + public FontRenderer fontRenderer() { + return fontRendererObj; + } + + public void drawRect(int left, int top, int right, int bottom, int color) { + SceneEditorScreen.this.drawRect(left, top, right, bottom, color); + } + + public void drawBorder(int left, int top, int width, int height, int color) { + SceneEditorScreen.this.drawBorder(left, top, width, height, color); + } + + public void drawString(String text, int x, int y, int color) { + SceneEditorScreen.this.drawString(fontRendererObj, text, x, y, color); + } + }; + } + + private static class MenuEntry { + + private final String id; + private final int order; + private final Supplier labelSupplier; + private final BooleanSupplier enabledSupplier; + private final BooleanSupplier checkedSupplier; + private final boolean checkBox; + private final SceneEditorMenuWidget widget; + private final Runnable action; + + private MenuEntry(String id, int order, Supplier labelSupplier, BooleanSupplier enabledSupplier, + BooleanSupplier checkedSupplier, SceneEditorMenuWidget widget, Runnable action) { + this.id = id; + this.order = order; + this.labelSupplier = labelSupplier; + this.enabledSupplier = enabledSupplier; + this.checkedSupplier = checkedSupplier; + this.checkBox = checkedSupplier != null; + this.widget = widget; + this.action = action; + } + + private static MenuEntry external(SceneEditorMenuItem item, SceneEditorActionContext context) { + return new MenuEntry( + item.id(), + item.order(), + item::label, + item::enabled, + item.hasCheckBox() ? item::checked : null, + item.widget(), + () -> item.triggerClick(context)); + } + + private String label() { + String value = labelSupplier.get(); + return value == null ? id : value; + } + + private boolean enabled() { + return enabledSupplier.getAsBoolean(); + } + + private boolean checked() { + return checkedSupplier != null && checkedSupplier.getAsBoolean(); + } + + private boolean hasCheckBox() { + return checkBox; + } + + private SceneEditorMenuWidget widget() { + return widget; + } + + private int height() { + return widget == null ? ELEMENT_MENU_ROW_HEIGHT : Math.max(ELEMENT_MENU_ROW_HEIGHT, widget.height()); + } + + private int order() { + return order; + } + + private void activate() { + action.run(); } } @@ -3859,13 +4365,25 @@ private boolean handleExportMenuClick(int mouseX, int mouseY, int button) { if (!exportMenuOpen) { return false; } - ExportMenuOption option = exportMenuOptionAt(mouseX, mouseY); - if (button == 0 && option != null) { - exportMenuOpen = false; - switch (option) { - case SNBT -> attemptSaveWithoutClose(); - case GAME_SCENE -> copyGameScene(); - case BLOCK_IMAGE -> copyBlockImage(); + MenuEntry option = exportMenuOptionAt(mouseX, mouseY); + if (button == 0 && option != null && option.enabled()) { + if (option.widget() != null) { + if (option.widget() + .triggerClick( + createActionContext(), + getExportMenuBounds().x(), + menuEntryY(exportMenuEntries(), option, getExportMenuBounds().y()), + getExportMenuBounds().width(), + option.height(), + mouseX, + mouseY, + button)) { + activeBuiltInWidget = option; + activeBuiltInWidgetMenu = SceneEditorMenuRegistry.MENU_EXPORT; + } + } else { + exportMenuOpen = false; + option.activate(); } return true; } @@ -3877,20 +4395,60 @@ private boolean handleExportMenuClick(int mouseX, int mouseY, int button) { private void drawExportMenu(int mouseX, int mouseY) { LytRect menuBounds = getExportMenuBounds(); - drawRect(menuBounds.x(), menuBounds.y(), menuBounds.right(), menuBounds.bottom(), ELEMENT_MENU_BACKGROUND); - drawBorder(menuBounds.x(), menuBounds.y(), menuBounds.width(), menuBounds.height(), 0xFF3E434A); - ExportMenuOption[] options = exportMenuOptions(); - for (int i = 0; i < options.length; i++) { - int rowY = menuBounds.y() + i * ELEMENT_MENU_ROW_HEIGHT; - drawMenuHover(menuBounds, mouseX, mouseY, rowY, ELEMENT_MENU_ROW_HEIGHT); - this.drawString( - this.fontRendererObj, - options[i].text() - .text(), - menuBounds.x() + 8, - rowY + 5, - PANEL_HEADER_COLOR); + drawRect( + menuBounds.x(), + menuBounds.y(), + menuBounds.right(), + menuBounds.bottom(), + ColorUtils.ELEMENT_MENU.getColor()); + drawBorder( + menuBounds.x(), + menuBounds.y(), + menuBounds.width(), + menuBounds.height(), + ColorUtils.INPUT_BORDER.getColor()); + List options = exportMenuEntries(); + int rowY = menuBounds.y(); + for (MenuEntry option : options) { + int rowHeight = option.height(); + drawMenuHover(menuBounds, mouseX, mouseY, rowY, rowHeight); + drawMenuEntry(menuBounds, option, rowY, mouseX, mouseY); + rowY += rowHeight; + } + } + + private void drawMenuEntry(LytRect menuBounds, MenuEntry option, int rowY, int mouseX, int mouseY) { + boolean hovered = mouseX >= menuBounds.x() && mouseX < menuBounds.right() + && mouseY >= rowY + && mouseY < rowY + option.height(); + if (option.widget() != null) { + option.widget() + .render( + menuWidgetContext(), + menuBounds.x(), + rowY, + menuBounds.width(), + option.height(), + hovered, + option.enabled()); + return; + } + int textX = menuBounds.x() + (option.hasCheckBox() ? 22 : 8); + if (option.hasCheckBox()) { + int boxX = menuBounds.x() + 6; + int boxY = rowY + 3; + drawRect(boxX, boxY, boxX + 10, boxY + 10, CHECKBOX_BACKGROUND_COLOR); + drawBorder(boxX, boxY, 10, 10, option.checked() ? CHECKBOX_CHECK_COLOR : INPUT_BORDER_COLOR); + if (option.checked()) { + drawRect(boxX + 2, boxY + 2, boxX + 8, boxY + 8, CHECKBOX_CHECK_COLOR); + } } + drawString( + fontRendererObj, + option.label(), + textX, + rowY + 5, + option.enabled() ? PANEL_HEADER_COLOR : PANEL_SUBTLE_TEXT); } private LytRect getScreenshotMenuBounds() { @@ -3998,8 +4556,18 @@ private boolean handleScreenshotMenuClick(int mouseX, int mouseY, int button) { private void drawScreenshotMenu(int mouseX, int mouseY) { LytRect menuBounds = getScreenshotMenuBounds(); - drawRect(menuBounds.x(), menuBounds.y(), menuBounds.right(), menuBounds.bottom(), ELEMENT_MENU_BACKGROUND); - drawBorder(menuBounds.x(), menuBounds.y(), menuBounds.width(), menuBounds.height(), 0xFF3E434A); + drawRect( + menuBounds.x(), + menuBounds.y(), + menuBounds.right(), + menuBounds.bottom(), + ColorUtils.ELEMENT_MENU.getColor()); + drawBorder( + menuBounds.x(), + menuBounds.y(), + menuBounds.width(), + menuBounds.height(), + ColorUtils.INPUT_BORDER.getColor()); int rowTop = menuBounds.y() + SceneEditorScreenshotMenuController.MENU_PADDING; for (int i = 0; i < SceneEditorScreenshotFormat.values().length; i++) { @@ -4087,14 +4655,14 @@ private boolean isInsideSnapButton(int mouseX, int mouseY) { } private LytRect getSnapModeMenuBounds() { + List entries = snapModeMenuEntries(); if (snapButton == null) { - return new LytRect(TOOLBAR_MARGIN_X, TOOLBAR_Y + GuideIconButton.HEIGHT, SNAP_MENU_WIDTH, 0); + return new LytRect(TOOLBAR_MARGIN_X, TOOLBAR_Y + GuideIconButton.HEIGHT, menuWidth(entries), 0); } - int menuHeight = SnapModeOption.values().length * ELEMENT_MENU_ROW_HEIGHT; return SceneEditorPopupLayout.placeBelowAnchor( new LytRect(snapButton.xPosition, snapButton.yPosition, snapButton.width, snapButton.height), - SNAP_MENU_WIDTH, - menuHeight, + menuWidth(entries), + menuHeight(entries), this.width, this.height, 4); @@ -4105,17 +4673,28 @@ private boolean isInsideSnapModeMenu(int mouseX, int mouseY) { } @Nullable - private SnapModeOption snapModeOptionAt(int mouseX, int mouseY) { + private MenuEntry snapModeOptionAt(int mouseX, int mouseY) { if (!isInsideSnapModeMenu(mouseX, mouseY)) { return null; } LytRect menuBounds = getSnapModeMenuBounds(); - int index = (mouseY - menuBounds.y()) / ELEMENT_MENU_ROW_HEIGHT; - SnapModeOption[] values = SnapModeOption.values(); - if (index < 0 || index >= values.length) { - return null; + List values = snapModeMenuEntries(); + return menuEntryAtY(values, menuBounds.y(), mouseY); + } + + private List snapModeMenuEntries() { + List entries = new ArrayList<>(); + SceneEditorActionContext context = createActionContext(); + for (SceneEditorMenuItem item : defaultControlRegistry.createSnapItems(context)) { + entries.add(MenuEntry.external(item, context)); } - return values[index]; + for (SceneEditorMenuItem item : SceneEditorMenuRegistry.snapshot(SceneEditorMenuRegistry.MENU_SNAP)) { + entries.add(MenuEntry.external(item, context)); + } + entries.sort( + Comparator.comparingInt(MenuEntry::order) + .thenComparing(entry -> entry.id)); + return entries; } private boolean handleSnapModeMenuClick(int mouseX, int mouseY, int button) { @@ -4123,10 +4702,26 @@ private boolean handleSnapModeMenuClick(int mouseX, int mouseY, int button) { return false; } if (button == 0) { - SnapModeOption option = snapModeOptionAt(mouseX, mouseY); - if (option != null) { - option.toggle(); - ModConfig.save(); + MenuEntry option = snapModeOptionAt(mouseX, mouseY); + if (option != null && option.enabled()) { + if (option.widget() != null) { + int entryY = menuEntryY(snapModeMenuEntries(), option, getSnapModeMenuBounds().y()); + if (option.widget() + .triggerClick( + createActionContext(), + getSnapModeMenuBounds().x(), + entryY, + getSnapModeMenuBounds().width(), + option.height(), + mouseX, + mouseY, + button)) { + activeBuiltInWidget = option; + activeBuiltInWidgetMenu = SceneEditorMenuRegistry.MENU_SNAP; + } + } else { + option.activate(); + } return true; } } @@ -4138,26 +4733,25 @@ private boolean handleSnapModeMenuClick(int mouseX, int mouseY, int button) { private void drawSnapModeMenu(int mouseX, int mouseY) { LytRect menuBounds = getSnapModeMenuBounds(); - drawRect(menuBounds.x(), menuBounds.y(), menuBounds.right(), menuBounds.bottom(), ELEMENT_MENU_BACKGROUND); - drawBorder(menuBounds.x(), menuBounds.y(), menuBounds.width(), menuBounds.height(), 0xFF3E434A); - for (int i = 0; i < SnapModeOption.values().length; i++) { - SnapModeOption option = SnapModeOption.values()[i]; - int rowY = menuBounds.y() + i * ELEMENT_MENU_ROW_HEIGHT; - drawMenuHover(menuBounds, mouseX, mouseY, rowY, ELEMENT_MENU_ROW_HEIGHT); - int boxX = menuBounds.x() + 6; - int boxY = rowY + 3; - drawRect(boxX, boxY, boxX + 10, boxY + 10, CHECKBOX_BACKGROUND_COLOR); - drawBorder(boxX, boxY, 10, 10, option.isEnabled() ? CHECKBOX_CHECK_COLOR : INPUT_BORDER_COLOR); - if (option.isEnabled()) { - drawRect(boxX + 2, boxY + 2, boxX + 8, boxY + 8, CHECKBOX_CHECK_COLOR); - } - this.drawString( - this.fontRendererObj, - option.text() - .text(), - menuBounds.x() + 22, - rowY + 5, - PANEL_HEADER_COLOR); + drawRect( + menuBounds.x(), + menuBounds.y(), + menuBounds.right(), + menuBounds.bottom(), + ColorUtils.ELEMENT_MENU.getColor()); + drawBorder( + menuBounds.x(), + menuBounds.y(), + menuBounds.width(), + menuBounds.height(), + ColorUtils.INPUT_BORDER.getColor()); + List options = snapModeMenuEntries(); + int rowY = menuBounds.y(); + for (MenuEntry option : options) { + int rowHeight = option.height(); + drawMenuHover(menuBounds, mouseX, mouseY, rowY, rowHeight); + drawMenuEntry(menuBounds, option, rowY, mouseX, mouseY); + rowY += rowHeight; } } @@ -4247,8 +4841,13 @@ private void drawElementContextMenu(int mouseX, int mouseY) { contextMenuY, contextMenuX + ELEMENT_CONTEXT_MENU_WIDTH, contextMenuY + menuHeight, - ELEMENT_MENU_BACKGROUND); - drawBorder(contextMenuX, contextMenuY, ELEMENT_CONTEXT_MENU_WIDTH, menuHeight, 0xFF3E434A); + ColorUtils.ELEMENT_MENU.getColor()); + drawBorder( + contextMenuX, + contextMenuY, + ELEMENT_CONTEXT_MENU_WIDTH, + menuHeight, + ColorUtils.INPUT_BORDER.getColor()); for (int i = 0; i < contextMenuActions.size(); i++) { int rowY = contextMenuY + i * ELEMENT_MENU_ROW_HEIGHT; drawMenuHover( @@ -4387,7 +4986,7 @@ private void drawElementReorderIndicator(List layouts) { } int lineX = layouts.getFirst().rowX; int lineWidth = layouts.getFirst().rowWidth; - drawRect(lineX, lineY - 1, lineX + lineWidth, lineY + 1, 0xFF00CAF2); + drawRect(lineX, lineY - 1, lineX + lineWidth, lineY + 1, ColorUtils.ACCENT.getColor()); } private boolean isInsideElementViewport(int mouseX, int mouseY) { @@ -4494,10 +5093,15 @@ private void drawElementScrollbar() { scrollbarBounds.y(), scrollbarBounds.right(), scrollbarBounds.bottom(), - 0x35101010); + ColorUtils.SCROLLBAR_TRACK.getColor()); SceneEditorVerticalScrollbar.Thumb thumb = getElementScrollbarThumb(); if (thumb != null) { - drawRect(scrollbarBounds.x(), thumb.start(), scrollbarBounds.right(), thumb.end(), 0xA0D8D8D8); + drawRect( + scrollbarBounds.x(), + thumb.start(), + scrollbarBounds.right(), + thumb.end(), + ColorUtils.SCROLLBAR_THUMB.getColor()); } } @@ -4516,8 +5120,8 @@ private void endScissor() { } private void drawElementTypeIcon(SceneEditorElementType type, int x, int y, boolean selected) { - int borderColor = selected ? 0xFF00CAF2 : 0xFF46505A; - drawRect(x, y, x + ELEMENT_ICON_SIZE, y + ELEMENT_ICON_SIZE, 0x33101012); + int borderColor = selected ? ColorUtils.ACCENT.getColor() : ColorUtils.ARGB_FF46505A.getColor(); + drawRect(x, y, x + ELEMENT_ICON_SIZE, y + ELEMENT_ICON_SIZE, ColorUtils.ARGB_33101012.getColor()); drawBorder(x, y, ELEMENT_ICON_SIZE, ELEMENT_ICON_SIZE, borderColor); if (type == SceneEditorElementType.BLOCK) { drawRect(x + 3, y + 3, x + 11, y + 11, type.getAccentColor()); @@ -4525,7 +5129,7 @@ private void drawElementTypeIcon(SceneEditorElementType type, int x, int y, bool } if (type == SceneEditorElementType.BOX) { drawBorder(x + 2, y + 2, 10, 10, type.getAccentColor()); - drawBorder(x + 4, y + 4, 6, 6, 0x88FFFFFF); + drawBorder(x + 4, y + 4, 6, 6, ColorUtils.ARGB_88FFFFFF.getColor()); return; } if (type == SceneEditorElementType.LINE) { @@ -4537,7 +5141,7 @@ private void drawElementTypeIcon(SceneEditorElementType type, int x, int y, bool if (type == SceneEditorElementType.DIAMOND && type.getIconPngPath() != null) { mc.getTextureManager() .bindTexture(new ResourceLocation(type.getIconPngPath())); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); Tessellator tess = Tessellator.instance; float uMax = 16f / 32f; tess.startDrawingQuads(); @@ -4568,7 +5172,8 @@ private String formatFloat(float value) { private GuideIconButton hoveredButton(int mouseX, int mouseY) { for (Object buttonObject : this.buttonList) { - if (buttonObject instanceof GuideIconButton button && mouseX >= button.xPosition + if (buttonObject instanceof GuideIconButton button && button.visible + && mouseX >= button.xPosition && mouseX < button.xPosition + button.width && mouseY >= button.yPosition && mouseY < button.yPosition + button.height) { @@ -5620,91 +6225,8 @@ private GuidebookText getText(SceneEditorElementModel element) { } } - private enum ExportMenuOption { - - SNBT(GuidebookText.SceneEditorExportSnbt), - GAME_SCENE(GuidebookText.SceneEditorCopyGameScene), - BLOCK_IMAGE(GuidebookText.SceneEditorCopyBlockImage); - - private final GuidebookText text; - - ExportMenuOption(GuidebookText text) { - this.text = text; - } - - private GuidebookText text() { - return text; - } - } - private record BlockImageExportData(String id, int meta, @Nullable String nbt) {} - private enum SnapModeOption { - - LINE(GuidebookText.SceneEditorSnapLine) { - - @Override - boolean isEnabled() { - return ModConfig.ui.sceneEditorSnapLineEnabled; - } - - @Override - void toggle() { - ModConfig.ui.sceneEditorSnapLineEnabled = !ModConfig.ui.sceneEditorSnapLineEnabled; - } - }, - POINT(GuidebookText.SceneEditorSnapPoint) { - - @Override - boolean isEnabled() { - return ModConfig.ui.sceneEditorSnapPointEnabled; - } - - @Override - void toggle() { - ModConfig.ui.sceneEditorSnapPointEnabled = !ModConfig.ui.sceneEditorSnapPointEnabled; - } - }, - FACE(GuidebookText.SceneEditorSnapFace) { - - @Override - boolean isEnabled() { - return ModConfig.ui.sceneEditorSnapFaceEnabled; - } - - @Override - void toggle() { - ModConfig.ui.sceneEditorSnapFaceEnabled = !ModConfig.ui.sceneEditorSnapFaceEnabled; - } - }, - CENTER(GuidebookText.SceneEditorSnapCenter) { - - @Override - boolean isEnabled() { - return ModConfig.ui.sceneEditorSnapCenterEnabled; - } - - @Override - void toggle() { - ModConfig.ui.sceneEditorSnapCenterEnabled = !ModConfig.ui.sceneEditorSnapCenterEnabled; - } - }; - - private final GuidebookText text; - - SnapModeOption(GuidebookText text) { - this.text = text; - } - - private GuidebookText text() { - return text; - } - - abstract boolean isEnabled(); - - abstract void toggle(); - } - private enum CloseConfirmAction { SAVE(GuidebookText.SceneEditorSave), diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ColorCandidate.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ColorCandidate.java index 86d5127c..0634b39c 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ColorCandidate.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ColorCandidate.java @@ -3,13 +3,15 @@ import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; +import com.hfstudio.guidenh.guide.color.ColorUtils; + public class ColorCandidate implements AutocompleteCandidate { private final String name; private final int color; private static final int SWATCH_SIZE = 12; private static final int TEXT_X = SWATCH_SIZE + 6; - private static final int TEXT_COLOR = 0xFFF0F0F0; + private static final int TEXT_COLOR = ColorUtils.TEXT.getColor(); public ColorCandidate(String name, int color) { this.name = name; @@ -40,8 +42,13 @@ public int renderWidth(FontRenderer fontRenderer) { public void render(FontRenderer fontRenderer, int x, int y, int width, boolean hovered) { // Draw color swatch int swatchY = y + (renderHeight() - SWATCH_SIZE) / 2; - Gui.drawRect(x, swatchY, x + SWATCH_SIZE, swatchY + SWATCH_SIZE, 0xFF000000 | color); - Gui.drawRect(x - 1, swatchY - 1, x + SWATCH_SIZE + 1, swatchY + SWATCH_SIZE + 1, 0xFF4D5661); + Gui.drawRect(x, swatchY, x + SWATCH_SIZE, swatchY + SWATCH_SIZE, ColorUtils.BLACK.getColor() | color); + Gui.drawRect( + x - 1, + swatchY - 1, + x + SWATCH_SIZE + 1, + swatchY + SWATCH_SIZE + 1, + ColorUtils.ARGB_FF4D5661.getColor()); // Draw name fontRenderer.drawString(name, x + TEXT_X, y + 3, TEXT_COLOR); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ColorProvider.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ColorProvider.java index 58d9e3d7..a1c49d8c 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ColorProvider.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ColorProvider.java @@ -7,7 +7,7 @@ import com.hfstudio.guidenh.guide.internal.editor.autocomplete.AutocompleteContext; -/** Suggests SymbolicColor names for <Color id> attributes. */ +/** Suggests ColorValue names for <Color id> attributes. */ public class ColorProvider implements AutocompleteProvider { private static final String[] SYMBOLIC_NAMES = { "LINK", "BODY_TEXT", "ERROR_TEXT", "CRAFTING_RECIPE_TYPE", diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ItemCandidate.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ItemCandidate.java index a274acbd..5daebd75 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ItemCandidate.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/ItemCandidate.java @@ -9,13 +9,15 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; +import com.hfstudio.guidenh.guide.color.ColorUtils; + public class ItemCandidate implements AutocompleteCandidate { private final String id; private final ItemStack stack; private static final int ICON_SIZE = 16; private static final int TEXT_X = ICON_SIZE + 2; - private static final int TEXT_COLOR = 0xFFF0F0F0; + private static final int TEXT_COLOR = ColorUtils.TEXT.getColor(); private static final RenderItem renderItem = new RenderItem(); public ItemCandidate(String id, ItemStack stack) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/RegistryCandidate.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/RegistryCandidate.java index e998b600..10f36dcb 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/RegistryCandidate.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/RegistryCandidate.java @@ -10,6 +10,8 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; +import com.hfstudio.guidenh.guide.color.ColorUtils; + /** Candidate displaying a registry key with optional item icon and subtitle. */ public class RegistryCandidate implements AutocompleteCandidate { @@ -20,8 +22,8 @@ public class RegistryCandidate implements AutocompleteCandidate { private final ItemStack icon; private static final int ICON_SIZE = 16; private static final int TEXT_X = ICON_SIZE + 2; - private static final int TEXT_COLOR = 0xFFF0F0F0; - private static final int SUBTITLE_COLOR = 0xFFA0A0A0; + private static final int TEXT_COLOR = ColorUtils.TEXT.getColor(); + private static final int SUBTITLE_COLOR = ColorUtils.ARGB_FFA0A0A0.getColor(); private static final RenderItem renderItem = new RenderItem(); public RegistryCandidate(String key) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/TextCandidate.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/TextCandidate.java index fd4cdb10..c08c44cf 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/TextCandidate.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/provider/TextCandidate.java @@ -2,10 +2,12 @@ import net.minecraft.client.gui.FontRenderer; +import com.hfstudio.guidenh.guide.color.ColorUtils; + public class TextCandidate implements AutocompleteCandidate { private final String text; - private static final int TEXT_COLOR = 0xFFF0F0F0; + private static final int TEXT_COLOR = ColorUtils.TEXT.getColor(); public TextCandidate(String text) { this.text = text; diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/ui/AutocompletePopup.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/ui/AutocompletePopup.java index 608148c3..7fbfadc2 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/ui/AutocompletePopup.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/autocomplete/ui/AutocompletePopup.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.internal.editor.autocomplete.provider.AutocompleteCandidate; import com.hfstudio.guidenh.guide.internal.editor.gui.SceneEditorPopupLayout; @@ -25,11 +26,11 @@ public class AutocompletePopup { public static final int PADDING_X = 6; public static final int PADDING_Y = 4; public static final int SCROLLBAR_W = 5; - public static final int BACKGROUND_COLOR = 0xF0181C22; - public static final int BORDER_COLOR = 0xFF4D5661; - public static final int HOVER_COLOR = 0xCC2A3A46; - public static final int SCROLLBAR_TRACK_COLOR = 0x35101010; - public static final int SCROLLBAR_THUMB_COLOR = 0xA0D8D8D8; + public static final int BACKGROUND_COLOR = ColorUtils.DIALOG.getColor(); + public static final int BORDER_COLOR = ColorUtils.ARGB_FF4D5661.getColor(); + public static final int HOVER_COLOR = ColorUtils.ARGB_CC2A3A46.getColor(); + public static final int SCROLLBAR_TRACK_COLOR = ColorUtils.SCROLLBAR_TRACK.getColor(); + public static final int SCROLLBAR_THUMB_COLOR = ColorUtils.SCROLLBAR_THUMB.getColor(); /** Gap between popup and cursor when flipped above (roughly FONT_HEIGHT + cursor gap). */ private static final int FLIP_GAP = 22; @@ -300,6 +301,6 @@ private static void pushScissor(int x, int y, int width, int height) { private static void popScissor() { GL11.glDisable(GL11.GL_SCISSOR_TEST); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/gui/SceneEditorMultilineTextArea.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/gui/SceneEditorMultilineTextArea.java index 757b86e0..41cf6280 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/gui/SceneEditorMultilineTextArea.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/gui/SceneEditorMultilineTextArea.java @@ -15,6 +15,7 @@ import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.GuideMarkdownOptions; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.internal.markdown.MdAstToMdxConverter; @@ -35,15 +36,15 @@ public class SceneEditorMultilineTextArea { public static final int PADDING = 4; public static final int SCROLLBAR_SIZE = 5; - public static final int BORDER_COLOR = 0xFF53565C; - public static final int FOCUSED_BORDER_COLOR = 0xFF7FC8FF; - public static final int ERROR_BORDER_COLOR = 0xFFFF6767; - public static final int BACKGROUND_COLOR = 0xA0121216; - public static final int SCROLLBAR_TRACK_COLOR = 0x35101010; - public static final int SCROLLBAR_THUMB_COLOR = 0xA0D8D8D8; - public static final int SELECTION_COLOR = 0x663D89C9; - public static final int EXTERNAL_HIGHLIGHT_COLOR = 0x4438BDF8; - public static final int SYNTAX_WARNING_COLOR = 0xFFFF6767; + public static final int BORDER_COLOR = ColorUtils.ARGB_FF53565C.getColor(); + public static final int FOCUSED_BORDER_COLOR = ColorUtils.INPUT_FOCUSED_BORDER.getColor(); + public static final int ERROR_BORDER_COLOR = ColorUtils.ERROR.getColor(); + public static final int BACKGROUND_COLOR = ColorUtils.ARGB_A0121216.getColor(); + public static final int SCROLLBAR_TRACK_COLOR = ColorUtils.SCROLLBAR_TRACK.getColor(); + public static final int SCROLLBAR_THUMB_COLOR = ColorUtils.SCROLLBAR_THUMB.getColor(); + public static final int SELECTION_COLOR = ColorUtils.ARGB_663D89C9.getColor(); + public static final int EXTERNAL_HIGHLIGHT_COLOR = ColorUtils.ARGB_4438BDF8.getColor(); + public static final int SYNTAX_WARNING_COLOR = ColorUtils.ERROR.getColor(); public static final long IME_DUPLICATE_WINDOW_MILLIS = 250L; private final FontRenderer fontRenderer; @@ -1064,7 +1065,11 @@ public void draw(boolean validationError) { if (drawY + lineHeight >= y && drawY < y + clipHeight) { drawExternalHighlightForLine(line, drawY, renderedHorizontalOffset); drawSelectionForLine(line, drawY, renderedHorizontalOffset); - fontRenderer.drawString(line.text(), x + PADDING - renderedHorizontalOffset, drawY, 0xF0F0F0); + fontRenderer.drawString( + line.text(), + x + PADDING - renderedHorizontalOffset, + drawY, + ColorUtils.ARGB_F0F0F0.getColor()); drawSyntaxWarningForLine(line, drawY, renderedHorizontalOffset); } drawY += lineHeight; @@ -1076,7 +1081,12 @@ public void draw(boolean validationError) { int cursorPixel = getCursorPixelOnLine(selectionModel.getCursorIndex(), visualLine); int cursorX = x + PADDING + cursorPixel - renderedHorizontalOffset; int cursorY = y + PADDING + cursorLine * lineHeight - renderedVerticalOffset; - Gui.drawRect(cursorX, cursorY, cursorX + 1, cursorY + fontRenderer.FONT_HEIGHT + 1, 0xFFFFFFFF); + Gui.drawRect( + cursorX, + cursorY, + cursorX + 1, + cursorY + fontRenderer.FONT_HEIGHT + 1, + ColorUtils.WHITE.getColor()); } if (focused) { @@ -1085,7 +1095,7 @@ public void draw(boolean validationError) { GL11.glDisable(GL11.GL_SCISSOR_TEST); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); drawVerticalScrollbar(); drawHorizontalScrollbar(); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorConflictPrompt.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorConflictPrompt.java index fb353f9b..96b128db 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorConflictPrompt.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorConflictPrompt.java @@ -5,6 +5,7 @@ import org.lwjgl.input.Keyboard; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.GuidebookText; public class GuideScreenEditorConflictPrompt extends GuiScreen { @@ -85,11 +86,17 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawDefaultBackground(); int baseX = (this.width - PROMPT_WIDTH) / 2; int baseY = (this.height - PROMPT_HEIGHT) / 2; - drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, 0xF0181C22); - drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + 1, 0xFF4D5661); - drawRect(baseX, baseY + PROMPT_HEIGHT - 1, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, 0xFF4D5661); - drawCenteredString(fontRendererObj, title, this.width / 2, baseY + 12, 0xFFF0F0F0); - fontRendererObj.drawSplitString(message, baseX + 12, baseY + 34, PROMPT_WIDTH - 24, 0xFFD0D8E0); + drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, ColorUtils.DIALOG.getColor()); + drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + 1, ColorUtils.ARGB_FF4D5661.getColor()); + drawRect( + baseX, + baseY + PROMPT_HEIGHT - 1, + baseX + PROMPT_WIDTH, + baseY + PROMPT_HEIGHT, + ColorUtils.ARGB_FF4D5661.getColor()); + drawCenteredString(fontRendererObj, title, this.width / 2, baseY + 12, ColorUtils.TEXT.getColor()); + fontRendererObj + .drawSplitString(message, baseX + 12, baseY + 34, PROMPT_WIDTH - 24, ColorUtils.TEXT_MUTED.getColor()); super.drawScreen(mouseX, mouseY, partialTicks); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorContextMenu.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorContextMenu.java index 81565998..40ece338 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorContextMenu.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorContextMenu.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.editor.gui.SceneEditorMultilineTextArea; import com.hfstudio.guidenh.guide.internal.editor.gui.SceneEditorPopupLayout; import com.hfstudio.guidenh.guide.internal.screen.GuideIconButton; @@ -28,13 +29,13 @@ public class GuideScreenEditorContextMenu { private static final int TEXT_Y_OFFSET = 2; private static final int TEXT_VISUAL_HEIGHT = 9; private static final int SCROLLBAR_W = SceneEditorMultilineTextArea.SCROLLBAR_SIZE; - private static final int BACKGROUND_COLOR = 0xF0181C22; - private static final int BORDER_COLOR = 0xFF4D5661; - private static final int HOVER_COLOR = 0xCC2A3A46; - private static final int TEXT_COLOR = 0xFFF0F0F0; - private static final int SEPARATOR_COLOR = 0xFF33404C; - private static final int SCROLLBAR_TRACK_COLOR = 0x35101010; - private static final int SCROLLBAR_THUMB_COLOR = 0xA0D8D8D8; + private static final int BACKGROUND_COLOR = ColorUtils.DIALOG.getColor(); + private static final int BORDER_COLOR = ColorUtils.ARGB_FF4D5661.getColor(); + private static final int HOVER_COLOR = ColorUtils.ARGB_CC2A3A46.getColor(); + private static final int TEXT_COLOR = ColorUtils.TEXT.getColor(); + private static final int SEPARATOR_COLOR = ColorUtils.ARGB_FF33404C.getColor(); + private static final int SCROLLBAR_TRACK_COLOR = ColorUtils.SCROLLBAR_TRACK.getColor(); + private static final int SCROLLBAR_THUMB_COLOR = ColorUtils.SCROLLBAR_THUMB.getColor(); public interface Listener { @@ -400,7 +401,8 @@ private void drawEntryIcon(Minecraft minecraft, Entry entry, int x, int y) { if (action == null) { return; } - GuideIconButton.drawIcon(minecraft, action.toRole(), x, y, ICON_SIZE, ICON_SIZE, 0xD8FFFFFF); + GuideIconButton + .drawIcon(minecraft, action.toRole(), x, y, ICON_SIZE, ICON_SIZE, ColorUtils.ARGB_D8FFFFFF.getColor()); } static int computeIconYForRow(int rowY) { @@ -542,7 +544,7 @@ private void pushScissor(int x, int y, int width, int height) { private void popScissor() { GL11.glDisable(GL11.GL_SCISSOR_TEST); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } private static final class MenuPane { diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorNewPagePrompt.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorNewPagePrompt.java index b695a7b5..03b246d4 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorNewPagePrompt.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorNewPagePrompt.java @@ -6,6 +6,7 @@ import org.lwjgl.input.Keyboard; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.GuidebookText; public class GuideScreenEditorNewPagePrompt extends GuiScreen { @@ -117,16 +118,25 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawDefaultBackground(); int baseX = (this.width - PROMPT_WIDTH) / 2; int baseY = (this.height - PROMPT_HEIGHT) / 2; - drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, 0xF0181C22); - drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + 1, 0xFF4D5661); - drawRect(baseX, baseY + PROMPT_HEIGHT - 1, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, 0xFF4D5661); + drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, ColorUtils.DIALOG.getColor()); + drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + 1, ColorUtils.ARGB_FF4D5661.getColor()); + drawRect( + baseX, + baseY + PROMPT_HEIGHT - 1, + baseX + PROMPT_WIDTH, + baseY + PROMPT_HEIGHT, + ColorUtils.ARGB_FF4D5661.getColor()); drawCenteredString( fontRendererObj, GuidebookText.GuideEditorNewPagePromptTitle.text(), this.width / 2, baseY + 12, - 0xFFF0F0F0); - fontRendererObj.drawString(GuidebookText.GuideEditorNewPagePath.text(), baseX + 14, baseY + 42, 0xFFD0D8E0); + ColorUtils.TEXT.getColor()); + fontRendererObj.drawString( + GuidebookText.GuideEditorNewPagePath.text(), + baseX + 14, + baseY + 42, + ColorUtils.TEXT_MUTED.getColor()); pathField.drawTextBox(); super.drawScreen(mouseX, mouseY, partialTicks); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorUnsavedPrompt.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorUnsavedPrompt.java index 465f49a4..03c92641 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorUnsavedPrompt.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/guide/GuideScreenEditorUnsavedPrompt.java @@ -5,6 +5,7 @@ import org.lwjgl.input.Keyboard; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.GuidebookText; public class GuideScreenEditorUnsavedPrompt extends GuiScreen { @@ -93,21 +94,26 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawDefaultBackground(); int baseX = (this.width - PROMPT_WIDTH) / 2; int baseY = (this.height - PROMPT_HEIGHT) / 2; - drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, 0xF0181C22); - drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + 1, 0xFF4D5661); - drawRect(baseX, baseY + PROMPT_HEIGHT - 1, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, 0xFF4D5661); + drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + PROMPT_HEIGHT, ColorUtils.DIALOG.getColor()); + drawRect(baseX, baseY, baseX + PROMPT_WIDTH, baseY + 1, ColorUtils.ARGB_FF4D5661.getColor()); + drawRect( + baseX, + baseY + PROMPT_HEIGHT - 1, + baseX + PROMPT_WIDTH, + baseY + PROMPT_HEIGHT, + ColorUtils.ARGB_FF4D5661.getColor()); drawCenteredString( fontRendererObj, GuidebookText.GuideEditorUnsavedTitle.text(), this.width / 2, baseY + 12, - 0xFFF0F0F0); + ColorUtils.TEXT.getColor()); fontRendererObj.drawSplitString( GuidebookText.GuideEditorUnsavedMessage.text(), baseX + 12, baseY + 34, PROMPT_WIDTH - 24, - 0xFFD0D8E0); + ColorUtils.TEXT_MUTED.getColor()); super.drawScreen(mouseX, mouseY, partialTicks); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorFolderOpener.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorFolderOpener.java new file mode 100644 index 00000000..2466f365 --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorFolderOpener.java @@ -0,0 +1,41 @@ +package com.hfstudio.guidenh.guide.internal.editor.io; + +import java.awt.Desktop; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog; + +/** Opens a saved Scene Editor file's directory using the host operating system. */ +public class SceneEditorFolderOpener { + + public static void open(Path directory) { + try { + if (Desktop.isDesktopSupported() && Desktop.getDesktop() + .isSupported(Desktop.Action.OPEN)) { + Desktop.getDesktop() + .open(directory.toFile()); + return; + } + } catch (Exception exception) { + GuideDebugLog.warnAlways("Failed to open scene export directory {}", directory, exception); + } + String osName = System.getProperty("os.name", "") + .toLowerCase(Locale.ROOT); + List command = new ArrayList<>(); + if (osName.contains("win")) command.add("explorer"); + else if (osName.contains("mac")) command.add("open"); + else if (osName.contains("nux") || osName.contains("nix") || osName.contains("aix")) command.add("xdg-open"); + else return; + command.add( + directory.toAbsolutePath() + .toString()); + try { + new ProcessBuilder(command).start(); + } catch (Exception exception) { + GuideDebugLog.warnAlways("Failed to open scene export directory {}", directory, exception); + } + } +} diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorOffscreenFramebuffer.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorOffscreenFramebuffer.java index 91b61ea7..c7eecf32 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorOffscreenFramebuffer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorOffscreenFramebuffer.java @@ -10,7 +10,6 @@ import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; import com.hfstudio.guidenh.guide.layout.MinecraftFontMetrics; @@ -55,10 +54,7 @@ public BufferedImage render(LytGuidebookScene scene) { scene.setSceneSize(width, height); scene.layout(new LayoutContext(new MinecraftFontMetrics()), 0, 0, width); - VanillaRenderContext renderContext = new VanillaRenderContext( - LightDarkMode.LIGHT_MODE, - new LytRect(0, 0, width, height), - height); + VanillaRenderContext renderContext = new VanillaRenderContext(new LytRect(0, 0, width, height), height); renderContext.setDocumentOrigin(0, 0); renderContext.setScrollOffsetY(0); scene.render(renderContext); @@ -107,10 +103,7 @@ public BufferedImage renderTile(LytGuidebookScene scene, int offsetX, int offset GL11.glClearColor(0f, 0f, 0f, 0f); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); - VanillaRenderContext renderContext = new VanillaRenderContext( - LightDarkMode.LIGHT_MODE, - new LytRect(0, 0, width, height), - height); + VanillaRenderContext renderContext = new VanillaRenderContext(new LytRect(0, 0, width, height), height); renderContext.setDocumentOrigin(-offsetX, -offsetY); renderContext.setScrollOffsetY(0); scene.render(renderContext); diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorScreenshotExportService.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorScreenshotExportService.java index 9bd6b8fc..aa271b61 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorScreenshotExportService.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/io/SceneEditorScreenshotExportService.java @@ -17,6 +17,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.layout.LayoutContext; import com.hfstudio.guidenh.guide.layout.MinecraftFontMetrics; @@ -26,7 +27,7 @@ public class SceneEditorScreenshotExportService { - public static final int OPAQUE_BACKGROUND_RGB = 0x121216; + public static final int OPAQUE_BACKGROUND_RGB = ColorUtils.ARGB_121216.getColor(); public static final DateTimeFormatter FILE_NAME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss"); private final Path rootDirectory; @@ -85,8 +86,8 @@ public ExportResult export(LytGuidebookScene scene, SceneEditorScreenshotFormat new IllegalStateException("No ImageIO writer available for ." + normalizedFormat.fileExtension())); } - scene.setSceneBackgroundColor(0x00000000); - scene.setSceneBorderColor(0x00000000); + scene.setSceneBackgroundColor(ColorUtils.TRANSPARENT.getColor()); + scene.setSceneBorderColor(ColorUtils.TRANSPARENT.getColor()); scene.setSceneButtonsVisible(false); scene.setBottomControlsVisible(false); scene.setReserveBottomControlArea(false); diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/model/SceneEditorElementType.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/model/SceneEditorElementType.java index fab16550..aed35764 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/model/SceneEditorElementType.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/model/SceneEditorElementType.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.GuidebookText; import com.hfstudio.guidenh.guide.scene.annotation.TextAnnotation; @@ -21,7 +22,7 @@ public class SceneEditorElementType { builder("guidenh:block", "BlockAnnotation", GuidebookText.SceneEditorElementBlock) .iconPngPath("guidenh:textures/guide/buttons.png") .fallbackGlyph('B') - .accentColor(0xFF9FC6FF) + .accentColor(ColorUtils.ARGB_FF9FC6FF.getColor()) .pointHandleMode(PointHandleMode.POINT) .includePrimaryVector(true) .includeSecondaryVector(false) @@ -35,7 +36,7 @@ public class SceneEditorElementType { builder("guidenh:box", "BoxAnnotation", GuidebookText.SceneEditorElementBox) .iconPngPath("guidenh:textures/guide/buttons.png") .fallbackGlyph('O') - .accentColor(0xFFFFC07A) + .accentColor(ColorUtils.ARGB_FFFFC07A.getColor()) .pointHandleMode(PointHandleMode.BOX) .includePrimaryVector(true) .includeSecondaryVector(true) @@ -50,7 +51,7 @@ public class SceneEditorElementType { builder("guidenh:line", "LineAnnotation", GuidebookText.SceneEditorElementLine) .iconPngPath("guidenh:textures/guide/buttons.png") .fallbackGlyph('L') - .accentColor(0xFF9FFFB0) + .accentColor(ColorUtils.ARGB_FF9FFFB0.getColor()) .pointHandleMode(PointHandleMode.LINE) .includePrimaryVector(true) .includeSecondaryVector(true) @@ -65,7 +66,7 @@ public class SceneEditorElementType { builder("guidenh:diamond", "DiamondAnnotation", GuidebookText.SceneEditorElementDiamond) .iconPngPath("guidenh:textures/guide/diamond.png") .fallbackGlyph('D') - .accentColor(0xFFFFE16A) + .accentColor(ColorUtils.ARGB_FFFFE16A.getColor()) .pointHandleMode(PointHandleMode.POINT) .includePrimaryVector(true) .includeSecondaryVector(false) @@ -77,7 +78,7 @@ public class SceneEditorElementType { .build()); public static final SceneEditorElementType TEXT = register( builder("guidenh:text", "TextAnnotation", GuidebookText.SceneEditorElementText).fallbackGlyph('T') - .accentColor(0xFFFFF1A8) + .accentColor(ColorUtils.ARGB_FFFFF1A8.getColor()) .pointHandleMode(PointHandleMode.POINT) .includePrimaryVector(true) .includeSecondaryVector(false) @@ -281,7 +282,7 @@ public Builder(String id, String tagName, GuidebookText textKey) { this.textKey = Objects.requireNonNull(textKey, "textKey"); this.iconPngPath = null; this.fallbackGlyph = '?'; - this.accentColor = 0xFFFFFFFF; + this.accentColor = ColorUtils.WHITE.getColor(); this.pointHandleMode = PointHandleMode.NONE; this.includePrimaryVector = false; this.includeSecondaryVector = false; diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorCameraMarkerOverlay.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorCameraMarkerOverlay.java index bd16323b..be82a1cd 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorCameraMarkerOverlay.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorCameraMarkerOverlay.java @@ -6,6 +6,7 @@ import org.joml.Vector3f; import org.joml.Vector3fc; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.internal.screen.GuideIconButton; import com.hfstudio.guidenh.guide.scene.CameraSettings; @@ -14,8 +15,8 @@ public class SceneEditorCameraMarkerOverlay { public static final int MARKER_SIZE = 16; public static final int MARKER_HALF_SIZE = MARKER_SIZE / 2; - public static final int MARKER_SHADOW_COLOR = 0x70000000; - public static final int MARKER_TINT = 0xF8FFFFFF; + public static final int MARKER_SHADOW_COLOR = ColorUtils.ARGB_70000000.getColor(); + public static final int MARKER_TINT = ColorUtils.ARGB_F8FFFFFF.getColor(); private final Vector3f projectedScratch = new Vector3f(); public LytRect getMarkerBounds(CameraSettings camera, LytRect viewport) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorHandleOverlay.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorHandleOverlay.java index d2a1be91..932384e7 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorHandleOverlay.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorHandleOverlay.java @@ -6,6 +6,7 @@ import org.joml.Vector3f; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.internal.editor.model.SceneEditorElementModel; import com.hfstudio.guidenh.guide.internal.editor.model.SceneEditorElementType; @@ -45,14 +46,14 @@ public class SceneEditorHandleOverlay { public static final float PLANE_LINE_WIDTH = 2.25f; public static final float ARROW_LENGTH = 8f; public static final float ARROW_HALF_WIDTH = 4f; - public static final int CENTER_HANDLE_FILL = 0x8A00CAF2; - public static final int CENTER_HANDLE_OUTLINE = 0xFFF4FBFF; - public static final int X_AXIS_COLOR = 0xFFFF5A5A; - public static final int Y_AXIS_COLOR = 0xFF67E26C; - public static final int Z_AXIS_COLOR = 0xFF64A8FF; - public static final int XY_PLANE_COLOR = 0xD8FFD45A; - public static final int YZ_PLANE_COLOR = 0xD85AE9FF; - public static final int ZX_PLANE_COLOR = 0xD8F16BFF; + public static final int CENTER_HANDLE_FILL = ColorUtils.ARGB_8A00CAF2.getColor(); + public static final int CENTER_HANDLE_OUTLINE = ColorUtils.ARGB_FFF4FBFF.getColor(); + public static final int X_AXIS_COLOR = ColorUtils.X_AXIS.getColor(); + public static final int Y_AXIS_COLOR = ColorUtils.Y_AXIS.getColor(); + public static final int Z_AXIS_COLOR = ColorUtils.Z_AXIS.getColor(); + public static final int XY_PLANE_COLOR = ColorUtils.XY_PLANE.getColor(); + public static final int YZ_PLANE_COLOR = ColorUtils.YZ_PLANE.getColor(); + public static final int ZX_PLANE_COLOR = ColorUtils.ZX_PLANE.getColor(); public static final String[] POINT_HANDLE_IDS = new String[] { CENTER_HANDLE_ID, XY_PLANE_HANDLE_ID, YZ_PLANE_HANDLE_ID, ZX_PLANE_HANDLE_ID, X_AXIS_HANDLE_ID, Y_AXIS_HANDLE_ID, Z_AXIS_HANDLE_ID }; public static final String[] LINE_HANDLE_IDS = new String[] { LINE_FROM_HANDLE_ID, LINE_TO_HANDLE_ID }; @@ -467,7 +468,7 @@ private void drawAxisArrow(Vector3f from, Vector3f to, int color) { GL11.glEnd(); } finally { GL11.glPopAttrib(); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } @@ -496,7 +497,7 @@ private void drawLine(Vector3f from, Vector3f to, int color, float lineWidth) { GL11.glEnd(); } finally { GL11.glPopAttrib(); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorSceneNodePreviewApplier.java b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorSceneNodePreviewApplier.java index bf3fc3cf..619be20e 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorSceneNodePreviewApplier.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/editor/preview/SceneEditorSceneNodePreviewApplier.java @@ -18,6 +18,7 @@ import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.compiler.GuideItemReferenceResolver; import com.hfstudio.guidenh.guide.compiler.GuideItemReferenceResolver.ResolvedBlockReference; @@ -676,7 +677,9 @@ private SceneAnnotation createTextHighlightAnnotation(SceneEditorElementModel el parseFloatAttributeOrDefault(hlMaxY, 1f), parseFloatAttributeOrDefault(hlMaxZ, 1f)); normalizeBounds(min, max); - ConstantColor highlightColor = parseColorOrDefault(element.getExtraAttribute("highlightColor"), 0x8000FFAA); + ConstantColor highlightColor = parseColorOrDefault( + element.getExtraAttribute("highlightColor"), + ColorUtils.HIGHLIGHT.getColor()); InWorldBoxAnnotation annotation = new InWorldBoxAnnotation( min, max, diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/home/HomePageController.java b/src/main/java/com/hfstudio/guidenh/guide/internal/home/HomePageController.java index a42d43cd..ae636934 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/home/HomePageController.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/home/HomePageController.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.screen.GuideNavBar; import com.hfstudio.guidenh.guide.internal.util.DisplayScale; import com.hfstudio.guidenh.guide.internal.util.SmoothFloatState; @@ -27,12 +28,12 @@ public class HomePageController { private static final int DRAG_THRESHOLD = 3; private static final float ENTRY_TITLE_SCALE = 1.12f; private static final float ENTRY_SUMMARY_SCALE = 0.85f; - private static final int PANEL_COLOR = 0xA6181A20; - private static final int ROW_COLOR = 0x661E232B; - private static final int ROW_HOVER_COLOR = 0x88303946; - private static final int TITLE_COLOR = 0xFFE5E9F0; - private static final int EMPTY_COLOR = 0xFF9AA3B2; - private static final int SUMMARY_COLOR = 0xFF9AA3B2; + private static final int PANEL_COLOR = ColorUtils.ARGB_A6181A20.getColor(); + private static final int ROW_COLOR = ColorUtils.ARGB_661E232B.getColor(); + private static final int ROW_HOVER_COLOR = ColorUtils.ARGB_88303946.getColor(); + private static final int TITLE_COLOR = ColorUtils.ARGB_FFE5E9F0.getColor(); + private static final int EMPTY_COLOR = ColorUtils.ARGB_FF9AA3B2.getColor(); + private static final int SUMMARY_COLOR = ColorUtils.ARGB_FF9AA3B2.getColor(); private static final int ENTRY_TEXT_TOP = 4; private static final int ENTRY_TEXT_BOTTOM = 25; @@ -162,7 +163,7 @@ private void drawLogo(Minecraft mc, HomePageLayout.Rect rect, ResourceLocation l .bindTexture(logoTexture); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); Tessellator tessellator = Tessellator.instance; tessellator.startDrawingQuads(); tessellator.addVertexWithUV(rect.x(), drawY + drawHeight, 0, 0f, 1f); @@ -249,8 +250,8 @@ private void drawScrollbar(HomePageLayout.Rect rect, HomePageSection section, in int thumbHeight = Math.max(18, visibleHeight * visibleHeight / Math.max(visibleHeight, contentHeight)); int travel = Math.max(1, visibleHeight - thumbHeight); int thumbY = contentY + (int) ((long) scrollOffset * travel / maxScroll); - Gui.drawRect(x, contentY, x + SCROLLBAR_WIDTH, contentY + visibleHeight, 0x22262D38); - Gui.drawRect(x, thumbY, x + SCROLLBAR_WIDTH, thumbY + thumbHeight, 0x889AA3B2); + Gui.drawRect(x, contentY, x + SCROLLBAR_WIDTH, contentY + visibleHeight, ColorUtils.ARGB_22262D38.getColor()); + Gui.drawRect(x, thumbY, x + SCROLLBAR_WIDTH, thumbY + thumbHeight, ColorUtils.SCROLLBAR_HOVER.getColor()); } private int computeContentHeight(HomePageSection section) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/ItemLinkScript.java b/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/ItemLinkScript.java index 298c58bb..5596b962 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/ItemLinkScript.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/ItemLinkScript.java @@ -11,7 +11,7 @@ import com.hfstudio.guidenh.guide.GuideAnchor; import com.hfstudio.guidenh.guide.PageAnchor; import com.hfstudio.guidenh.guide.PageCollection; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.IdUtils; import com.hfstudio.guidenh.guide.document.block.LytItemImage; import com.hfstudio.guidenh.guide.document.block.LytParagraph; @@ -99,7 +99,7 @@ public void onEvent(Object node, LytEvent event, ScriptContext ctx) { span.setTooltip(new ItemTooltip(stack)); } span.modifyStyle( - style -> style.color(SymbolicColor.GRAY) + style -> style.color(ColorUtils.MC_GRAY) .italic(true)); ctx.replace(span); return; diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/QuestCardScript.java b/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/QuestCardScript.java index 04cb476f..513ea513 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/QuestCardScript.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/QuestCardScript.java @@ -6,7 +6,8 @@ import net.minecraft.util.StatCollector; import com.hfstudio.guidenh.guide.PageAnchor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; +import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.document.block.LytParagraph; import com.hfstudio.guidenh.guide.document.block.LytQuoteBox; import com.hfstudio.guidenh.guide.document.flow.LytFlowLink; @@ -55,7 +56,7 @@ public void onEvent(Object node, LytEvent event, ScriptContext ctx) { QuestState state = display.getState(); var box = new LytQuoteBox(); - SymbolicColor accent = pickAccentColor(state); + ColorValue accent = pickAccentColor(state); box.setQuoteStyle(accent, null, null); var title = new LytParagraph(); @@ -110,17 +111,17 @@ private static String resolveTitleText(QuestDisplay display, UUID questId) { return "[" + StatCollector.translateToLocal("guidenh.compat.bq.hidden") + "]"; } - private static SymbolicColor pickAccentColor(QuestState state) { - if (state == QuestState.COMPLETED) return SymbolicColor.GREEN; - if (state == QuestState.LOCKED || state == QuestState.HIDDEN) return SymbolicColor.GRAY; - if (state == QuestState.MISSING) return SymbolicColor.RED; - return SymbolicColor.LINK; + private static ColorValue pickAccentColor(QuestState state) { + if (state == QuestState.COMPLETED) return ColorUtils.MC_GREEN; + if (state == QuestState.LOCKED || state == QuestState.HIDDEN) return ColorUtils.MC_GRAY; + if (state == QuestState.MISSING) return ColorUtils.MC_RED; + return ColorUtils.LINK; } - private static SymbolicColor pickPlaceholderColor(QuestState state) { - if (state == QuestState.HIDDEN) return SymbolicColor.DARK_GRAY; - if (state == QuestState.MISSING) return SymbolicColor.RED; - return SymbolicColor.GRAY; + private static ColorValue pickPlaceholderColor(QuestState state) { + if (state == QuestState.HIDDEN) return ColorUtils.MC_DARK_GRAY; + if (state == QuestState.MISSING) return ColorUtils.MC_RED; + return ColorUtils.MC_GRAY; } private static boolean isVisibleToPlayer(QuestState state) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/QuestLinkScript.java b/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/QuestLinkScript.java index 67660351..1ba6b759 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/QuestLinkScript.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/host/scripts/QuestLinkScript.java @@ -5,7 +5,8 @@ import net.minecraft.client.Minecraft; import net.minecraft.util.StatCollector; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; +import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.document.block.LytParagraph; import com.hfstudio.guidenh.guide.document.flow.LytFlowContent; import com.hfstudio.guidenh.guide.document.flow.LytFlowSpan; @@ -53,7 +54,7 @@ public void onEvent(Object node, LytEvent event, ScriptContext ctx) { } if (display == null) { LytFlowSpan errorSpan = new LytFlowSpan(); - errorSpan.modifyStyle(style -> style.color(SymbolicColor.ERROR_TEXT)); + errorSpan.modifyStyle(style -> style.color(ColorUtils.ERROR_TEXT)); errorSpan.appendText("[QuestLink] Quest not found: " + questId); ctx.replace(errorSpan); return; @@ -65,8 +66,8 @@ public void onEvent(Object node, LytEvent event, ScriptContext ctx) { if (QuestTagSupport.isNavigable(state)) { replacement = QuestTagSupport.createQuestGuiLink(questId, display, text, Boolean.TRUE.equals(showTooltip)); } else { - SymbolicColor color = state == QuestState.HIDDEN ? SymbolicColor.DARK_GRAY - : state == QuestState.MISSING ? SymbolicColor.RED : SymbolicColor.GRAY; + ColorValue color = state == QuestState.HIDDEN ? ColorUtils.MC_DARK_GRAY + : state == QuestState.MISSING ? ColorUtils.MC_RED : ColorUtils.MC_GRAY; LytFlowSpan span = new LytFlowSpan(); span.modifyStyle( style -> style.color(color) diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/GithubAlertType.java b/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/GithubAlertType.java index 1fd9a418..1414ad77 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/GithubAlertType.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/GithubAlertType.java @@ -2,16 +2,17 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.internal.GuidebookText; public enum GithubAlertType { - NOTE(GuidebookText.MarkdownAlertNote, "ⓘ", new ConstantColor(0xFF638EF1)), - TIP(GuidebookText.MarkdownAlertTip, "✦", new ConstantColor(0xFF61B75D)), - IMPORTANT(GuidebookText.MarkdownAlertImportant, "➤", new ConstantColor(0xFF8755DD)), - WARNING(GuidebookText.MarkdownAlertWarning, "⚠", new ConstantColor(0xFFC79D3E)), - CAUTION(GuidebookText.MarkdownAlertCaution, "☢", new ConstantColor(0xFFE46150)); + NOTE(GuidebookText.MarkdownAlertNote, "ⓘ", new ConstantColor(ColorUtils.ARGB_FF638EF1.getColor())), + TIP(GuidebookText.MarkdownAlertTip, "✦", new ConstantColor(ColorUtils.ARGB_FF61B75D.getColor())), + IMPORTANT(GuidebookText.MarkdownAlertImportant, "➤", new ConstantColor(ColorUtils.ARGB_FF8755DD.getColor())), + WARNING(GuidebookText.MarkdownAlertWarning, "⚠", new ConstantColor(ColorUtils.ARGB_FFC79D3E.getColor())), + CAUTION(GuidebookText.MarkdownAlertCaution, "☢", new ConstantColor(ColorUtils.ARGB_FFE46150.getColor())); private final GuidebookText label; private final String symbol; diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/MarkdownRuntimeBlocks.java b/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/MarkdownRuntimeBlocks.java index 2b738446..1dbfb6ab 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/MarkdownRuntimeBlocks.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/MarkdownRuntimeBlocks.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import com.github.bsideup.jabel.Desugar; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.libs.mdast.mdx.model.MdxJsxElementFields; @@ -125,7 +126,7 @@ private MarkdownRuntimeBlocks() {} return new BlockquoteDirective( null, - color != null ? color : new ConstantColor(0xFF7C8795), + color != null ? color : new ConstantColor(ColorUtils.ARGB_FF7C8795.getColor()), title, icon, trimLeadingDirectiveText(trimmed, directiveEnd + 1), @@ -255,7 +256,7 @@ private static ColorValue parseColor(String value) { try { if (normalized.length() == 7) { int rgb = Integer.parseInt(normalized.substring(1), 16); - return new ConstantColor(0xFF000000 | rgb); + return new ConstantColor(ColorUtils.BLACK.getColor() | rgb); } if (normalized.length() == 9) { long argb = Long.parseLong(normalized.substring(1), 16); diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/highlight/CodeHighlightTheme.java b/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/highlight/CodeHighlightTheme.java index 894d573a..cb25fa5b 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/highlight/CodeHighlightTheme.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/markdown/highlight/CodeHighlightTheme.java @@ -3,6 +3,8 @@ import java.util.EnumMap; import java.util.Map; +import com.hfstudio.guidenh.guide.color.ColorUtils; + public class CodeHighlightTheme { public static final CodeHighlightTheme GITHUB_DARK_DEFAULT = githubDarkDefault(); @@ -63,25 +65,25 @@ public int colorOf(CodeTokenType type) { private static CodeHighlightTheme githubDarkDefault() { Map colors = new EnumMap<>(CodeTokenType.class); - colors.put(CodeTokenType.PLAIN, 0xFFE6EDF3); - colors.put(CodeTokenType.KEYWORD, 0xFFFF7B72); - colors.put(CodeTokenType.STRING, 0xFFA5D6FF); - colors.put(CodeTokenType.NUMBER, 0xFF79C0FF); - colors.put(CodeTokenType.COMMENT, 0xFF8B949E); - colors.put(CodeTokenType.OPERATOR, 0xFFFF7B72); - colors.put(CodeTokenType.PUNCTUATION, 0xFFE6EDF3); - colors.put(CodeTokenType.TYPE, 0xFF7EE787); - colors.put(CodeTokenType.FUNCTION, 0xFFD2A8FF); - colors.put(CodeTokenType.ANNOTATION, 0xFFFFA657); - colors.put(CodeTokenType.PROPERTY, 0xFF79C0FF); + colors.put(CodeTokenType.PLAIN, ColorUtils.ARGB_FFE6EDF3.getColor()); + colors.put(CodeTokenType.KEYWORD, ColorUtils.ARGB_FFFF7B72.getColor()); + colors.put(CodeTokenType.STRING, ColorUtils.ARGB_FFA5D6FF.getColor()); + colors.put(CodeTokenType.NUMBER, ColorUtils.ARGB_FF79C0FF.getColor()); + colors.put(CodeTokenType.COMMENT, ColorUtils.ARGB_FF8B949E.getColor()); + colors.put(CodeTokenType.OPERATOR, ColorUtils.ARGB_FFFF7B72.getColor()); + colors.put(CodeTokenType.PUNCTUATION, ColorUtils.ARGB_FFE6EDF3.getColor()); + colors.put(CodeTokenType.TYPE, ColorUtils.ARGB_FF7EE787.getColor()); + colors.put(CodeTokenType.FUNCTION, ColorUtils.ARGB_FFD2A8FF.getColor()); + colors.put(CodeTokenType.ANNOTATION, ColorUtils.ARGB_FFFFA657.getColor()); + colors.put(CodeTokenType.PROPERTY, ColorUtils.ARGB_FF79C0FF.getColor()); return new CodeHighlightTheme( - 0xFF0D1117, - 0xFF161B22, - 0xFF30363D, - 0x4D6E7681, - 0x80768496, - 0xCC768496, - 0xFF8B949E, + ColorUtils.ARGB_FF0D1117.getColor(), + ColorUtils.ARGB_FF161B22.getColor(), + ColorUtils.ARGB_FF30363D.getColor(), + ColorUtils.ARGB_4D6E7681.getColor(), + ColorUtils.ARGB_80768496.getColor(), + ColorUtils.ARGB_CC768496.getColor(), + ColorUtils.ARGB_FF8B949E.getColor(), colors); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/LytNeiRecipeBox.java b/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/LytNeiRecipeBox.java index 25d7ca9a..8a897a53 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/LytNeiRecipeBox.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/LytNeiRecipeBox.java @@ -13,6 +13,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.block.LytBlock; import com.hfstudio.guidenh.guide.document.interaction.GuideTooltip; @@ -181,7 +182,7 @@ public void render(RenderContext context) { int bodyY = innerTop + titleHeight + BODY_MARGIN + bodyTopInset; context.restoreExternalRenderState(); - WindowNinePatch.drawWindow(context.lightDarkMode(), x, y, w, h); + WindowNinePatch.drawWindow(x, y, w, h); try { renderRecipeBody(bodyX, bodyY, context); @@ -251,7 +252,7 @@ private void drawTitleRow(RenderContext context, int innerLeft, int innerRight, if (!handlerName.isEmpty()) { int textX = innerLeft + iconSize() + (iconSize() > 0 ? TITLE_GAP_AFTER_ICON : 0); int textY = titleRowTop + (Math.max(ICON_SIZE, fontHeight) - fontHeight) / 2; - Minecraft.getMinecraft().fontRenderer.drawString(handlerName, textX, textY, 0xFF000000); + Minecraft.getMinecraft().fontRenderer.drawString(handlerName, textX, textY, ColorUtils.BLACK.getColor()); } LytRect actionButtonBounds = getActionButtonBounds(); if (recipeJumpEnabled && actionButtonBounds != null) { @@ -316,7 +317,7 @@ private void drawWindowOverlayStrip(RenderContext context, int windowX, int wind } context.pushLocalScissor(strip); try { - WindowNinePatch.drawWindow(context.lightDarkMode(), windowX, windowY, windowW, windowH); + WindowNinePatch.drawWindow(windowX, windowY, windowW, windowH); } finally { context.popScissor(); } @@ -354,14 +355,14 @@ public static void drawScaledImage(Object image, int x, int y, int size, int nat try { GL11.glTranslatef(x + offX, y + offY, 0f); GL11.glScalef(scale, scale, 1f); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GuideNhIntegrationRegistry.global() .drawRecipeDrawable(image, 0, 0); } finally { GL11.glPopMatrix(); // DrawableResource.draw leaves the color/texture state reasonable, but make sure no // leftover tint poisons later blits in the same frame. - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/NeiHandlerRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/NeiHandlerRenderer.java index 078c9ff1..2d9cffb0 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/NeiHandlerRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/NeiHandlerRenderer.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.item.GuideDisplayItemStacks; import com.hfstudio.guidenh.integration.api.GuideNhIntegrationRegistry; import com.hfstudio.guidenh.integration.api.RecipeSlot; @@ -75,12 +76,12 @@ private NeiHandlerRenderer() {} GL11.glPushMatrix(); try { GL11.glTranslatef(screenX, screenY, 0f); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); registry.renderRecipeHandler(handler, recipeIndex, skipForeground); } catch (Throwable ignored) {} finally { GL11.glPopMatrix(); GL11.glPopAttrib(); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_BLEND); @@ -176,7 +177,7 @@ private static void drawItemInternal(ItemStack stack, int x, int y, boolean draw GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_CURRENT_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_LIGHTING_BIT); try { GL11.glDisable(GL11.GL_BLEND); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); RenderHelper.enableGUIStandardItemLighting(); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit); @@ -202,7 +203,7 @@ private static void drawItemInternal(ItemStack stack, int x, int y, boolean draw GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/WindowNinePatch.java b/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/WindowNinePatch.java index 1b2e5b98..941b087b 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/WindowNinePatch.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/recipe/WindowNinePatch.java @@ -6,7 +6,7 @@ import org.lwjgl.opengl.GL11; -import com.hfstudio.guidenh.guide.color.LightDarkMode; +import com.hfstudio.guidenh.guide.color.ColorUtils; /** * Draws the {@code window.png} and {@code window_inner.png} 9-slice frames (16x16 source, 4px @@ -33,12 +33,12 @@ public class WindowNinePatch { private WindowNinePatch() {} - public static void drawWindow(LightDarkMode mode, int x, int y, int w, int h) { - draw(mode == LightDarkMode.DARK_MODE ? WINDOW_DARK : WINDOW_LIGHT, x, y, w, h); + public static void drawWindow(int x, int y, int w, int h) { + draw(WINDOW_DARK, x, y, w, h); } - public static void drawWindowInner(LightDarkMode mode, int x, int y, int w, int h) { - draw(mode == LightDarkMode.DARK_MODE ? WINDOW_INNER_DARK : WINDOW_INNER_LIGHT, x, y, w, h); + public static void drawWindowInner(int x, int y, int w, int h) { + draw(WINDOW_INNER_DARK, x, y, w, h); } public static void draw(ResourceLocation texture, int x, int y, int w, int h) { @@ -49,7 +49,7 @@ public static void draw(ResourceLocation texture, int x, int y, int w, int h) { GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); var tess = Tessellator.instance; tess.startDrawingQuads(); diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/scene/GuidebookPreviewPlayerSkinImageBuffer.java b/src/main/java/com/hfstudio/guidenh/guide/internal/scene/GuidebookPreviewPlayerSkinImageBuffer.java index 7b536d44..35d5240d 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/scene/GuidebookPreviewPlayerSkinImageBuffer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/scene/GuidebookPreviewPlayerSkinImageBuffer.java @@ -7,6 +7,8 @@ import net.minecraft.client.renderer.IImageBuffer; +import com.hfstudio.guidenh.guide.color.ColorUtils; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -37,7 +39,7 @@ public static BufferedImage processSkinFormat(BufferedImage sourceImage) { graphics.drawImage(sourceImage, 0, 0, null); if (legacySkinLayout) { - graphics.setColor(new Color(0, 0, 0, 0)); + graphics.setColor(new Color(ColorUtils.TRANSPARENT.getColor(), true)); graphics.fillRect(0, LEGACY_IMAGE_HEIGHT, IMAGE_WIDTH, LEGACY_IMAGE_HEIGHT); copyLegacySkinLayout(graphics, outputImage); } @@ -83,7 +85,7 @@ private static void setAreaTransparent(int[] imageData, int minX, int minY, int private static void setAreaOpaque(int[] imageData, int minX, int minY, int maxX, int maxY) { for (int x = minX; x < maxX; ++x) { for (int y = minY; y < maxY; ++y) { - imageData[x + y * IMAGE_WIDTH] |= 0xFF000000; + imageData[x + y * IMAGE_WIDTH] |= ColorUtils.BLACK.getColor(); } } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/screen/GuideIconButton.java b/src/main/java/com/hfstudio/guidenh/guide/internal/screen/GuideIconButton.java index a5d6da94..ddf5a95e 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/screen/GuideIconButton.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/screen/GuideIconButton.java @@ -7,6 +7,8 @@ import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; +import com.hfstudio.guidenh.guide.editor.SceneEditorIcon; import com.hfstudio.guidenh.guide.internal.GuidebookText; import lombok.Getter; @@ -28,15 +30,27 @@ public class GuideIconButton extends GuiButton { private Role role; private boolean active; + private SceneEditorIcon customIcon; + private String customTooltip; public GuideIconButton(int id, int x, int y, Role role) { super(id, x, y, WIDTH, HEIGHT, ""); this.role = role; this.active = false; + this.customIcon = null; + this.customTooltip = null; + } + + public GuideIconButton(int id, int x, int y, SceneEditorIcon icon, String tooltip) { + super(id, x, y, WIDTH, HEIGHT, ""); + this.role = null; + this.active = false; + this.customIcon = icon; + this.customTooltip = tooltip; } public String getTooltip() { - return role.tooltip(); + return role != null ? role.tooltip() : customTooltip; } @Override @@ -48,17 +62,21 @@ public void drawButton(Minecraft mc, int mouseX, int mouseY) { int color = resolveIconColor(enabled, field_146123_n, active); - drawIcon(mc, role, xPosition, yPosition, width, height, color); + if (customIcon != null) { + drawIcon(mc, customIcon, xPosition, yPosition, width, height, color); + } else { + drawIcon(mc, role, xPosition, yPosition, width, height, color); + } } public static int resolveIconColor(boolean enabled, boolean hovered, boolean active) { if (!enabled) { - return 0x60FFFFFF; + return ColorUtils.ARGB_60FFFFFF.getColor(); } if (active || hovered) { - return 0xFF00CAF2; + return ColorUtils.ACCENT.getColor(); } - return 0xC0FFFFFF; + return ColorUtils.ARGB_C0FFFFFF.getColor(); } public static void drawIcon(Minecraft mc, Role role, int x, int y, int width, int height, int color) { @@ -77,7 +95,7 @@ public static void drawIcon(Minecraft mc, Role role, int x, int y, int width, in int r = (color >>> 16) & 0xFF; int g = (color >>> 8) & 0xFF; int b = color & 0xFF; - GL11.glColor4f(r / 255f, g / 255f, b / 255f, a / 255f); + ColorUtils.applyGlColor(r / 255f, g / 255f, b / 255f, a / 255f); float texSize = GuideIconButton.TEXTURE_SIZE; float u0 = role.iconSrcX() / texSize; @@ -93,7 +111,59 @@ public static void drawIcon(Minecraft mc, Role role, int x, int y, int width, in tess.addVertexWithUV(x, y, 0, u0, v0); tess.draw(); } finally { - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); + GL11.glPopAttrib(); + } + } + + public static void drawIcon(Minecraft mc, SceneEditorIcon icon, int x, int y, int width, int height, int color) { + if (icon == null) return; + drawIcon( + mc, + icon.texture(), + icon.textureWidth(), + icon.textureHeight(), + icon.sourceX(), + icon.sourceY(), + icon.sourceWidth(), + icon.sourceHeight(), + x, + y, + width, + height, + color); + } + + private static void drawIcon(Minecraft mc, ResourceLocation texture, int textureWidth, int textureHeight, + int sourceX, int sourceY, int sourceWidth, int sourceHeight, int x, int y, int width, int height, int color) { + if (mc == null || texture == null) return; + + GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_CURRENT_BIT | GL11.GL_COLOR_BUFFER_BIT); + try { + mc.getTextureManager() + .bindTexture(texture); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + int a = (color >>> 24) & 0xFF; + int r = (color >>> 16) & 0xFF; + int g = (color >>> 8) & 0xFF; + int b = color & 0xFF; + ColorUtils.applyGlColor(r / 255f, g / 255f, b / 255f, a / 255f); + + float u0 = sourceX / (float) textureWidth; + float v0 = sourceY / (float) textureHeight; + float u1 = (sourceX + sourceWidth) / (float) textureWidth; + float v1 = (sourceY + sourceHeight) / (float) textureHeight; + var tess = Tessellator.instance; + tess.startDrawingQuads(); + tess.addVertexWithUV(x, y + height, 0, u0, v1); + tess.addVertexWithUV(x + width, y + height, 0, u1, v1); + tess.addVertexWithUV(x + width, y, 0, u1, v0); + tess.addVertexWithUV(x, y, 0, u0, v0); + tess.draw(); + } finally { + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glPopAttrib(); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/screen/GuideNavBar.java b/src/main/java/com/hfstudio/guidenh/guide/internal/screen/GuideNavBar.java index c17a1fcb..1b54b52e 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/screen/GuideNavBar.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/screen/GuideNavBar.java @@ -23,6 +23,7 @@ import com.hfstudio.guidenh.guide.GuidePageIcon; import com.hfstudio.guidenh.guide.PageCollection; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.GuideBookmarkState; import com.hfstudio.guidenh.guide.internal.GuidebookText; import com.hfstudio.guidenh.guide.internal.util.DisplayScale; @@ -389,14 +390,14 @@ public void render(Minecraft mc, @Nullable ResourceLocation currentGuideId, int textRightBase = x + w - 2; int bookmarkActionLeft = getBookmarkActionLeft(w); int bookmarkIconX = bookmarkActionLeft + ACTION_PADDING_RIGHT; - int bgTop = 0xE0151515; - int bgBot = 0xE0101010; + int bgTop = ColorUtils.ARGB_E0151515.getColor(); + int bgBot = ColorUtils.ARGB_E0101010.getColor(); drawVGradient(x, y, w, height, bgTop, bgBot); - Gui.drawRect(rowRight, y, x + w, y + height, 0xFF2A2A2A); + Gui.drawRect(rowRight, y, x + w, y + height, ColorUtils.ARGB_FF2A2A2A.getColor()); if (!isOpen()) { resetTitleScroll(); - drawArrow(x + w / 2 - 2, y + height / 2 - 3, true, 0xFF888888); + drawArrow(x + w / 2 - 2, y + height / 2 - 3, true, ColorUtils.ARGB_FF888888.getColor()); return; } @@ -475,7 +476,7 @@ public void render(Minecraft mc, @Nullable ResourceLocation currentGuideId, GL11.glPopAttrib(); GL11.glDisable(GL11.GL_SCISSOR_TEST); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } @@ -491,18 +492,18 @@ private boolean renderRow(Minecraft mc, FontRenderer fr, Row row, int rowY, int boolean bookmarkable = row.bookmarkable(); if (sticky) { - Gui.drawRect(x, rowY, rowRight, rowY + ROW_H, 0xF0181818); - Gui.drawRect(x, rowY + ROW_H - 1, rowRight, rowY + ROW_H, 0x802A2A2A); + Gui.drawRect(x, rowY, rowRight, rowY + ROW_H, ColorUtils.ARGB_F0181818.getColor()); + Gui.drawRect(x, rowY + ROW_H - 1, rowRight, rowY + ROW_H, ColorUtils.ARGB_802A2A2A.getColor()); } if (current) { - Gui.drawRect(x, rowY, rowRight, rowY + ROW_H, 0x40FFFFFF); + Gui.drawRect(x, rowY, rowRight, rowY + ROW_H, ColorUtils.ARGB_40FFFFFF.getColor()); } else if (hovered) { - Gui.drawRect(x, rowY, rowRight, rowY + ROW_H, 0x20FFFFFF); + Gui.drawRect(x, rowY, rowRight, rowY + ROW_H, ColorUtils.ARGB_20FFFFFF.getColor()); } if (row.hasChildren()) { boolean collapsed = isCollapsed(row); - drawArrow(rowX, rowY + 2, collapsed, 0xFFCCCCCC); + drawArrow(rowX, rowY + 2, collapsed, ColorUtils.ARGB_FFCCCCCC.getColor()); } int textX = rowX + EXPAND_INDENT; @@ -586,8 +587,8 @@ private void resetTitleScroll() { private void renderTitle(Minecraft mc, int width, int mouseX, int mouseY, boolean showNewPageButton) { FontRenderer fr = mc.fontRenderer; - Gui.drawRect(x, y, x + width - 1, y + TITLE_H, 0xD0202020); - Gui.drawRect(x, y + TITLE_H - 1, x + width - 1, y + TITLE_H, 0xFF2A2A2A); + Gui.drawRect(x, y, x + width - 1, y + TITLE_H, ColorUtils.ARGB_D0202020.getColor()); + Gui.drawRect(x, y + TITLE_H - 1, x + width - 1, y + TITLE_H, ColorUtils.ARGB_FF2A2A2A.getColor()); int pinX = getPinButtonX(); int buttonY = getTitleButtonY(); if (showNewPageButton) { @@ -623,7 +624,12 @@ private void renderTitle(Minecraft mc, int width, int mouseX, int mouseY, boolea String renderedTitle = fr.getStringWidth(title) > titleW ? fr.trimStringToWidth(title, Math.max(0, titleW - 4)) + "…" : title; - fr.drawString(renderedTitle, titleX, y + (TITLE_H - fr.FONT_HEIGHT) / 2 + 1, 0xFFE8E8E8, false); + fr.drawString( + renderedTitle, + titleX, + y + (TITLE_H - fr.FONT_HEIGHT) / 2 + 1, + ColorUtils.ARGB_FFE8E8E8.getColor(), + false); } } @@ -1015,9 +1021,11 @@ private static void setScissor(Minecraft mc, int x, int y, int w, int h, int sca public static int getRowTextColor(boolean current, boolean hovered, boolean failed) { if (failed) { - return current ? 0xFFFF9999 : hovered ? 0xFFFF7777 : 0xFFFF5555; + return current ? ColorUtils.ARGB_FFFF9999.getColor() + : hovered ? ColorUtils.ARGB_FFFF7777.getColor() : ColorUtils.ARGB_FFFF5555.getColor(); } - return current ? 0xFFFFFFFF : hovered ? 0xFF88BBFF : 0xFFBBBBBB; + return current ? ColorUtils.WHITE.getColor() + : hovered ? ColorUtils.ARGB_FF88BBFF.getColor() : ColorUtils.ARGB_FFBBBBBB.getColor(); } public static void drawVGradient(int x, int y, int w, int h, int topColor, int botColor) { @@ -1097,7 +1105,7 @@ public static void drawMiniItemIcon(Minecraft mc, ItemStack stack, int x, int y, } finally { GL11.glPopAttrib(); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } @@ -1117,7 +1125,7 @@ public static void drawMiniTextureIcon(@Nullable GuidePageTexture texture, int x GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); var tess = Tessellator.instance; tess.startDrawingQuads(); diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/search/GuideSearchResultDocumentBuilder.java b/src/main/java/com/hfstudio/guidenh/guide/internal/search/GuideSearchResultDocumentBuilder.java index 0dc1de22..d8060662 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/search/GuideSearchResultDocumentBuilder.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/search/GuideSearchResultDocumentBuilder.java @@ -9,6 +9,7 @@ import com.github.bsideup.jabel.Desugar; import com.hfstudio.guidenh.guide.GuidePageIcon; import com.hfstudio.guidenh.guide.PageAnchor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.document.block.AlignItems; import com.hfstudio.guidenh.guide.document.block.LytBlock; @@ -29,9 +30,10 @@ public class GuideSearchResultDocumentBuilder { - public static final ConstantColor SEARCH_TITLE_COLOR = new ConstantColor(0xFF00D2FC); - public static final ConstantColor SPECIAL_SEARCH_TITLE_COLOR = new ConstantColor(0xFFFFD254); - public static final ConstantColor RESULT_DIVIDER_COLOR = new ConstantColor(0xFF3A3A3A); + public static final ConstantColor SEARCH_TITLE_COLOR = new ConstantColor(ColorUtils.ARGB_FF00D2FC.getColor()); + public static final ConstantColor SPECIAL_SEARCH_TITLE_COLOR = new ConstantColor( + ColorUtils.ARGB_FFFFD254.getColor()); + public static final ConstantColor RESULT_DIVIDER_COLOR = new ConstantColor(ColorUtils.ARGB_FF3A3A3A.getColor()); public static final int RESULT_ICON_SIZE = 16; public static final int RESULT_ICON_MARGIN_TOP = 2; public static final int RESULT_ICON_GAP = 6; diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/ui/GuideSliderRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/internal/ui/GuideSliderRenderer.java index 53a6f399..5d5e9626 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/ui/GuideSliderRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/ui/GuideSliderRenderer.java @@ -1,13 +1,14 @@ package com.hfstudio.guidenh.guide.internal.ui; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; public class GuideSliderRenderer { - public static final int TRACK_COLOR = 0x6622262C; - public static final int FILL_COLOR = 0xAA1CB4E9; - public static final int THUMB_COLOR = 0xFFEAF6FF; - public static final int ACTIVE_THUMB_COLOR = 0xFFFFFFFF; + public static final int TRACK_COLOR = ColorUtils.ARGB_6622262C.getColor(); + public static final int FILL_COLOR = ColorUtils.ARGB_AA1CB4E9.getColor(); + public static final int THUMB_COLOR = ColorUtils.ARGB_FFEAF6FF.getColor(); + public static final int ACTIVE_THUMB_COLOR = ColorUtils.WHITE.getColor(); public static final int TRACK_HEIGHT = 4; public static final int THUMB_WIDTH = 6; public static final int THUMB_OVERHANG = 2; diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/welcome/GuideWelcomeScreen.java b/src/main/java/com/hfstudio/guidenh/guide/internal/welcome/GuideWelcomeScreen.java index 435aaabd..7837dabe 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/welcome/GuideWelcomeScreen.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/welcome/GuideWelcomeScreen.java @@ -28,7 +28,7 @@ import com.hfstudio.guidenh.guide.GuidePage; import com.hfstudio.guidenh.guide.PageAnchor; import com.hfstudio.guidenh.guide.PageCollection; -import com.hfstudio.guidenh.guide.color.LightDarkMode; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.ParsedGuidePage; import com.hfstudio.guidenh.guide.document.LytRect; @@ -72,14 +72,8 @@ public class GuideWelcomeScreen extends GuiScreen implements GuideUiHost, GuiYes private static final int EXTERNAL_LINK_CONFIRM_ID = 0; private final GuiScreen parent; - private final VanillaRenderContext renderContext = new VanillaRenderContext( - LightDarkMode.DARK_MODE, - LytRect.empty(), - 0); - private final VanillaRenderContext contentTooltipRenderContext = new VanillaRenderContext( - LightDarkMode.LIGHT_MODE, - LytRect.empty(), - 0); + private final VanillaRenderContext renderContext = new VanillaRenderContext(LytRect.empty(), 0); + private final VanillaRenderContext contentTooltipRenderContext = new VanillaRenderContext(LytRect.empty(), 0); private final MinecraftFontMetrics fontMetrics = new MinecraftFontMetrics(); @Nullable @@ -204,7 +198,7 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawDefaultBackground(); } - drawRect(0, 0, width, height, 0x88000000); + drawRect(0, 0, width, height, ColorUtils.ARGB_88000000.getColor()); int panelW = panelWidth(); int panelH = panelHeight(); @@ -213,18 +207,18 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { int panelRight = panelX + panelW; int panelBottom = panelY + panelH; - drawRect(panelX, panelY, panelRight, panelBottom, 0xF0181C22); - drawRect(panelX, panelY, panelRight, panelY + 1, 0xFF586170); - drawRect(panelX, panelBottom - 1, panelRight, panelBottom, 0xFF586170); - drawRect(panelX, panelY, panelX + 1, panelBottom, 0xFF586170); - drawRect(panelRight - 1, panelY, panelRight, panelBottom, 0xFF586170); + drawRect(panelX, panelY, panelRight, panelBottom, ColorUtils.DIALOG.getColor()); + drawRect(panelX, panelY, panelRight, panelY + 1, ColorUtils.ARGB_FF586170.getColor()); + drawRect(panelX, panelBottom - 1, panelRight, panelBottom, ColorUtils.ARGB_FF586170.getColor()); + drawRect(panelX, panelY, panelX + 1, panelBottom, ColorUtils.ARGB_FF586170.getColor()); + drawRect(panelRight - 1, panelY, panelRight, panelBottom, ColorUtils.ARGB_FF586170.getColor()); drawCenteredString( fontRendererObj, StatCollector.translateToLocal("guidenh.welcome.title"), width / 2, panelY + 10, - 0xFFF0F0F0); + ColorUtils.TEXT.getColor()); if (closeButton != null) { closeButton.drawButton(mc, mouseX, mouseY); } @@ -240,7 +234,7 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { StatCollector.translateToLocal("guidenh.welcome.close_hint"), width / 2, panelBottom - 14, - 0xFFB8C0CC); + ColorUtils.ARGB_FFB8C0CC.getColor()); drawHoverTooltip(mouseX, mouseY); } @@ -453,7 +447,12 @@ private static MutableGuide resolvePageCollection() { private void renderDocument(int mouseX, int mouseY) { if (document == null) { - drawCenteredString(fontRendererObj, I18n.format("gui.done"), width / 2, documentTop(), 0xFFD0D8E0); + drawCenteredString( + fontRendererObj, + I18n.format("gui.done"), + width / 2, + documentTop(), + ColorUtils.TEXT_MUTED.getColor()); return; } @@ -469,7 +468,6 @@ private void renderDocument(int mouseX, int mouseY) { document.setHoveredElement(hit); int viewportTop = Math.max(0, Math.round(scrollY)); - renderContext.setLightDarkMode(LightDarkMode.DARK_MODE); renderContext.setViewport(new LytRect(0, viewportTop, docW, docH)); renderContext.setScreenHeight(height); renderContext.setDocumentOrigin(docX, docY); @@ -599,8 +597,8 @@ private void updateVisualScroll() { private void drawScrollbar() { LytRect track = scrollbarTrackRect(); LytRect thumb = scrollbarThumbRect(track); - drawRect(track.x(), track.y(), track.right(), track.bottom(), 0x33262D38); - int color = draggingScrollbar ? 0xFFFFFFFF : 0x99B8C0CC; + drawRect(track.x(), track.y(), track.right(), track.bottom(), ColorUtils.ARGB_33262D38.getColor()); + int color = draggingScrollbar ? ColorUtils.WHITE.getColor() : ColorUtils.ARGB_99B8C0CC.getColor(); drawRect(thumb.x(), thumb.y(), thumb.right(), thumb.bottom(), color); } @@ -719,9 +717,9 @@ private void drawContentTooltip(ContentTooltip tooltip, int mouseX, int mouseY) GL11.glDisable(GL11.GL_DEPTH_TEST); zLevel = 300F; itemRender.zLevel = 300F; - int background = 0xF0100010; - int borderTop = 0x505000FF; - int borderBottom = 0x5028007F; + int background = ColorUtils.ARGB_F0100010.getColor(); + int borderTop = ColorUtils.ARGB_505000FF.getColor(); + int borderBottom = ColorUtils.ARGB_5028007F.getColor(); drawGradientRect( x - padding, y - padding, diff --git a/src/main/java/com/hfstudio/guidenh/guide/latex/GuideLatexRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/latex/GuideLatexRenderer.java index 7495fdc4..c1a3b235 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/latex/GuideLatexRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/latex/GuideLatexRenderer.java @@ -17,13 +17,14 @@ import org.scilab.forge.jlatexmath.TeXFormula; import org.scilab.forge.jlatexmath.TeXIcon; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog; public class GuideLatexRenderer { public static final GuideLatexRenderer INSTANCE = new GuideLatexRenderer(); - private static final int DEFAULT_FILL_COLOR_ARGB = 0xFFFFFFFF; + private static final int DEFAULT_FILL_COLOR_ARGB = ColorUtils.WHITE.getColor(); /** Calibration formula used to determine a reference character height at a given sourceScale. */ private static final String CALIBRATION_FORMULA = "x"; @@ -204,7 +205,7 @@ public void renderLatex(int x, int y, int displayW, int displayH, int textureId) GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); Tessellator tess = Tessellator.instance; tess.startDrawingQuads(); @@ -238,7 +239,7 @@ private BufferedImage renderToImage(TeXIcon icon) { g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - g.setColor(new Color(0, 0, 0, 0)); + g.setColor(new Color(ColorUtils.TRANSPARENT.getColor(), true)); g.fillRect(0, 0, w, h); icon.paintIcon(null, g, 0, 0); diff --git a/src/main/java/com/hfstudio/guidenh/guide/layout/flow/LineBuilder.java b/src/main/java/com/hfstudio/guidenh/guide/layout/flow/LineBuilder.java index 5cd6fb15..fc5143e6 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/layout/flow/LineBuilder.java +++ b/src/main/java/com/hfstudio/guidenh/guide/layout/flow/LineBuilder.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.document.DefaultStyles; import com.hfstudio.guidenh.guide.document.LytRect; @@ -34,7 +35,7 @@ public class LineBuilder implements Consumer { private static final ThreadLocal LINE_BREAK_ITERATOR = ThreadLocal .withInitial(BreakIterator::getLineInstance); - private static final ConstantColor SPOILER_MASK_COLOR = new ConstantColor(0xFF000000); + private static final ConstantColor SPOILER_MASK_COLOR = new ConstantColor(ColorUtils.BLACK.getColor()); private final LayoutContext context; private final List lines; diff --git a/src/main/java/com/hfstudio/guidenh/guide/layout/flow/LineTextRun.java b/src/main/java/com/hfstudio/guidenh/guide/layout/flow/LineTextRun.java index c4091d84..f1e759b3 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/layout/flow/LineTextRun.java +++ b/src/main/java/com/hfstudio/guidenh/guide/layout/flow/LineTextRun.java @@ -1,7 +1,7 @@ package com.hfstudio.guidenh.guide.layout.flow; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.render.RenderContext; import com.hfstudio.guidenh.guide.style.ResolvedTextStyle; @@ -10,8 +10,8 @@ public class LineTextRun extends LineElement { public static final int INLINE_CODE_PAD_X = 3; public static final int INLINE_CODE_EXTRA_WIDTH = INLINE_CODE_PAD_X * 2; - public static final int INLINE_CODE_BACKGROUND_LIGHT = 0x1AF0F6FF; - public static final int INLINE_CODE_BACKGROUND_DARK = 0x1A6FB6FF; + public static final int INLINE_CODE_BACKGROUND_LIGHT = ColorUtils.ARGB_1AF0F6FF.getColor(); + public static final int INLINE_CODE_BACKGROUND_DARK = ColorUtils.ARGB_1A6FB6FF.getColor(); public final String text; public final ResolvedTextStyle style; @@ -41,9 +41,7 @@ public void render(RenderContext context) { if (width > 0 && height > 0) { int backgroundY = rect.y() - 1; if (inlineCode) { - int backgroundColorArgb = context.lightDarkMode() == LightDarkMode.DARK_MODE - ? INLINE_CODE_BACKGROUND_DARK - : INLINE_CODE_BACKGROUND_LIGHT; + int backgroundColorArgb = INLINE_CODE_BACKGROUND_DARK; context.fillRect(rect.x(), backgroundY, width, height, backgroundColorArgb); } else { context.fillRect(rect.x() - 1, backgroundY, width + 2, height, backgroundColor); diff --git a/src/main/java/com/hfstudio/guidenh/guide/mediawiki/MediaWikiGeneratedListBlock.java b/src/main/java/com/hfstudio/guidenh/guide/mediawiki/MediaWikiGeneratedListBlock.java index b6513ef3..3d39583b 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/mediawiki/MediaWikiGeneratedListBlock.java +++ b/src/main/java/com/hfstudio/guidenh/guide/mediawiki/MediaWikiGeneratedListBlock.java @@ -8,8 +8,8 @@ import com.hfstudio.guidenh.guide.GuidePageIcon; import com.hfstudio.guidenh.guide.PageAnchor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.document.DefaultStyles; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.block.BorderRenderer; @@ -42,12 +42,12 @@ public class MediaWikiGeneratedListBlock extends LytBlock implements Interactive private static final ConstantColor LIST_MARKER_COLOR = ConstantColor.WHITE; private static final ResolvedTextStyle LINK_STYLE = TextStyle.builder() .apply(DefaultStyles.BODY_TEXT) - .color(SymbolicColor.LINK) + .color(ColorUtils.LINK) .build() .mergeWith(DefaultStyles.BASE_STYLE); private static final ResolvedTextStyle HOVER_LINK_STYLE = TextStyle.builder() .apply(DefaultStyles.BODY_TEXT) - .color(SymbolicColor.LINK) + .color(ColorUtils.LINK) .underlined(true) .build() .mergeWith(DefaultStyles.BASE_STYLE); diff --git a/src/main/java/com/hfstudio/guidenh/guide/mediawiki/MediaWikiSpecialGeneratedBlock.java b/src/main/java/com/hfstudio/guidenh/guide/mediawiki/MediaWikiSpecialGeneratedBlock.java index 4316f18a..b5cddb0a 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/mediawiki/MediaWikiSpecialGeneratedBlock.java +++ b/src/main/java/com/hfstudio/guidenh/guide/mediawiki/MediaWikiSpecialGeneratedBlock.java @@ -14,8 +14,8 @@ import com.github.bsideup.jabel.Desugar; import com.hfstudio.guidenh.guide.GuidePageIcon; import com.hfstudio.guidenh.guide.PageAnchor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.document.DefaultStyles; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.block.BorderRenderer; @@ -58,12 +58,12 @@ public class MediaWikiSpecialGeneratedBlock extends LytBlock implements Interact private static final ConstantColor LIST_MARKER_COLOR = ConstantColor.WHITE; private static final ResolvedTextStyle LINK_STYLE = TextStyle.builder() .apply(DefaultStyles.BODY_TEXT) - .color(SymbolicColor.LINK) + .color(ColorUtils.LINK) .build() .mergeWith(DefaultStyles.BASE_STYLE); private static final ResolvedTextStyle HOVER_LINK_STYLE = TextStyle.builder() .apply(DefaultStyles.BODY_TEXT) - .color(SymbolicColor.LINK) + .color(ColorUtils.LINK) .underlined(true) .build() .mergeWith(DefaultStyles.BASE_STYLE); @@ -73,7 +73,7 @@ public class MediaWikiSpecialGeneratedBlock extends LytBlock implements Interact .mergeWith(DefaultStyles.BASE_STYLE); private static final ResolvedTextStyle SUBTITLE_STYLE = TextStyle.builder() .apply(DefaultStyles.BODY_TEXT) - .color(SymbolicColor.GRAY) + .color(ColorUtils.MC_GRAY) .build() .mergeWith(DefaultStyles.BASE_STYLE); private static final ResolvedTextStyle EMPTY_STYLE = DefaultStyles.BODY_TEXT.mergeWith(DefaultStyles.BASE_STYLE); diff --git a/src/main/java/com/hfstudio/guidenh/guide/render/RenderContext.java b/src/main/java/com/hfstudio/guidenh/guide/render/RenderContext.java index 490e2c6c..d8e29b28 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/render/RenderContext.java +++ b/src/main/java/com/hfstudio/guidenh/guide/render/RenderContext.java @@ -4,18 +4,11 @@ import net.minecraft.util.ResourceLocation; import com.hfstudio.guidenh.guide.color.ColorValue; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.style.ResolvedTextStyle; public interface RenderContext { - LightDarkMode lightDarkMode(); - - default boolean isDarkMode() { - return lightDarkMode() == LightDarkMode.DARK_MODE; - } - LytRect viewport(); default boolean intersectsViewport(LytRect bounds) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/render/VanillaRenderContext.java b/src/main/java/com/hfstudio/guidenh/guide/render/VanillaRenderContext.java index 7ef71339..0591e5a1 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/render/VanillaRenderContext.java +++ b/src/main/java/com/hfstudio/guidenh/guide/render/VanillaRenderContext.java @@ -15,8 +15,8 @@ import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.internal.util.DisplayScale; import com.hfstudio.guidenh.guide.style.ResolvedTextStyle; @@ -33,8 +33,6 @@ public class VanillaRenderContext implements RenderContext { @Setter private int screenHeight; - @Setter - private LightDarkMode lightDarkMode; @Setter private LytRect viewport; @@ -50,8 +48,7 @@ public class VanillaRenderContext implements RenderContext { @Getter private float zoom = 1.0f; - public VanillaRenderContext(LightDarkMode mode, LytRect viewport, int screenHeight) { - this.lightDarkMode = mode; + public VanillaRenderContext(LytRect viewport, int screenHeight) { this.viewport = viewport; this.screenHeight = screenHeight; this.fontRenderer = Minecraft.getMinecraft().fontRenderer; @@ -95,11 +92,6 @@ public LytRect toScreenRect(LytRect rect) { Math.max(1, Math.round(rect.height() * zoom))); } - @Override - public LightDarkMode lightDarkMode() { - return lightDarkMode; - } - @Override public LytRect viewport() { return viewport; @@ -107,7 +99,7 @@ public LytRect viewport() { @Override public int resolveColor(ColorValue ref) { - return ref.resolve(lightDarkMode); + return ref.resolve(); } @Override @@ -216,7 +208,7 @@ public void drawText(String text, int x, int y, ResolvedTextStyle style) { if (text == null || text.isEmpty()) return; int color = resolveColor(style.color()); if ((color >>> 24) == 0) { - color |= 0xFF000000; + color |= ColorUtils.BLACK.getColor(); } String drawn = GuideFontCompat.prepareRenderedText(text, style); @@ -314,7 +306,7 @@ private void renderItemInternal(ItemStack stack, int x, int y, boolean drawOverl // flushes). We instead explicitly restore every state we touch in the finally block. try { GL11.glDisable(GL11.GL_BLEND); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); RenderHelper.enableGUIStandardItemLighting(); GL11.glEnable(GL11.GL_LIGHTING); @@ -338,7 +330,7 @@ private void renderItemInternal(ItemStack stack, int x, int y, boolean drawOverl GL11.glDisable(GL11.GL_ALPHA_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } @@ -347,7 +339,7 @@ public void blitTexture(ResourceLocation texture, int x, int y, int u, int v, in Minecraft.getMinecraft() .getTextureManager() .bindTexture(texture); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); var tess = Tessellator.instance; float texW = 256f; float texH = 256f; @@ -374,7 +366,7 @@ public void fillIcon(LytRect rect, GuiSprite sprite, ColorValue color) { GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(r / 255f, g / 255f, b / 255f, a / 255f); + ColorUtils.applyGlColor(r / 255f, g / 255f, b / 255f, a / 255f); Minecraft.getMinecraft() .getTextureManager() .bindTexture(sprite.getTexture()); @@ -399,7 +391,7 @@ public void fillIcon(LytRect rect, GuiSprite sprite, ColorValue color) { tess.addVertexWithUV(x, y, 0, u / texW, v / texH); tess.draw(); } finally { - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glPopAttrib(); } } @@ -407,14 +399,14 @@ public void fillIcon(LytRect rect, GuiSprite sprite, ColorValue color) { @Override public void fillTexturedRect(LytRect rect, GuidePageTexture texture) { if (texture == null || texture.isMissing()) { - fillRect(rect, 0xFF333333); - drawBorder(rect, 0xFFFF00FF, 1); + fillRect(rect, ColorUtils.ARGB_FF333333.getColor()); + drawBorder(rect, ColorUtils.ARGB_FFFF00FF.getColor(), 1); return; } ResourceLocation resolvedTexture = texture.getTexture(); if (resolvedTexture == null) { - fillRect(rect, 0xFF333333); - drawBorder(rect, 0xFFFF00FF, 1); + fillRect(rect, ColorUtils.ARGB_FF333333.getColor()); + drawBorder(rect, ColorUtils.ARGB_FFFF00FF.getColor(), 1); return; } Minecraft.getMinecraft() @@ -423,7 +415,7 @@ public void fillTexturedRect(LytRect rect, GuidePageTexture texture) { GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); int x = rect.x(); int y = rect.y(); int w = rect.width(); @@ -441,14 +433,14 @@ public void fillTexturedRect(LytRect rect, GuidePageTexture texture) { public void fillTexturedRect(LytRect rect, GuidePageTexture texture, int sourceX, int sourceY, int sourceWidth, int sourceHeight) { if (texture == null || texture.isMissing()) { - fillRect(rect, 0xFF333333); - drawBorder(rect, 0xFFFF00FF, 1); + fillRect(rect, ColorUtils.ARGB_FF333333.getColor()); + drawBorder(rect, ColorUtils.ARGB_FFFF00FF.getColor(), 1); return; } ResourceLocation resolvedTexture = texture.getTexture(); if (resolvedTexture == null) { - fillRect(rect, 0xFF333333); - drawBorder(rect, 0xFFFF00FF, 1); + fillRect(rect, ColorUtils.ARGB_FF333333.getColor()); + drawBorder(rect, ColorUtils.ARGB_FFFF00FF.getColor(), 1); return; } int naturalWidth = Math.max( @@ -469,7 +461,7 @@ public void fillTexturedRect(LytRect rect, GuidePageTexture texture, int sourceX GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); int x = rect.x(); int y = rect.y(); int w = rect.width(); @@ -536,7 +528,7 @@ public void restoreExternalRenderState() { GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glDepthMask(true); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); RenderHelper.disableStandardItemLighting(); if (!scissorStack.isEmpty()) { @@ -571,7 +563,7 @@ private static void beginShapeDraw() { private static void endShapeDraw() { GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glPopAttrib(); } @@ -583,7 +575,7 @@ private static void applyArgb(int argb) { if (a == 0) { a = 0xFF; } - GL11.glColor4f(r / 255f, g / 255f, b / 255f, a / 255f); + ColorUtils.applyGlColor(r / 255f, g / 255f, b / 255f, a / 255f); } /** diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookLevelRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookLevelRenderer.java index d3510d9d..63c148b4 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookLevelRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookLevelRenderer.java @@ -39,7 +39,7 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; -import com.hfstudio.guidenh.guide.color.LightDarkMode; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.scene.GuidebookFakeRenderEnvironment; import com.hfstudio.guidenh.guide.internal.util.DisplayScale; import com.hfstudio.guidenh.guide.scene.annotation.InWorldAnnotation; @@ -94,12 +94,11 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int panelHeight, partialTicks, List.of(), - LightDarkMode.LIGHT_MODE, null); } public void render(GuidebookLevel level, CameraSettings camera, int panelX, int panelY, int panelWidth, - int panelHeight, float partialTicks, List annotations, LightDarkMode lightDarkMode) { + int panelHeight, float partialTicks, List annotations) { render( level, camera, @@ -113,13 +112,12 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int panelHeight, partialTicks, annotations, - lightDarkMode, null); } public void render(GuidebookLevel level, CameraSettings camera, int panelX, int panelY, int panelWidth, int panelHeight, int scissorX, int scissorY, int scissorW, int scissorH, float partialTicks, - List annotations, LightDarkMode lightDarkMode) { + List annotations) { render( level, camera, @@ -133,13 +131,12 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int scissorH, partialTicks, annotations, - lightDarkMode, null); } public void render(GuidebookLevel level, CameraSettings camera, int panelX, int panelY, int panelWidth, int panelHeight, int scissorX, int scissorY, int scissorW, int scissorH, float partialTicks, - List annotations, LightDarkMode lightDarkMode, @Nullable Integer visibleLayerY) { + List annotations, @Nullable Integer visibleLayerY) { render( level, camera, @@ -153,15 +150,13 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int scissorH, partialTicks, annotations, - lightDarkMode, visibleLayerY, List.of()); } public void render(GuidebookLevel level, CameraSettings camera, int panelX, int panelY, int panelWidth, int panelHeight, int scissorX, int scissorY, int scissorW, int scissorH, float partialTicks, - List annotations, LightDarkMode lightDarkMode, @Nullable Integer visibleLayerY, - List particles) { + List annotations, @Nullable Integer visibleLayerY, List particles) { render( level, camera, @@ -175,7 +170,6 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int scissorH, partialTicks, annotations, - lightDarkMode, GuidebookSceneLayerSelection.fromVisibleLayer(visibleLayerY), particles, List.of(), @@ -184,7 +178,7 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int public void render(GuidebookLevel level, CameraSettings camera, int panelX, int panelY, int panelWidth, int panelHeight, int scissorX, int scissorY, int scissorW, int scissorH, float partialTicks, - List annotations, LightDarkMode lightDarkMode, GuidebookSceneLayerSelection layerSelection, + List annotations, GuidebookSceneLayerSelection layerSelection, List particles) { render( level, @@ -199,7 +193,6 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int scissorH, partialTicks, annotations, - lightDarkMode, layerSelection, particles, List.of(), @@ -208,7 +201,7 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int public void render(GuidebookLevel level, CameraSettings camera, int panelX, int panelY, int panelWidth, int panelHeight, int scissorX, int scissorY, int scissorW, int scissorH, float partialTicks, - List annotations, LightDarkMode lightDarkMode, GuidebookSceneLayerSelection layerSelection, + List annotations, GuidebookSceneLayerSelection layerSelection, List particles, List weatherEffects, float weatherAnimationTick) { @@ -264,7 +257,7 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int GL11.glEnable(GL_TEXTURE_2D); GL11.glDisable(GL12.GL_RESCALE_NORMAL); GL11.glEnable(GL11.GL_NORMALIZE); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glNormal3f(0f, 1f, 0f); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); @@ -310,7 +303,7 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int renderEntities(level.getEntities(), partialTicks, layerSelection, camera); if (!annotations.isEmpty()) { - InWorldAnnotationRenderer.render(annotations, lightDarkMode); + InWorldAnnotationRenderer.render(annotations); } if (weatherEffects != null && !weatherEffects.isEmpty()) { renderWeatherInContext(level, camera, layerSelection, weatherEffects, weatherAnimationTick); @@ -356,7 +349,7 @@ public void render(GuidebookLevel level, CameraSettings camera, int panelX, int GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glEnable(GL_ALPHA_TEST); GL11.glAlphaFunc(GL11.GL_GREATER, 0.1f); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); RenderHelper.disableStandardItemLighting(); } finally { @@ -582,7 +575,7 @@ private void renderEntities(Iterable entities, float partialTicks, int upperBits = brightness / 65536; OpenGlHelper .setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float) lowerBits, (float) upperBits); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); // The scene view matrix already transforms world coordinates relative to the camera. renderManager.renderEntityWithPosYaw( entity, @@ -634,7 +627,7 @@ public static void preparePreviewModelLighting() { GL11.glDisable(GL12.GL_RESCALE_NORMAL); GL11.glEnable(GL11.GL_NORMALIZE); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } private void loadMatrix(Matrix4f m) { @@ -654,7 +647,7 @@ public static void setRenderPass(int pass) { } public static void setTileEntityRenderPassState(int pass) { - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); if (pass == 0) { GL11.glEnable(GL_DEPTH_TEST); GL11.glDisable(GL_BLEND); diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookSceneParticleFactory.java b/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookSceneParticleFactory.java index 1c7ec5aa..d06dcb68 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookSceneParticleFactory.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookSceneParticleFactory.java @@ -6,7 +6,7 @@ import net.minecraft.util.ResourceLocation; -import com.hfstudio.guidenh.guide.color.ARGB; +import com.hfstudio.guidenh.guide.color.ColorUtils; /** * Factory helpers for guidebook scene particles and reusable particle presets. @@ -268,9 +268,9 @@ public static void appendIndicatorPreset(List out, Rando } int maxAmountPerBlockFromBudget = Math.max(1, (int) (MAX_INDICATOR_TOTAL_PARTICLES / targetBlockCount)); resolvedAmountPerBlock = Math.min(resolvedAmountPerBlock, maxAmountPerBlockFromBudget); - float red = ARGB.red(color) / 255f; - float green = ARGB.green(color) / 255f; - float blue = ARGB.blue(color) / 255f; + float red = ColorUtils.red(color) / 255f; + float green = ColorUtils.green(color) / 255f; + float blue = ColorUtils.blue(color) / 255f; for (int blockX : xValues) { for (int blockY : yValues) { for (int blockZ : zValues) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookSceneWeatherSupport.java b/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookSceneWeatherSupport.java index f6898585..269be834 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookSceneWeatherSupport.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/GuidebookSceneWeatherSupport.java @@ -1,14 +1,15 @@ package com.hfstudio.guidenh.guide.scene; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.jetbrains.annotations.Nullable; import com.hfstudio.guidenh.guide.scene.level.GuidebookLevel; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; + public class GuidebookSceneWeatherSupport { public static final int[] EMPTY_BOUNDS = { 0, 0, 0, 0, 0, 0 }; @@ -148,7 +149,7 @@ public static List resolveRenderableEffects(List occupiedColumns = new HashSet<>(); + LongSet occupiedColumns = new LongOpenHashSet(); List resolved = new ArrayList<>(effects.size()); for (GuidebookSceneWeatherEffect effect : effects) { if (effect == null || activeTick != null && !effect.isActiveAt(activeTick)) { @@ -231,7 +232,7 @@ public static boolean intersectsVisibleLayer(GuidebookSceneWeatherEffect effect, } private static List trimWeatherAreas(List areas, - Set occupiedColumns) { + LongSet occupiedColumns) { if (areas == null || areas.isEmpty()) { return List.of(); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/LytGuidebookScene.java b/src/main/java/com/hfstudio/guidenh/guide/scene/LytGuidebookScene.java index df15e18b..25cc7b17 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/LytGuidebookScene.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/LytGuidebookScene.java @@ -46,6 +46,7 @@ import org.lwjgl.opengl.GL11; import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.document.DefaultStyles; import com.hfstudio.guidenh.guide.document.LytRect; @@ -117,6 +118,9 @@ import com.hfstudio.guidenh.integration.structurelib.StructureLibSceneMetadata; import com.hfstudio.guidenh.integration.structurelib.StructureLibTooltipContentBuilder; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.LongSet; import lombok.Getter; import lombok.Setter; @@ -144,13 +148,13 @@ public boolean overlaps(int otherStartTick, int otherEndTickExclusive) { public static final float MAX_ZOOM = 10f; private static final int MIN_RESPONSIVE_SCENE_SIZE = 16; public static final int SCENE_SLIDER_AREA_HEIGHT = 14; - private static final int LOADING_FILL_COLOR = 0xAAFFC107; + private static final int LOADING_FILL_COLOR = ColorUtils.ARGB_AAFFC107.getColor(); public static final int SCENE_SLIDER_SIDE_PADDING = 8; public static final float ORIGIN_AXIS_LENGTH = 1.5f; public static final float ORIGIN_AXIS_THICKNESS = 2.0f; - public static final int ORIGIN_X_AXIS_COLOR = 0xFFFF5A5A; - public static final int ORIGIN_Y_AXIS_COLOR = 0xFF67E26C; - public static final int ORIGIN_Z_AXIS_COLOR = 0xFF64A8FF; + public static final int ORIGIN_X_AXIS_COLOR = ColorUtils.X_AXIS.getColor(); + public static final int ORIGIN_Y_AXIS_COLOR = ColorUtils.Y_AXIS.getColor(); + public static final int ORIGIN_Z_AXIS_COLOR = ColorUtils.Z_AXIS.getColor(); public static final ResolvedTextStyle VISIBLE_LAYER_SLIDER_TEXT_STYLE = DefaultStyles.BODY_TEXT .mergeWith(DefaultStyles.BASE_STYLE); public static final ResolvedTextStyle STRUCTURELIB_TIER_SLIDER_TEXT_STYLE = DefaultStyles.BODY_TEXT @@ -164,8 +168,8 @@ public boolean overlaps(int otherStartTick, int otherEndTickExclusive) { .dropShadow(true) .build() .mergeWith(DefaultStyles.BASE_STYLE); - public static final int BLOCK_STATS_BACKGROUND_COLOR = 0xAA111922; - public static final int BLOCK_STATS_BORDER_COLOR = 0x66FFFFFF; + public static final int BLOCK_STATS_BACKGROUND_COLOR = ColorUtils.ARGB_AA111922.getColor(); + public static final int BLOCK_STATS_BORDER_COLOR = ColorUtils.ARGB_66FFFFFF.getColor(); public static final int BLOCK_STATS_PADDING_X = 5; public static final int BLOCK_STATS_PADDING_Y = 4; public static final int BLOCK_STATS_GAP = 4; @@ -179,8 +183,8 @@ public boolean overlaps(int otherStartTick, int otherEndTickExclusive) { public static final int BLOCK_STATS_SCROLLBAR_MIN_THUMB = 12; public static final int BLOCK_STATS_WHEEL_STEP = 18; public static final int BLOCK_STATS_DOCK_GAP = 4; - public static final int BLOCK_STATS_SELECTED_ROW_COLOR = 0x6656C8FF; - public static final int BLOCK_STATS_HIGHLIGHT_COLOR = 0x6600F5FF; + public static final int BLOCK_STATS_SELECTED_ROW_COLOR = ColorUtils.ARGB_6656C8FF.getColor(); + public static final int BLOCK_STATS_HIGHLIGHT_COLOR = ColorUtils.ARGB_6600F5FF.getColor(); private static final int MAX_PONDER_PARTICLE_POOL_SIZE = 1024; private int dragButton = -1; @@ -232,14 +236,14 @@ public boolean overlaps(int otherStartTick, int otherEndTickExclusive) { private int sceneAnimationTick = 0; private int ponderLastKeyframeIdx = -2; private int ponderAnnotationFadeTick = 5; - private final Set triggeredPonderSoundKeyframes = new HashSet<>(); - private final Map ponderBlockSnapshot = new LinkedHashMap<>(); + private final IntSet triggeredPonderSoundKeyframes = new IntOpenHashSet(); + private final Long2ObjectLinkedOpenHashMap ponderBlockSnapshot = new Long2ObjectLinkedOpenHashMap<>(); private final Map ponderEntityRefs = new LinkedHashMap<>(); private final Map ponderEntityRuntimesBySceneEntityId = new HashMap<>(); private final Map> ponderSceneEntityRefs = new HashMap<>(); private final List ponderTimedEntityAnimations = new ArrayList<>(); private final Map ponderEntityAnimationBaselines = new LinkedHashMap<>(); - private final Map ponderWeatherColumnReservations = new LinkedHashMap<>(); + private final Long2ObjectLinkedOpenHashMap ponderWeatherColumnReservations = new Long2ObjectLinkedOpenHashMap<>(); private boolean ponderTimelineBaselineReady; @Nullable private LytRect cachedPonderBarTrackRect; @@ -265,7 +269,7 @@ public boolean overlaps(int otherStartTick, int otherEndTickExclusive) { @Getter private float loadProgress; private String loadStatusText = ""; - private int loadStatusColor = 0xFFFFFFFF; + private int loadStatusColor = ColorUtils.WHITE.getColor(); @Getter @Setter private boolean reserveBottomControlArea = true; @@ -278,8 +282,8 @@ public boolean overlaps(int otherStartTick, int otherEndTickExclusive) { @Setter private boolean forceHideOriginAxes; - public static int SCENE_BG_COLOR = 0xFF0A0A10; - public static int SCENE_BORDER_COLOR = 0xFF303040; + public static int SCENE_BG_COLOR = ColorUtils.SCENE_BACKGROUND.getColor(); + public static int SCENE_BORDER_COLOR = ColorUtils.SCENE_BORDER.getColor(); public static final ResourceLocation BUTTONS_TEXTURE = new ResourceLocation( "guidenh", @@ -296,8 +300,8 @@ public boolean overlaps(int otherStartTick, int otherEndTickExclusive) { GuideIconButton.Role.PONDER_PLAY_PAUSE, GuideIconButton.Role.PONDER_RESTART }; public static final int PONDER_BTN_TOTAL_WIDTH = SCENE_SLIDER_AREA_HEIGHT * 3; - public static final int PONDER_KEYFRAME_NODE_COLOR = 0xC0AAAADD; - public static final int PONDER_KEYFRAME_NODE_HOVER_COLOR = 0xFFC0C0FF; + public static final int PONDER_KEYFRAME_NODE_COLOR = ColorUtils.ARGB_C0AAAADD.getColor(); + public static final int PONDER_KEYFRAME_NODE_HOVER_COLOR = ColorUtils.ARGB_FFC0C0FF.getColor(); public static final int DEFAULT_WIDTH = 256; public static final int DEFAULT_HEIGHT = 192; @@ -341,9 +345,41 @@ public boolean overlaps(int otherStartTick, int otherEndTickExclusive) { private final Vector3f projectedLineFromScratch = new Vector3f(); private final Vector3f projectedLineToScratch = new Vector3f(); private final float[] pickRayScratch = new float[6]; + private boolean hoveredSceneTargetCacheValid; + private int cachedPickMouseX; + private int cachedPickMouseY; + private int cachedPickViewportX; + private int cachedPickViewportY; + private int cachedPickViewportW; + private int cachedPickViewportH; + private long cachedPickSpatialRevision; + private int cachedPickPonderTick; + @Nullable + private Integer cachedPickVisibleLayerY; + private float cachedPickZoom; + private float cachedPickRotationX; + private float cachedPickRotationY; + private float cachedPickRotationZ; + private float cachedPickOffsetX; + private float cachedPickOffsetY; + private float cachedPickRotationCenterX; + private float cachedPickRotationCenterY; + private float cachedPickRotationCenterZ; + @Nullable + private int[] cachedHoveredBlock; + @Nullable + private AxisAlignedBB cachedHoveredBlockBounds; + @Nullable + private MovingObjectPosition cachedHoveredBlockHitResult; + @Nullable + private Entity cachedHoveredEntity; + @Nullable + private AxisAlignedBB cachedHoveredEntityBounds; + @Nullable + private MovingObjectPosition cachedHoveredEntityHitResult; private final float[] diggingParticleColorScratch = new float[3]; private final float[] diggingParticleVelocityScratch = new float[3]; - private final ConstantColor hoverBoxColor = new ConstantColor(0xFFFFFFFF); + private final ConstantColor hoverBoxColor = new ConstantColor(ColorUtils.WHITE.getColor()); private final ConstantColor blockStatsHighlightColor = new ConstantColor(BLOCK_STATS_HIGHLIGHT_COLOR); private final ConstantColor originXAxisColor = new ConstantColor(ORIGIN_X_AXIS_COLOR); @@ -572,6 +608,7 @@ public void setLevel(GuidebookLevel level) { } snapshotInitialCamera(); clearLayerDrivenHoverState(); + hoveredSceneTargetCacheValid = false; markBlockStatsDirty(); } @@ -584,6 +621,7 @@ public void addSoundCue(SceneSoundCue cue) { public void setCamera(CameraSettings camera) { this.camera = camera != null ? camera : new CameraSettings(); snapshotInitialCamera(); + hoveredSceneTargetCacheValid = false; } public void snapshotInitialCamera() { @@ -1110,6 +1148,7 @@ private void clearLayerDrivenHoverState() { hoveredEntityHitResult = null; hoveredStructureLibHatch = null; clearAnnotationHover(); + hoveredSceneTargetCacheValid = false; } public StructureLibSceneBinding registerStructureLibBinding(@Nullable String name) { @@ -1282,8 +1321,6 @@ public StructureLibImportResult getStructureLibImportResult(@Nullable String nam return binding != null ? binding.getLastSuccessfulImportResult() : null; } - // ========== SNBT placements (ImportStructure) ========== - public void addSnbtPlacement(SnbtPlacement placement) { snbtPlacements.add(placement); } @@ -1301,8 +1338,6 @@ public void clearSnbtPlacements() { snbtPlacements.clear(); } - // ========== Unified build / clear / rebuild ========== - /** * Build all blocks in the scene from registered SNBT placements and StructureLib bindings. * Called after element compilers have registered their configs, @@ -1648,14 +1683,14 @@ public void setLoading(boolean loading) { this.isLoading = loading; if (loading) { this.loadFailed = false; - this.loadStatusColor = 0xFFFFFFFF; + this.loadStatusColor = ColorUtils.WHITE.getColor(); } } public void setLoadProgress(int done, int total) { this.loadProgress = total > 0 ? (float) done / (float) total : 0f; this.loadStatusText = "Loading import (" + done + "/" + total + ")..."; - this.loadStatusColor = 0xFFFFFFFF; + this.loadStatusColor = ColorUtils.WHITE.getColor(); this.loadFailed = false; } @@ -1665,7 +1700,7 @@ public void setLoadFailure(String message) { this.loadProgress = 0f; this.loadStatusText = message != null && !message.trim() .isEmpty() ? message.trim() : "StructureLib preview failed"; - this.loadStatusColor = 0xFFFF5555; + this.loadStatusColor = ColorUtils.ARGB_FFFF5555.getColor(); } public void clearLoadState() { @@ -1673,7 +1708,7 @@ public void clearLoadState() { this.loadFailed = false; this.loadProgress = 0f; this.loadStatusText = ""; - this.loadStatusColor = 0xFFFFFFFF; + this.loadStatusColor = ColorUtils.WHITE.getColor(); } public void setBottomControlsVisible(boolean bottomControlsVisible) { @@ -2465,7 +2500,6 @@ else if (pa instanceof OverlayAnnotation ov) { clipH, 0f, inWorld, - context.lightDarkMode(), weatherLayerSelection, resolveRenderableSceneParticles(), weatherEffects, @@ -3242,8 +3276,8 @@ private static void drawBlockStatsScrollbar(RenderContext context, @Nullable Lyt if (track == null || thumb == null || track.isEmpty() || thumb.isEmpty()) { return; } - context.fillRect(track, 0x5522262C); - context.fillRect(thumb, 0xCCEAF6FF); + context.fillRect(track, ColorUtils.ARGB_5522262C.getColor()); + context.fillRect(thumb, ColorUtils.ARGB_CCEAF6FF.getColor()); } public static class BlockStatsHitRegion { @@ -3461,7 +3495,7 @@ private void drawSceneButtons(RenderContext context, LytRect sceneRect, LytRect GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit); int mx, my; @@ -3550,7 +3584,7 @@ private void drawOneSceneButton(int x, int y, int btnSize, GuideIconButton.Role int r = (color >>> 16) & 0xFF; int g = (color >>> 8) & 0xFF; int b = color & 0xFF; - GL11.glColor4f(r / 255f, g / 255f, b / 255f, a / 255f); + ColorUtils.applyGlColor(r / 255f, g / 255f, b / 255f, a / 255f); float texSize = GuideIconButton.TEXTURE_SIZE; float u0 = role.iconSrcX() / texSize; float v0 = role.iconSrcY() / texSize; @@ -3563,7 +3597,7 @@ private void drawOneSceneButton(int x, int y, int btnSize, GuideIconButton.Role tess.addVertexWithUV(x + btnSize, y, 0, u1, v0); tess.addVertexWithUV(x, y, 0, u0, v0); tess.draw(); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } private boolean isSceneButtonActive(GuideIconButton.Role role) { @@ -3623,6 +3657,7 @@ public void setHoveredBlock(int @Nullable [] xyz) { this.hoveredBlockBounds = null; this.hoveredBlockHitResult = null; } + hoveredSceneTargetCacheValid = false; } public void setHoveredEntity(@Nullable Entity entity) { @@ -3631,6 +3666,7 @@ public void setHoveredEntity(@Nullable Entity entity) { this.hoveredEntityBounds = null; this.hoveredEntityHitResult = null; } + hoveredSceneTargetCacheValid = false; } public int @Nullable [] getHoveredBlock() { @@ -3657,10 +3693,18 @@ public MovingObjectPosition getHoveredEntityHitResult() { } public void updateHoveredSceneTarget(int mouseAbsX, int mouseAbsY) { + updateVisualCameraState(); + Integer visibleLayerY = resolveVisibleLayerY(); + if (isHoveredSceneTargetCacheHit(mouseAbsX, mouseAbsY, visibleLayerY)) { + restoreCachedHoveredSceneTarget(); + return; + } + cacheHoveredSceneTargetInput(mouseAbsX, mouseAbsY, visibleLayerY); PickRay pickRay = resolvePickRay(mouseAbsX, mouseAbsY); if (pickRay == null) { setHoveredEntity(null); setHoveredBlock(null); + cacheHoveredSceneTargetResult(); return; } @@ -3671,18 +3715,93 @@ public void updateHoveredSceneTarget(int mouseAbsX, int mouseAbsY) { hoveredEntityBounds = entityHit.getBounds(); hoveredEntityHitResult = entityHit.getHitResult(); setHoveredBlock(null); + cacheHoveredSceneTargetResult(); return; } setHoveredEntity(null); if (blockHit == null) { setHoveredBlock(null); + cacheHoveredSceneTargetResult(); return; } hoveredBlock = blockHit.pos; hoveredBlockBounds = blockHit.bounds; hoveredBlockHitResult = blockHit.hitResult; + cacheHoveredSceneTargetResult(); + } + + private boolean isHoveredSceneTargetCacheHit(int mouseAbsX, int mouseAbsY, @Nullable Integer visibleLayerY) { + if (!hoveredSceneTargetCacheValid || cachedPickMouseX != mouseAbsX + || cachedPickMouseY != mouseAbsY + || cachedPickViewportX != lastAbsX + || cachedPickViewportY != lastAbsY + || cachedPickViewportW != lastW + || cachedPickViewportH != lastH + || cachedPickSpatialRevision != level.getSpatialRevision() + || cachedPickPonderTick != ponderCurrentTick + || !Objects.equals(cachedPickVisibleLayerY, visibleLayerY)) { + return false; + } + return Float.floatToIntBits(cachedPickZoom) == Float.floatToIntBits(visualCamZoom.value()) + && Float.floatToIntBits(cachedPickRotationX) == Float.floatToIntBits(visualCamRotX.value()) + && Float.floatToIntBits(cachedPickRotationY) == Float.floatToIntBits(visualCamRotY.value()) + && Float.floatToIntBits(cachedPickRotationZ) == Float.floatToIntBits(visualCamRotZ.value()) + && Float.floatToIntBits(cachedPickOffsetX) == Float.floatToIntBits(visualCamOffX.value()) + && Float.floatToIntBits(cachedPickOffsetY) == Float.floatToIntBits(visualCamOffY.value()) + && Float.floatToIntBits(cachedPickRotationCenterX) == Float.floatToIntBits( + camera.getRotationCenter() + .x()) + && Float.floatToIntBits(cachedPickRotationCenterY) == Float.floatToIntBits( + camera.getRotationCenter() + .y()) + && Float.floatToIntBits(cachedPickRotationCenterZ) == Float.floatToIntBits( + camera.getRotationCenter() + .z()); + } + + private void cacheHoveredSceneTargetInput(int mouseAbsX, int mouseAbsY, @Nullable Integer visibleLayerY) { + cachedPickMouseX = mouseAbsX; + cachedPickMouseY = mouseAbsY; + cachedPickViewportX = lastAbsX; + cachedPickViewportY = lastAbsY; + cachedPickViewportW = lastW; + cachedPickViewportH = lastH; + cachedPickSpatialRevision = level.getSpatialRevision(); + cachedPickPonderTick = ponderCurrentTick; + cachedPickVisibleLayerY = visibleLayerY; + cachedPickZoom = visualCamZoom.value(); + cachedPickRotationX = visualCamRotX.value(); + cachedPickRotationY = visualCamRotY.value(); + cachedPickRotationZ = visualCamRotZ.value(); + cachedPickOffsetX = visualCamOffX.value(); + cachedPickOffsetY = visualCamOffY.value(); + cachedPickRotationCenterX = camera.getRotationCenter() + .x(); + cachedPickRotationCenterY = camera.getRotationCenter() + .y(); + cachedPickRotationCenterZ = camera.getRotationCenter() + .z(); + } + + private void cacheHoveredSceneTargetResult() { + cachedHoveredBlock = hoveredBlock; + cachedHoveredBlockBounds = hoveredBlockBounds; + cachedHoveredBlockHitResult = hoveredBlockHitResult; + cachedHoveredEntity = hoveredEntity; + cachedHoveredEntityBounds = hoveredEntityBounds; + cachedHoveredEntityHitResult = hoveredEntityHitResult; + hoveredSceneTargetCacheValid = true; + } + + private void restoreCachedHoveredSceneTarget() { + hoveredBlock = cachedHoveredBlock; + hoveredBlockBounds = cachedHoveredBlockBounds; + hoveredBlockHitResult = cachedHoveredBlockHitResult; + hoveredEntity = cachedHoveredEntity; + hoveredEntityBounds = cachedHoveredEntityBounds; + hoveredEntityHitResult = cachedHoveredEntityHitResult; } public int @Nullable [] pickStructureLibHatch(int mouseAbsX, int mouseAbsY) { @@ -6704,11 +6823,15 @@ private void drawLoadProgressOverlay(RenderContext context, LytRect sceneRect) { int trackH = 4; // Track - context.fillRect(new LytRect(barX, barY, barWidth, trackH), loadFailed ? 0x66AA2222 : 0x6622262C); + context.fillRect( + new LytRect(barX, barY, barWidth, trackH), + loadFailed ? ColorUtils.ARGB_66AA2222.getColor() : ColorUtils.ARGB_6622262C.getColor()); // Fill (amber yellow) int fillW = Math.round(barWidth * loadProgress); if (fillW > 0) { - context.fillRect(new LytRect(barX, barY, fillW, trackH), loadFailed ? 0xFFFF5555 : LOADING_FILL_COLOR); + context.fillRect( + new LytRect(barX, barY, fillW, trackH), + loadFailed ? ColorUtils.ARGB_FFFF5555.getColor() : LOADING_FILL_COLOR); } // Status text if (loadStatusText != null && !loadStatusText.isEmpty()) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/StructureLibSceneBinding.java b/src/main/java/com/hfstudio/guidenh/guide/scene/StructureLibSceneBinding.java index a73e193f..26e51ff2 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/StructureLibSceneBinding.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/StructureLibSceneBinding.java @@ -107,8 +107,6 @@ public Map getChannelOverrides() { return channelOverrides; } - // ========== Pending selection (UI state across page reloads) ========== - @Nullable private StructureLibPreviewSelection pendingSelection; @@ -121,8 +119,6 @@ public void setPendingSelection(@Nullable StructureLibPreviewSelection pendingSe this.pendingSelection = pendingSelection; } - // ========== Apply selection (convenience for scene to restore state) ========== - public void applyPreviewSelection(StructureLibPreviewSelection selection) { if (selection == null) return; setCurrentTier(selection.getMasterTier()); @@ -133,8 +129,6 @@ public void applyPreviewSelection(StructureLibPreviewSelection selection) { } } - // ========== Rebuild recipe ========== - public void setRebuildRecipe(StructureLibBuildRequest request, int offsetX, int offsetY, int offsetZ, boolean formed) { this.rebuildRequestTemplate = request; @@ -164,8 +158,6 @@ public StructureLibBuildRequest buildRebuildRequest() { return req; } - // ========== Selection listener ========== - @Nullable public Consumer getSelectionChangeListener() { return selectionChangeListener; @@ -175,8 +167,6 @@ public void setSelectionChangeListener(@Nullable Consumer annotations, LightDarkMode lightDarkMode) { + public static void render(Iterable annotations) { // Single up-front scan: bail out early when there is nothing to draw (the common case for // scenes without highlights), and at the same time figure out whether any non-occluded // pass / always-on-top pass actually has work to do. Avoids paying for a full GL state @@ -47,17 +47,17 @@ public static void render(Iterable annotations, LightDarkMode GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glDepthFunc(GL11.GL_GREATER); GL11.glDepthMask(false); - drawAll(annotations, lightDarkMode, /* occluded */ true, /* pass2 */ false); + drawAll(annotations, /* occluded */ true, /* pass2 */ false); GL11.glDepthFunc(GL11.GL_LEQUAL); GL11.glDepthMask(true); - drawAll(annotations, lightDarkMode, /* occluded */ false, /* pass2 */ false); + drawAll(annotations, /* occluded */ false, /* pass2 */ false); } // Pass 2b: alwaysOnTop. if (hasAlwaysOnTop) { GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); - drawAll(annotations, lightDarkMode, /* occluded */ false, /* pass2 */ true); + drawAll(annotations, /* occluded */ false, /* pass2 */ true); } } finally { GL11.glDepthFunc(GL11.GL_LEQUAL); @@ -67,22 +67,21 @@ public static void render(Iterable annotations, LightDarkMode } } - public static void drawAll(Iterable annotations, LightDarkMode mode, boolean occluded, - boolean pass2) { + public static void drawAll(Iterable annotations, boolean occluded, boolean pass2) { for (var a : annotations) { if (a.isAlwaysOnTop() != pass2) continue; if (occluded && a.isAlwaysOnTop()) continue; if (a instanceof InWorldBoxAnnotation box) { - int color = resolve(box.color(), mode, a.isHovered(), occluded); + int color = resolve(box.color(), a.isHovered(), occluded); drawBoxEdges(box.min(), box.max(), color, box.thickness()); } else if (a instanceof InWorldBoxFaceOverlayAnnotation overlay) { if (!occluded) { - int color = resolve(overlay.color(), mode, a.isHovered(), false); + int color = resolve(overlay.color(), a.isHovered(), false); drawBoxFaceOverlay(overlay, color); } } else if (a instanceof InWorldLineAnnotation line) { - int color = resolve(line.color(), mode, a.isHovered(), occluded); - drawLineAnnotation(line, mode, color, occluded); + int color = resolve(line.color(), a.isHovered(), occluded); + drawLineAnnotation(line, color, occluded); } else if (a instanceof SceneFloorGridAnnotation grid) { if (!occluded) { drawFloorGrid(grid); @@ -91,8 +90,7 @@ public static void drawAll(Iterable annotations, LightDarkMod } } - private static void drawLineAnnotation(InWorldLineAnnotation line, LightDarkMode mode, int color, - boolean occluded) { + private static void drawLineAnnotation(InWorldLineAnnotation line, int color, boolean occluded) { var points = line.points(); for (int i = 0; i + 1 < points.size(); i++) { Vector3f from = points.get(i); @@ -110,10 +108,10 @@ private static void drawLineAnnotation(InWorldLineAnnotation line, LightDarkMode } else if (line.arrow() == InWorldLineAnnotation.Arrow.END) { drawArrowHead(points.getLast(), points.get(points.size() - 2), color, line.thickness()); } - drawLinePoints(line, mode, occluded); + drawLinePoints(line, occluded); } - private static void drawLinePoints(InWorldLineAnnotation line, LightDarkMode mode, boolean occluded) { + private static void drawLinePoints(InWorldLineAnnotation line, boolean occluded) { var points = line.points(); for (int i = 0; i < points.size(); i++) { InWorldLineAnnotation.PointStyle style = line.pointStyleFor(i); @@ -123,13 +121,13 @@ private static void drawLinePoints(InWorldLineAnnotation line, LightDarkMode mod } ColorValue colorValue = style != null && style.color() != null ? style.color() : line.pointColor(); float size = style != null && style.size() != null ? style.size() : line.pointSize(); - int color = resolve(colorValue, mode, line.isHovered(), occluded); + int color = resolve(colorValue, line.isHovered(), occluded); drawPointCube(points.get(i), color, size); } } - public static int resolve(ColorValue cv, LightDarkMode mode, boolean hovered, boolean occluded) { - int argb = cv.resolve(mode); + public static int resolve(ColorValue cv, boolean hovered, boolean occluded) { + int argb = cv.resolve(); if (hovered) argb = lighter(argb, 50); if (occluded) { argb = darker(argb, 50); @@ -574,7 +572,7 @@ public static void drawFloorGrid(SceneFloorGridAnnotation grid) { int z0 = grid.getMinZ(); int x1 = grid.getMaxX(); int z1 = grid.getMaxZ(); - int color = 0x55FFFFFF; + int color = ColorUtils.ARGB_55FFFFFF.getColor(); applyColor(color); GL11.glBegin(GL11.GL_QUADS); for (int ix = x0; ix <= x1; ix++) { @@ -636,7 +634,7 @@ private static void drawFloorGridLabels(SceneFloorGridAnnotation grid) { GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); // X-axis numbers: vertical signs standing at the north (-Z) edge, one per column. // Sign faces outward toward -Z, so rotateY = 0. @@ -685,7 +683,7 @@ private static void drawVerticalLabel(FontRenderer fr, String text, float wx, fl GL11.glScalef(-scale, -scale, scale); // Center the label horizontally within the cell. GL11.glTranslatef(-textWidthPx / 2f, 0f, 0f); - fr.drawStringWithShadow(text, 0, 0, 0xFFFFFF); + fr.drawStringWithShadow(text, 0, 0, ColorUtils.RGB_WHITE.getColor()); GL11.glPopMatrix(); } @@ -706,12 +704,12 @@ private static void drawFloorGridDirLabel(FontRenderer fr, String text, float wx GL11.glRotatef(90f, 1f, 0f, 0f); GL11.glScalef(-scale, -scale, scale); GL11.glTranslatef(-labelW / 2f, 0f, 0f); - fr.drawStringWithShadow(text, 0, 0, 0x66FFFFFF); + fr.drawStringWithShadow(text, 0, 0, ColorUtils.ARGB_66FFFFFF.getColor()); // Ponder-style fade: bar then dot below the initial. int barX = labelW / 2 - fr.getStringWidth("|") / 2; int dotX = labelW / 2 - fr.getStringWidth(".") / 2; - fr.drawStringWithShadow("|", barX, fr.FONT_HEIGHT - 1, 0x44FFFFFF); - fr.drawStringWithShadow(".", dotX, fr.FONT_HEIGHT * 2 - 2, 0x22FFFFFF); + fr.drawStringWithShadow("|", barX, fr.FONT_HEIGHT - 1, ColorUtils.ARGB_44FFFFFF.getColor()); + fr.drawStringWithShadow(".", dotX, fr.FONT_HEIGHT * 2 - 2, ColorUtils.ARGB_22FFFFFF.getColor()); GL11.glPopMatrix(); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/PonderInputAnnotation.java b/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/PonderInputAnnotation.java index 25b770a1..57597c48 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/PonderInputAnnotation.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/PonderInputAnnotation.java @@ -12,6 +12,7 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.internal.screen.GuideIconButton; import com.hfstudio.guidenh.guide.render.RenderContext; @@ -140,12 +141,19 @@ public void render(CameraSettings camera, RenderContext context, LytRect viewpor int textX = cx - textW / 2; int textY = by - mc.fontRenderer.FONT_HEIGHT - 2; GL11.glEnable(GL11.GL_TEXTURE_2D); - mc.fontRenderer.drawStringWithShadow(modText, textX, textY, applyFade(0xFFCCCCCC, fade)); + mc.fontRenderer + .drawStringWithShadow(modText, textX, textY, applyFade(ColorUtils.ARGB_FFCCCCCC.getColor(), fade)); GL11.glDisable(GL11.GL_TEXTURE_2D); } - TextAnnotation.drawFilledRect(bx - 1, by - 1, bx + boxW + 1, by + boxH + 1, applyFade(0x80AAAADD, fade)); - TextAnnotation.drawFilledRect(bx, by, bx + boxW, by + boxH, applyFade(0xCC0E0E20, fade)); + TextAnnotation.drawFilledRect( + bx - 1, + by - 1, + bx + boxW + 1, + by + boxH + 1, + applyFade(ColorUtils.ARGB_80AAAADD.getColor(), fade)); + TextAnnotation + .drawFilledRect(bx, by, bx + boxW, by + boxH, applyFade(ColorUtils.ARGB_CC0E0E20.getColor(), fade)); GL11.glEnable(GL11.GL_TEXTURE_2D); @@ -179,7 +187,7 @@ public void render(CameraSettings camera, RenderContext context, LytRect viewpor mc.getTextureManager() .bindTexture(GuideIconButton.PONDER_WIDGETS_TEX); - GL11.glColor4f(1f, 1f, 1f, fade); + ColorUtils.applyWhite(fade); float texSize = 256f; float u0 = inputType.srcX / texSize; float v0 = inputType.srcY / texSize; @@ -194,7 +202,7 @@ public void render(CameraSettings camera, RenderContext context, LytRect viewpor tess.addVertexWithUV(iconX, iconY, 0, u0, v0); tess.draw(); - GL11.glColor4f(1f, 1f, 1f, fade); + ColorUtils.applyWhite(fade); GL11.glDisable(GL11.GL_BLEND); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/TextAnnotation.java b/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/TextAnnotation.java index 8878e9d9..9e8ac5a0 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/TextAnnotation.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/TextAnnotation.java @@ -11,6 +11,7 @@ import org.joml.Vector3f; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.document.LytRect; @@ -41,7 +42,7 @@ public class TextAnnotation extends OverlayAnnotation { public static final int LINE_GAP = 2; public static final int CONNECTOR_HEIGHT = 6; public static final int DEFAULT_BACKGROUND_ALPHA = 0xCC; - private static final int BACKGROUND_RGB = 0x0E0E20; + private static final int BACKGROUND_RGB = ColorUtils.ARGB_0E0E20.getColor(); @Getter private final Vector3f worldPos; @@ -213,7 +214,7 @@ public void render(CameraSettings camera, RenderContext context, LytRect viewpor viewport.width(), viewport.height()); float fade = getFade(); - int borderArgb = borderColor.resolve(context.lightDarkMode()); + int borderArgb = borderColor.resolve(); LayoutMeasure measure = measureLayout(localViewport.width()); if (richContent != null) { @@ -246,7 +247,7 @@ public void render(CameraSettings camera, RenderContext context, LytRect viewpor richContent.layout(layoutContext, bx + PADDING_X, by + PADDING_Y, measure.availableWidth()); GL11.glEnable(GL11.GL_TEXTURE_2D); richContent.render(context); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glDisable(GL11.GL_BLEND); return; } @@ -278,14 +279,14 @@ public void render(CameraSettings camera, RenderContext context, LytRect viewpor GL11.glEnable(GL11.GL_TEXTURE_2D); - int textArgb = applyFade(0xFFFFFFFF, fade); + int textArgb = applyFade(ColorUtils.WHITE.getColor(), fade); int lineY = by + PADDING_Y; for (String line : lines) { fr.drawStringWithShadow(line, bx + PADDING_X, lineY, textArgb); lineY += fr.FONT_HEIGHT + LINE_GAP; } - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glDisable(GL11.GL_BLEND); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/compiler/DiamondAnnotationElementCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/compiler/DiamondAnnotationElementCompiler.java index 25a9f984..2384fdb4 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/compiler/DiamondAnnotationElementCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/annotation/compiler/DiamondAnnotationElementCompiler.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.tags.MdxAttrs; @@ -21,7 +22,7 @@ public class DiamondAnnotationElementCompiler extends AnnotationTagCompiler { /** Default green used when the MDX tag omits the {@code color} attribute. */ - public static final ConstantColor DEFAULT_DIAMOND_COLOR = new ConstantColor(0xFF00E000); + public static final ConstantColor DEFAULT_DIAMOND_COLOR = new ConstantColor(ColorUtils.ARGB_FF00E000.getColor()); @Override public Set getTagNames() { diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/cache/GuideSceneStructureSnapshot.java b/src/main/java/com/hfstudio/guidenh/guide/scene/cache/GuideSceneStructureSnapshot.java index 6db3038b..b31bd877 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/cache/GuideSceneStructureSnapshot.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/cache/GuideSceneStructureSnapshot.java @@ -31,6 +31,9 @@ import com.hfstudio.guidenh.guide.scene.level.GuidebookTileEntityLoader; import com.hfstudio.guidenh.integration.gregtech.GregTechHelpers; +import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + public class GuideSceneStructureSnapshot implements Serializable { @Serial @@ -170,7 +173,7 @@ private Map indexExplicitBlockIds() { if (explicitBlockIds.isEmpty()) { return Map.of(); } - HashMap indexed = new HashMap<>(explicitBlockIds.size()); + Long2ObjectOpenHashMap indexed = new Long2ObjectOpenHashMap<>(explicitBlockIds.size()); for (ExplicitBlockIdEntry entry : explicitBlockIds) { indexed.put(GuidebookLevel.packPos(entry.x, entry.y, entry.z), entry.explicitBlockId); } @@ -252,7 +255,7 @@ private void restorePreviewAuthority(GuidebookLevel level) { if (previewAuthorityEntries.isEmpty()) { return; } - LinkedHashMap> restored = new LinkedHashMap<>(); + Long2ObjectLinkedOpenHashMap> restored = new Long2ObjectLinkedOpenHashMap<>(); for (PreviewAuthorityEntry entry : previewAuthorityEntries) { restored.put(entry.packedPos, entry.payloads()); } diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/element/ImportPonderElementCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/scene/element/ImportPonderElementCompiler.java index 27198d50..d3a43757 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/element/ImportPonderElementCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/element/ImportPonderElementCompiler.java @@ -12,6 +12,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.tags.MdxAttrs; @@ -142,7 +143,7 @@ private static void resolveAndAdd(PonderKeyframeAnnotation raw, List points = resolveLinePoints(raw); - int argb = raw.parseColor(0xFFFFFFFF); + int argb = raw.parseColor(ColorUtils.WHITE.getColor()); float lw = raw.getLineWidth(InWorldLineAnnotation.DEFAULT_THICKNESS); var ann = new InWorldLineAnnotation(points, new ConstantColor(argb), lw); ann.setAlwaysOnTop(raw.isAlwaysOnTop()); @@ -204,7 +205,7 @@ private static SceneAnnotation resolveAnnotation(PonderKeyframeAnnotation raw, P int bx = raw.getBlockX(0); int by = raw.getBlockY(0); int bz = raw.getBlockZ(0); - int argb = raw.parseColor(0x80FFFFFF); + int argb = raw.parseColor(ColorUtils.ARGB_80FFFFFF.getColor()); var ann = new InWorldBlockFaceOverlayAnnotation(bx, by, bz, new ConstantColor(argb), Set.of()); ann.setAlwaysOnTop(raw.isAlwaysOnTop()); return ann; @@ -213,7 +214,7 @@ private static SceneAnnotation resolveAnnotation(PonderKeyframeAnnotation raw, P var pos = new Vector3f(raw.getX(0f), raw.getY(0f), raw.getZ(0f)); String msg = raw.getText(); if (msg == null || msg.isEmpty()) return null; - int borderArgb = raw.parseColor(0xFFAAAAAA); + int borderArgb = raw.parseColor(ColorUtils.ARGB_FFAAAAAA.getColor()); int maxW = raw.getMaxWidth(0); TextAnnotation ann; if (raw.isIndependent()) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/element/ImportStructureLibElementCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/scene/element/ImportStructureLibElementCompiler.java index 6de66378..2b8e192d 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/element/ImportStructureLibElementCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/element/ImportStructureLibElementCompiler.java @@ -121,8 +121,6 @@ public void compile(GuidebookLevel level, CameraSettings camera, PageCompiler co } } - // ========== Utility for callers that need to replicate parsing ========== - @Nullable public static StructureLibBuildRequest buildDefaultPreviewRequest(MdxJsxElementFields el) { return buildDefaultPreviewRequest(null, NoopErrorSink.INSTANCE, el); diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/element/TextAnnotationElementCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/scene/element/TextAnnotationElementCompiler.java index f963f4d8..21c68c2b 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/element/TextAnnotationElementCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/element/TextAnnotationElementCompiler.java @@ -6,6 +6,7 @@ import org.joml.Vector3f; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.tags.MdxAttrs; @@ -86,7 +87,7 @@ public void compile(GuidebookLevel level, CameraSettings camera, PageCompiler co float hlMaxX = parseFloat(compiler, errorSink, el, "hlMaxX", 1f); float hlMaxY = parseFloat(compiler, errorSink, el, "hlMaxY", 1f); float hlMaxZ = parseFloat(compiler, errorSink, el, "hlMaxZ", 1f); - int hlArgb = parseColor(compiler, errorSink, el, "highlightColor", 0x8000FFAA); + int hlArgb = parseColor(compiler, errorSink, el, "highlightColor", ColorUtils.HIGHLIGHT.getColor()); var box = new InWorldBoxAnnotation( new Vector3f(hlMinX, hlMinY, hlMinZ), new Vector3f(hlMaxX, hlMaxY, hlMaxZ), diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/level/GuidebookFakeWorld.java b/src/main/java/com/hfstudio/guidenh/guide/scene/level/GuidebookFakeWorld.java index 81b3f571..a6ba3a87 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/level/GuidebookFakeWorld.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/level/GuidebookFakeWorld.java @@ -1,9 +1,7 @@ package com.hfstudio.guidenh.guide.scene.level; import java.util.Collection; -import java.util.HashSet; import java.util.Iterator; -import java.util.Set; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; @@ -33,6 +31,8 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; /** * Lightweight client-only world wrapper backed by a {@link GuidebookLevel}. @@ -47,7 +47,7 @@ public class GuidebookFakeWorld extends WorldClient implements GuidebookPreviewW /** Stable read-only chunk views; renderer/CTM asks for the same coordinates repeatedly. */ private final Long2ObjectOpenHashMap chunkViews = new Long2ObjectOpenHashMap<>(); @Nullable - private Set markBlockForUpdateGuard; + private LongSet markBlockForUpdateGuard; public GuidebookFakeWorld(GuidebookLevel level) { super( @@ -251,7 +251,7 @@ public void markBlockForUpdate(int x, int y, int z) { return; } long guardKey = packBlockPos(x, y, z); - Set inProgress = getOrCreateMarkBlockForUpdateGuard(); + LongSet inProgress = getOrCreateMarkBlockForUpdateGuard(); if (!inProgress.add(guardKey)) { return; } @@ -403,9 +403,9 @@ private boolean suppressAe2StaleTileDescriptionRefresh(@Nullable TileEntity te) .suppressMarkBlockForUpdateDescriptionResync(te, level); } - private Set getOrCreateMarkBlockForUpdateGuard() { + private LongSet getOrCreateMarkBlockForUpdateGuard() { if (markBlockForUpdateGuard == null) { - markBlockForUpdateGuard = new HashSet<>(); + markBlockForUpdateGuard = new LongOpenHashSet(); } return markBlockForUpdateGuard; } diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/level/GuidebookLevel.java b/src/main/java/com/hfstudio/guidenh/guide/scene/level/GuidebookLevel.java index 3454ec54..d98e7756 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/level/GuidebookLevel.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/level/GuidebookLevel.java @@ -37,6 +37,10 @@ import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntIterator; +import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -52,9 +56,9 @@ public class GuidebookLevel implements IBlockAccess, GuidebookChunkSource { private int cachedChunkZ; private final Long2ObjectLinkedOpenHashMap tileEntities = new Long2ObjectLinkedOpenHashMap<>(); - private final LinkedHashMap entities = new LinkedHashMap<>(); - private final LinkedHashMap> sceneEntityIds = new LinkedHashMap<>(); - private final HashMap entitySceneIds = new HashMap<>(); + private final Int2ObjectLinkedOpenHashMap entities = new Int2ObjectLinkedOpenHashMap<>(); + private final LinkedHashMap sceneEntityIds = new LinkedHashMap<>(); + private final Int2ObjectOpenHashMap entitySceneIds = new Int2ObjectOpenHashMap<>(); private final HashMap firstLiveSceneEntityIds = new HashMap<>(); private final LinkedHashMap sceneEntityMountStates = new LinkedHashMap<>(); private final HashMap> sceneEntityMountChildren = new HashMap<>(); @@ -96,6 +100,7 @@ public class GuidebookLevel implements IBlockAccess, GuidebookChunkSource { private int maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE, maxZ = Integer.MIN_VALUE; private boolean boundsDirty = true; private boolean centerDirty = true; + private long spatialRevision = 1L; public GuidebookLevel() { synchronized (LIVE_LEVELS) { @@ -287,6 +292,7 @@ public void setTileEntity(int x, int y, int z, @Nullable TileEntity tileEntity) tileEntity.validate(); tileEntities.put(key, tileEntity); } + markSpatialDirty(); previewStateDirty = true; } @@ -294,6 +300,7 @@ public void restoreTileEntityFast(int x, int y, int z, @Nullable TileEntity tile long key = packPos(x, y, z); if (tileEntity == null) { tileEntities.remove(key); + markSpatialDirty(); previewStateDirty = true; return; } @@ -303,6 +310,7 @@ public void restoreTileEntityFast(int x, int y, int z, @Nullable TileEntity tile tileEntity.blockType = getBlock(x, y, z); tileEntity.blockMetadata = getBlockMetadata(x, y, z); tileEntities.put(key, tileEntity); + markSpatialDirty(); previewStateDirty = true; } @@ -328,6 +336,7 @@ public boolean setBlockMetadata(int x, int y, int z, int meta) { bindTileEntity(tileEntity, x, y, z, getOrCreateFakeWorld()); } + markSpatialDirty(); previewStateDirty = true; return true; } @@ -508,15 +517,15 @@ public int removeEntitiesBySceneEntityId(@Nullable String sceneEntityId) { if (normalizedSceneEntityId == null) { return 0; } - LinkedHashSet entityIds = sceneEntityIds.get(normalizedSceneEntityId); + IntLinkedOpenHashSet entityIds = sceneEntityIds.get(normalizedSceneEntityId); if (entityIds == null || entityIds.isEmpty()) { clearSceneEntityMountState(normalizedSceneEntityId); return 0; } int removedCount = 0; - Integer[] snapshot = entityIds.toArray(new Integer[0]); - for (Integer entityId : snapshot) { - if (entityId != null && removeEntityInternal(entityId, true)) { + int[] snapshot = entityIds.toIntArray(); + for (int entityId : snapshot) { + if (removeEntityInternal(entityId, true)) { removedCount++; } } @@ -546,13 +555,14 @@ public List getEntitiesBySceneEntityId(@Nullable String sceneEntityId) { if (normalizedSceneEntityId == null) { return List.of(); } - LinkedHashSet entityIds = sceneEntityIds.get(normalizedSceneEntityId); + IntLinkedOpenHashSet entityIds = sceneEntityIds.get(normalizedSceneEntityId); if (entityIds == null || entityIds.isEmpty()) { return List.of(); } List resolved = new ArrayList<>(entityIds.size()); - for (Integer entityId : entityIds) { - Entity entity = entityId != null ? entities.get(entityId) : null; + for (IntIterator iterator = entityIds.iterator(); iterator.hasNext();) { + int entityId = iterator.nextInt(); + Entity entity = entities.get(entityId); if (entity != null && !entity.isDead) { resolved.add(entity); } @@ -573,13 +583,14 @@ public Entity getFirstEntityBySceneEntityId(@Nullable String sceneEntityId) { return cached; } } - LinkedHashSet entityIds = sceneEntityIds.get(normalizedSceneEntityId); + IntLinkedOpenHashSet entityIds = sceneEntityIds.get(normalizedSceneEntityId); if (entityIds == null || entityIds.isEmpty()) { firstLiveSceneEntityIds.remove(normalizedSceneEntityId); return null; } - for (Integer entityId : entityIds) { - Entity entity = entityId != null ? entities.get(entityId) : null; + for (IntIterator iterator = entityIds.iterator(); iterator.hasNext();) { + int entityId = iterator.nextInt(); + Entity entity = entities.get(entityId); if (entity != null && !entity.isDead) { firstLiveSceneEntityIds.put(normalizedSceneEntityId, entity.getEntityId()); return entity; @@ -752,6 +763,14 @@ public float[] getCenter() { public void markSpatialDirty() { boundsDirty = true; centerDirty = true; + spatialRevision++; + if (spatialRevision == 0L) { + spatialRevision = 1L; + } + } + + public long getSpatialRevision() { + return spatialRevision; } public int getPrecipitationBlockingY(int x, int z, int minY, int maxY) { @@ -943,7 +962,7 @@ private void registerSceneEntityId(@Nullable String sceneEntityId, int entityId) if (normalizedSceneEntityId == null) { return; } - sceneEntityIds.computeIfAbsent(normalizedSceneEntityId, ignored -> new LinkedHashSet<>()) + sceneEntityIds.computeIfAbsent(normalizedSceneEntityId, ignored -> new IntLinkedOpenHashSet()) .add(entityId); entitySceneIds.put(entityId, normalizedSceneEntityId); firstLiveSceneEntityIds.putIfAbsent(normalizedSceneEntityId, entityId); @@ -957,7 +976,7 @@ private void registerSceneEntityId(@Nullable String sceneEntityId, int entityId) } private void unregisterSceneEntityId(String sceneEntityId, int entityId) { - LinkedHashSet entityIds = sceneEntityIds.get(sceneEntityId); + IntLinkedOpenHashSet entityIds = sceneEntityIds.get(sceneEntityId); if (entityIds == null) { return; } diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/ponder/PonderKeyframeParticle.java b/src/main/java/com/hfstudio/guidenh/guide/scene/ponder/PonderKeyframeParticle.java index c5af24e0..ea4158d8 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/ponder/PonderKeyframeParticle.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/ponder/PonderKeyframeParticle.java @@ -7,7 +7,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; -import com.hfstudio.guidenh.guide.color.Colors; +import com.hfstudio.guidenh.guide.color.ColorUtils; /** * A particle effect entry triggered when a Ponder keyframe becomes active during forward playback. @@ -20,7 +20,7 @@ public class PonderKeyframeParticle { public static final int MAX_WEATHER_DENSITY_PER_TICK = 64; public static final float MAX_POWER = 12f; public static final float MAX_SIZE = 4f; - public static final int DEFAULT_INDICATOR_COLOR = 0xFFFF0000; + public static final int DEFAULT_INDICATOR_COLOR = ColorUtils.ARGB_FFFF0000.getColor(); @Nullable private String preset; @@ -188,7 +188,7 @@ public int getIndicatorColor() { if (trimmed.startsWith("0x") || trimmed.startsWith("0X")) { trimmed = "#" + trimmed.substring(2); } - return Colors.hexToRgb(trimmed); + return ColorUtils.hexToRgb(trimmed); } @Nullable diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/snapshot/GuidebookPreviewAuthorityStore.java b/src/main/java/com/hfstudio/guidenh/guide/scene/snapshot/GuidebookPreviewAuthorityStore.java index 70d80477..20cdb23f 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/snapshot/GuidebookPreviewAuthorityStore.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/snapshot/GuidebookPreviewAuthorityStore.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongIterator; /** * Per-coordinate opaque supplement bytes keyed by {@link #supplementId()}, for server-authoritative preview data. @@ -95,7 +96,9 @@ public Map> snapshotAll() { return Map.of(); } HashMap> snapshot = new HashMap<>(); - for (Long packedPos : byPos.keySet()) { + for (LongIterator iterator = byPos.keySet() + .iterator(); iterator.hasNext();) { + long packedPos = iterator.nextLong(); snapshot.put(packedPos, snapshotAt(packedPos)); } return snapshot.isEmpty() ? Map.of() : snapshot; diff --git a/src/main/java/com/hfstudio/guidenh/guide/scene/support/GuidePreviewStateSupport.java b/src/main/java/com/hfstudio/guidenh/guide/scene/support/GuidePreviewStateSupport.java index 0cc8cd9b..cba375c1 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/scene/support/GuidePreviewStateSupport.java +++ b/src/main/java/com/hfstudio/guidenh/guide/scene/support/GuidePreviewStateSupport.java @@ -1,11 +1,12 @@ package com.hfstudio.guidenh.guide.scene.support; import com.hfstudio.guidenh.guide.scene.level.GuidebookLevel; +import com.hfstudio.guidenh.guide.scene.snapshot.PreviewPrepareContributor; import com.hfstudio.guidenh.guide.scene.snapshot.PreviewPreparePipeline; /** * Cross-mod entry point for preparing guide preview state. Actual logic lives in registered - * {@link com.hfstudio.guidenh.guide.scene.snapshot.PreviewPrepareContributor}s. + * {@link PreviewPrepareContributor}s. */ public class GuidePreviewStateSupport { diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteGraphRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteGraphRenderer.java index 4f49aa44..558ab836 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteGraphRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteGraphRenderer.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.document.block.MermaidNodeRenderer; import com.hfstudio.guidenh.guide.document.block.chart.CornerLegendPosition; @@ -175,16 +176,16 @@ public static String renderFileTree(String source) { private static final int MM_ACCENT_STRIPE = 3; private static final int MM_MIN_NODE_WIDTH = 64; - private static final int MM_BG_COLOR = 0xF00C1117; - private static final int MM_BORDER_COLOR = 0x66434C57; - private static final int MM_CONNECTOR_COLOR = 0xFF5D6C7C; - private static final int MM_ROOT_BG = 0xFF1F2A38; - private static final int MM_NODE_BG = 0xFF111922; - private static final int MM_ROOT_TEXT = 0xFFF1F6FB; - private static final int MM_NODE_TEXT = 0xFFD7DEE7; - private static final int MM_BADGE_TEXT = 0xFFB8C2CF; - private static final int MM_BADGE_BG = 0xFF262A33; - private static final int MM_DEFAULT_ACCENT = 0xFF7AA2F7; + private static final int MM_BG_COLOR = ColorUtils.ARGB_F00C1117.getColor(); + private static final int MM_BORDER_COLOR = ColorUtils.ARGB_66434C57.getColor(); + private static final int MM_CONNECTOR_COLOR = ColorUtils.ARGB_FF5D6C7C.getColor(); + private static final int MM_ROOT_BG = ColorUtils.ARGB_FF1F2A38.getColor(); + private static final int MM_NODE_BG = ColorUtils.ARGB_FF111922.getColor(); + private static final int MM_ROOT_TEXT = ColorUtils.ARGB_FFF1F6FB.getColor(); + private static final int MM_NODE_TEXT = ColorUtils.ARGB_FFD7DEE7.getColor(); + private static final int MM_BADGE_TEXT = ColorUtils.CHART_LABEL.getColor(); + private static final int MM_BADGE_BG = ColorUtils.ARGB_FF262A33.getColor(); + private static final int MM_DEFAULT_ACCENT = ColorUtils.ARGB_FF7AA2F7.getColor(); private static class MmLayoutNode { @@ -626,7 +627,7 @@ private static void renderFlowchartEdges(StringBuilder sb, FlowchartDocument doc .append(labelH) .append("\" rx=\"3\"") .append(" fill=\"") - .append(argbToRgba(0xCC0C1117)) + .append(argbToRgba(ColorUtils.ARGB_CC0C1117.getColor())) .append("\" stroke=\"rgba(180,180,200,0.3)\"") .append(" stroke-width=\"1\"/>\n"); sb.append("") .append(esc(badgeText)) .append("\n"); @@ -986,26 +991,26 @@ private static int resolveMmAccent(MmLayoutNode node) { if (lower.contains("danger") || lower.contains("error") || lower.contains("urgent") || lower.contains("red")) { - accent = 0xFFF7768E; + accent = ColorUtils.ARGB_FFF7768E.getColor(); break; } if (lower.contains("success") || lower.contains("green") || lower.contains("done")) { - accent = 0xFF9ECE6A; + accent = ColorUtils.ARGB_FF9ECE6A.getColor(); break; } if (lower.contains("warn") || lower.contains("yellow") || lower.contains("amber")) { - accent = 0xFFE0AF68; + accent = ColorUtils.ARGB_FFE0AF68.getColor(); break; } if (lower.contains("muted") || lower.contains("gray") || lower.contains("grey")) { - accent = 0xFF8B949E; + accent = ColorUtils.ARGB_FF8B949E.getColor(); } } return switch (node.source.getShape()) { - case CIRCLE -> 0xFF7DCFFF; - case HEXAGON -> 0xFFE0AF68; - case CLOUD -> 0xFF73DACA; - case BANG -> 0xFFF7768E; + case CIRCLE -> ColorUtils.ARGB_FF7DCFFF.getColor(); + case HEXAGON -> ColorUtils.ARGB_FFE0AF68.getColor(); + case CLOUD -> ColorUtils.ARGB_FF73DACA.getColor(); + case BANG -> ColorUtils.ARGB_FFF7768E.getColor(); default -> accent; }; } diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteHtmlCompiler.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteHtmlCompiler.java index e04872e4..a607db16 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteHtmlCompiler.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteHtmlCompiler.java @@ -13,8 +13,8 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.ParsedGuidePage; import com.hfstudio.guidenh.guide.compiler.tags.MdxAttrs; @@ -1570,7 +1570,7 @@ private String renderQuoteIcon(QuoteIconSpec icon, GuideSiteTemplateRegistry tem } private static String toCssColor(ColorValue color) { - int argb = color.resolve(LightDarkMode.LIGHT_MODE); + int argb = color.resolve(); int a = (argb >>> 24) & 0xFF; int r = (argb >>> 16) & 0xFF; int g = (argb >>> 8) & 0xFF; @@ -1607,7 +1607,7 @@ private String parseLatexCssColor(@Nullable String raw) { private int parseLatexColorArgb(@Nullable String raw) { if (raw == null || raw.trim() .isEmpty()) { - return 0xFFFFFFFF; + return ColorUtils.WHITE.getColor(); } String trimmed = raw.trim(); if (trimmed.startsWith("#")) { @@ -1615,13 +1615,13 @@ private int parseLatexColorArgb(@Nullable String raw) { } try { if (trimmed.length() == 6) { - return 0xFF000000 | Integer.parseUnsignedInt(trimmed, 16); + return ColorUtils.BLACK.getColor() | Integer.parseUnsignedInt(trimmed, 16); } if (trimmed.length() == 8) { return (int) Long.parseLong(trimmed, 16); } } catch (NumberFormatException ignored) {} - return 0xFFFFFFFF; + return ColorUtils.WHITE.getColor(); } private String escapeCssColor(String raw) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteItemIconExporter.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteItemIconExporter.java index d84ee5e7..03314ddd 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteItemIconExporter.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteItemIconExporter.java @@ -18,6 +18,7 @@ import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog; public class GuideSiteItemIconExporter implements GuideSiteItemIconResolver { @@ -119,7 +120,7 @@ private byte[] renderPng(ItemStack stack) throws Exception { GL11.glAlphaFunc(GL11.GL_GREATER, 0.1f); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); float scale = (ICON_SIZE - 2f) / 16f; float origin = (ICON_SIZE - 16f * scale) / 2f; @@ -169,7 +170,7 @@ private byte[] renderPng(ItemStack stack) throws Exception { GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteLatexExporter.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteLatexExporter.java index 662fd956..c58744c2 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteLatexExporter.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteLatexExporter.java @@ -16,6 +16,7 @@ import org.scilab.forge.jlatexmath.TeXFormula; import org.scilab.forge.jlatexmath.TeXIcon; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog; public class GuideSiteLatexExporter { @@ -76,7 +77,7 @@ private int referenceHeight(float sourceScale) throws ParseException { if (cached != null) { return cached; } - TeXIcon icon = createIcon(CALIBRATION_FORMULA, 0xFFFFFFFF, sourceScale); + TeXIcon icon = createIcon(CALIBRATION_FORMULA, ColorUtils.WHITE.getColor(), sourceScale); int height = Math.max(1, icon.getIconHeight()); referenceHeights.put(key, height); return height; @@ -105,7 +106,7 @@ private byte[] renderPng(TeXIcon icon) throws Exception { RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); graphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - graphics.setColor(new Color(0, 0, 0, 0)); + graphics.setColor(new Color(ColorUtils.TRANSPARENT.getColor(), true)); graphics.fillRect(0, 0, image.getWidth(), image.getHeight()); icon.paintIcon(null, graphics, 0, 0); } finally { diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteMdxTagRenderer.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteMdxTagRenderer.java index 184a84c9..f8233640 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteMdxTagRenderer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteMdxTagRenderer.java @@ -24,10 +24,9 @@ import com.hfstudio.guidenh.guide.Guide; import com.hfstudio.guidenh.guide.GuidePageIcon; import com.hfstudio.guidenh.guide.PageAnchor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; import com.hfstudio.guidenh.guide.color.ConstantColor; -import com.hfstudio.guidenh.guide.color.LightDarkMode; -import com.hfstudio.guidenh.guide.color.SymbolicColor; import com.hfstudio.guidenh.guide.color.SymbolicColorResolver; import com.hfstudio.guidenh.guide.compiler.FrontmatterNavigation; import com.hfstudio.guidenh.guide.compiler.GuideItemReferenceResolver; @@ -1733,8 +1732,8 @@ private String renderCsvTable(MdxJsxElementFields element, @Nullable ResourceLoc private String renderColumnChart(MdxJsxElementFields element) { int w = readInt(element, "width", 1280); int h = readInt(element, "height", 800); - int bgColor = parseArgbAttr(element, "background", 0xFF1B1F23); - int borderColor = parseArgbAttr(element, "border", 0xFF3A4047); + int bgColor = parseArgbAttr(element, "background", ColorUtils.CHART_BACKGROUND.getColor()); + int borderColor = parseArgbAttr(element, "border", ColorUtils.CHART_BORDER.getColor()); String title = readOptional(element, "title"); String[] categories = ChartAttrParser.parseStringArray(readOptional(element, "categories")); boolean showLegend = readBoolean(element, "showLegend", true); @@ -1759,8 +1758,8 @@ private String renderColumnChart(MdxJsxElementFields element) { private String renderBarChart(MdxJsxElementFields element) { int w = readInt(element, "width", 1280); int h = readInt(element, "height", 800); - int bgColor = parseArgbAttr(element, "background", 0xFF1B1F23); - int borderColor = parseArgbAttr(element, "border", 0xFF3A4047); + int bgColor = parseArgbAttr(element, "background", ColorUtils.CHART_BACKGROUND.getColor()); + int borderColor = parseArgbAttr(element, "border", ColorUtils.CHART_BORDER.getColor()); String title = readOptional(element, "title"); String[] categories = ChartAttrParser.parseStringArray(readOptional(element, "categories")); boolean showLegend = readBoolean(element, "showLegend", true); @@ -1771,8 +1770,8 @@ private String renderBarChart(MdxJsxElementFields element) { private String renderLineChart(MdxJsxElementFields element) { int w = readInt(element, "width", 1280); int h = readInt(element, "height", 800); - int bgColor = parseArgbAttr(element, "background", 0xFF1B1F23); - int borderColor = parseArgbAttr(element, "border", 0xFF3A4047); + int bgColor = parseArgbAttr(element, "background", ColorUtils.CHART_BACKGROUND.getColor()); + int borderColor = parseArgbAttr(element, "border", ColorUtils.CHART_BORDER.getColor()); String title = readOptional(element, "title"); String[] categories = ChartAttrParser.parseStringArray(readOptional(element, "categories")); boolean numericX = readBoolean(element, "numericX", false); @@ -1785,7 +1784,10 @@ private String renderLineChart(MdxJsxElementFields element) { .parseCornerLegendPosition(readOptional(element, "cornerLegend"), CornerLegendPosition.NONE); int cornerLegendWidth = readInt(element, "cornerLegendWidth", 120); int cornerLegendHeight = readInt(element, "cornerLegendHeight", 64); - int cornerLegendBackground = parseArgbAttr(element, "cornerLegendBackground", 0xAA111922); + int cornerLegendBackground = parseArgbAttr( + element, + "cornerLegendBackground", + ColorUtils.ARGB_AA111922.getColor()); List series = parseSeriesChildren(element); return GuideSiteGraphRenderer.renderLineChart( w, @@ -1807,8 +1809,8 @@ private String renderLineChart(MdxJsxElementFields element) { private String renderPieChart(MdxJsxElementFields element) { int w = readInt(element, "width", 1280); int h = readInt(element, "height", 800); - int bgColor = parseArgbAttr(element, "background", 0xFF1B1F23); - int borderColor = parseArgbAttr(element, "border", 0xFF3A4047); + int bgColor = parseArgbAttr(element, "background", ColorUtils.CHART_BACKGROUND.getColor()); + int borderColor = parseArgbAttr(element, "border", ColorUtils.CHART_BORDER.getColor()); String title = readOptional(element, "title"); boolean showLegend = readBoolean(element, "showLegend", true); List slices = parseSliceChildren(element); @@ -1818,15 +1820,18 @@ private String renderPieChart(MdxJsxElementFields element) { private String renderScatterChart(MdxJsxElementFields element) { int w = readInt(element, "width", 1280); int h = readInt(element, "height", 800); - int bgColor = parseArgbAttr(element, "background", 0xFF1B1F23); - int borderColor = parseArgbAttr(element, "border", 0xFF3A4047); + int bgColor = parseArgbAttr(element, "background", ColorUtils.CHART_BACKGROUND.getColor()); + int borderColor = parseArgbAttr(element, "border", ColorUtils.CHART_BORDER.getColor()); String title = readOptional(element, "title"); boolean showLegend = readBoolean(element, "showLegend", true); CornerLegendPosition cornerLegendPosition = ChartAttrParser .parseCornerLegendPosition(readOptional(element, "cornerLegend"), CornerLegendPosition.NONE); int cornerLegendWidth = readInt(element, "cornerLegendWidth", 120); int cornerLegendHeight = readInt(element, "cornerLegendHeight", 64); - int cornerLegendBackground = parseArgbAttr(element, "cornerLegendBackground", 0xAA111922); + int cornerLegendBackground = parseArgbAttr( + element, + "cornerLegendBackground", + ColorUtils.ARGB_AA111922.getColor()); List series = parseScatterSeriesChildren(element); return GuideSiteGraphRenderer.renderScatterChart( w, @@ -1847,10 +1852,10 @@ private String renderFunctionGraphTag(MdxJsxElementFields element, String defaul GuideSiteHtmlCompiler.SceneResolver sceneResolver, GuideSiteHtmlCompiler compiler) { int w = readInt(element, "width", 1280); int h = readInt(element, "height", 880); - int bgColor = parseArgbAttr(element, "background", 0xFF1B1F23); - int borderColor = parseArgbAttr(element, "border", 0xFF3A4047); - int axisColor = parseArgbAttr(element, "axisColor", 0xFFB8C2CF); - int gridColor = parseArgbAttr(element, "gridColor", 0x33B8C2CF); + int bgColor = parseArgbAttr(element, "background", ColorUtils.CHART_BACKGROUND.getColor()); + int borderColor = parseArgbAttr(element, "border", ColorUtils.CHART_BORDER.getColor()); + int axisColor = parseArgbAttr(element, "axisColor", ColorUtils.CHART_LABEL.getColor()); + int gridColor = parseArgbAttr(element, "gridColor", ColorUtils.CHART_GRID.getColor()); boolean showGrid = readBoolean(element, "showGrid", true); boolean showAxes = readBoolean(element, "showAxes", true); String title = readOptional(element, "title"); @@ -1860,7 +1865,10 @@ private String renderFunctionGraphTag(MdxJsxElementFields element, String defaul .parseCornerLegendPosition(readOptional(element, "cornerLegend"), CornerLegendPosition.NONE); int cornerLegendWidth = readInt(element, "cornerLegendWidth", 120); int cornerLegendHeight = readInt(element, "cornerLegendHeight", 64); - int cornerLegendBackground = parseArgbAttr(element, "cornerLegendBackground", 0xAA111922); + int cornerLegendBackground = parseArgbAttr( + element, + "cornerLegendBackground", + ColorUtils.ARGB_AA111922.getColor()); double xMin = parseDoubleAttr(element, "xMin", -10); double xMax = parseDoubleAttr(element, "xMax", 10); double yMin = parseDoubleAttr(element, "yMin", Double.NaN); @@ -2868,7 +2876,7 @@ private String resolveItemLabelKey(String defaultNamespace, @Nullable String raw private String resolveCssColor(MdxJsxElementFields element, String defaultNamespace) { String symbolicId = readOptional(element, "id"); if (symbolicId != null && !symbolicId.isEmpty()) { - ColorValue color = resolveSymbolicColor(symbolicId, defaultNamespace); + ColorValue color = resolveColorValue(symbolicId, defaultNamespace); return color != null ? toCssColor(color) : null; } @@ -2877,10 +2885,13 @@ private String resolveCssColor(MdxJsxElementFields element, String defaultNamesp } @Nullable - private ColorValue resolveSymbolicColor(String id, String defaultNamespace) { + private ColorValue resolveColorValue(String id, String defaultNamespace) { try { - return SymbolicColor.valueOf(id.toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException ignored) {} + ColorValue builtIn = ColorUtils.symbolic(id); + if (builtIn != null) { + return builtIn; + } + } catch (RuntimeException ignored) {} ResourceLocation colorId; try { @@ -2934,7 +2945,7 @@ private String parseLiteralColor(@Nullable String rawColor) { } private String toCssColor(ColorValue color) { - int argb = color.resolve(LightDarkMode.LIGHT_MODE); + int argb = color.resolve(); int alpha = argb >>> 24 & 0xFF; int red = argb >>> 16 & 0xFF; int green = argb >>> 8 & 0xFF; diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteNeiPhase1BackgroundExporter.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteNeiPhase1BackgroundExporter.java index 5576d508..7da79cfd 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteNeiPhase1BackgroundExporter.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteNeiPhase1BackgroundExporter.java @@ -16,7 +16,9 @@ import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.recipe.LytNeiRecipeBox; +import com.hfstudio.guidenh.guide.internal.recipe.NeiHandlerRenderer; import com.hfstudio.guidenh.guide.internal.recipe.NeiRecipeLayoutMetrics; import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog; import com.hfstudio.guidenh.integration.nei.NeiRecipeLookup; @@ -26,7 +28,7 @@ * Renders NEI handler Phase1 ({@code drawBackground} / optionally {@code drawForeground} / * {@code drawExtras}) off-screen and writes a PNG shared asset for static site overlays. * - * @see com.hfstudio.guidenh.guide.internal.recipe.NeiHandlerRenderer + * @see NeiHandlerRenderer */ public class GuideSiteNeiPhase1BackgroundExporter { @@ -163,7 +165,7 @@ private static byte[] renderPng(Object handler, int recipeIndex, int viewportW, GL11.glAlphaFunc(GL11.GL_GREATER, 0.1f); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glPushMatrix(); try { @@ -202,7 +204,7 @@ private static byte[] renderPng(Object handler, int recipeIndex, int viewportW, GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneAnnotationSerializer.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneAnnotationSerializer.java index a75bc6c5..3e9e28de 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneAnnotationSerializer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneAnnotationSerializer.java @@ -18,8 +18,8 @@ import com.google.gson.GsonBuilder; import com.hfstudio.guidenh.guide.GuideAnchor; import com.hfstudio.guidenh.guide.PageAnchor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ColorValue; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.document.block.LytBlock; import com.hfstudio.guidenh.guide.document.block.LytDocument; import com.hfstudio.guidenh.guide.document.block.LytHeading; @@ -410,7 +410,7 @@ private static List toVectors(List vectors) { } private static String toCssColor(@Nullable ColorValue color) { - int argb = color != null ? color.resolve(LightDarkMode.LIGHT_MODE) : 0xFFFFFFFF; + int argb = color != null ? color.resolve() : ColorUtils.WHITE.getColor(); int alpha = argb >>> 24 & 0xFF; int red = argb >>> 16 & 0xFF; int green = argb >>> 8 & 0xFF; diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneHoverTargetSerializer.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneHoverTargetSerializer.java index 5bf94e81..b4079059 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneHoverTargetSerializer.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneHoverTargetSerializer.java @@ -2,10 +2,8 @@ import java.util.ArrayList; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; import net.minecraft.block.Block; import net.minecraft.entity.Entity; @@ -31,6 +29,9 @@ import com.hfstudio.guidenh.guide.scene.support.GuideEntityDisplayResolver; import com.hfstudio.guidenh.integration.structurelib.StructureLibSceneMetadata; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; + public class GuideSiteSceneHoverTargetSerializer { private static final Gson GSON = new GsonBuilder().disableHtmlEscaping() @@ -65,11 +66,11 @@ public static String serialize(LytGuidebookScene scene, GuideSiteTemplateRegistr Map templateIdsByHtml = new LinkedHashMap<>(); Integer visibleLayerY = resolveVisibleLayerY(scene); List structureLibMetadataList = collectStructureLibMetadata(scene); - Set hatchPositions = new LinkedHashSet<>(); + LongSet hatchPositions = new LongOpenHashSet(); for (StructureLibSceneMetadata metadata : structureLibMetadataList) { hatchPositions.addAll(metadata.getHatchTooltipPositions()); } - Set exportedHatchPositions = new LinkedHashSet<>(); + LongSet exportedHatchPositions = new LongOpenHashSet(); for (int[] pos : level.getFilledBlocks()) { if (pos == null || pos.length < 3 || !isVisibleBlock(pos[1], visibleLayerY)) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneRuntimeExporter.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneRuntimeExporter.java index 41bed9ea..c903296a 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneRuntimeExporter.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneRuntimeExporter.java @@ -24,7 +24,7 @@ import org.lwjgl.opengl.GL11; import com.google.flatbuffers.FlatBufferBuilder; -import com.hfstudio.guidenh.guide.color.LightDarkMode; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.editor.io.SceneEditorOffscreenFramebuffer; import com.hfstudio.guidenh.guide.internal.resource.GuideResourceAccess; import com.hfstudio.guidenh.guide.scene.CameraSettings; @@ -117,8 +117,8 @@ private BufferedImage renderPlaceholderImage(LytGuidebookScene scene) throws Exc int renderHeight = logicalHeight * PLACEHOLDER_SCALE; try { - scene.setSceneBackgroundColor(0x00000000); - scene.setSceneBorderColor(0x00000000); + scene.setSceneBackgroundColor(ColorUtils.TRANSPARENT.getColor()); + scene.setSceneBorderColor(ColorUtils.TRANSPARENT.getColor()); scene.setSceneButtonsVisible(false); scene.setBottomControlsVisible(false); scene.setReserveBottomControlArea(false); @@ -216,7 +216,6 @@ private void captureSceneMeshes(LytGuidebookScene scene, int width, int height) height, 0.0f, List.of(), - LightDarkMode.LIGHT_MODE, layerSelection, scene.getRenderableParticlesForExport(), scene.getRenderableWeatherEffectsForExport(), diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneTessellatorCapture.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneTessellatorCapture.java index ead1a745..f628a686 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneTessellatorCapture.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/GuideSiteSceneTessellatorCapture.java @@ -24,6 +24,7 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.scene.support.GuideDebugLog; import guideme.flatbuffers.scene.ExpDepthTest; @@ -548,7 +549,7 @@ static int appendCapturedVertices(int[] rawBuffer, int vertexCount, boolean hasT cursor += Float.BYTES; } - int rgba = hasColor ? rawBuffer[base + 5] : 0xFFFFFFFF; + int rgba = hasColor ? rawBuffer[base + 5] : ColorUtils.WHITE.getColor(); target[cursor++] = (byte) (rgba & 255); target[cursor++] = (byte) (rgba >> 8 & 255); target[cursor++] = (byte) (rgba >> 16 & 255); diff --git a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/layout/SiteRecipeRawHandlerAccess.java b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/layout/SiteRecipeRawHandlerAccess.java index b7afd246..164bc3cb 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/layout/SiteRecipeRawHandlerAccess.java +++ b/src/main/java/com/hfstudio/guidenh/guide/siteexport/site/layout/SiteRecipeRawHandlerAccess.java @@ -4,11 +4,12 @@ import org.jetbrains.annotations.Nullable; +import com.hfstudio.guidenh.guide.siteexport.site.GuideSiteRecipeTagRenderer.HandlerRuntime; import com.hfstudio.guidenh.integration.nei.NeiRecipeLookup; /** * Narrow interface for reading NEI handler slots without depending on - * {@link com.hfstudio.guidenh.guide.siteexport.site.GuideSiteRecipeTagRenderer.HandlerRuntime}. + * {@link HandlerRuntime}. */ public interface SiteRecipeRawHandlerAccess { diff --git a/src/main/java/com/hfstudio/guidenh/integration/ae2/Ae2Helpers.java b/src/main/java/com/hfstudio/guidenh/integration/ae2/Ae2Helpers.java index c977c5f1..2faa9301 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/ae2/Ae2Helpers.java +++ b/src/main/java/com/hfstudio/guidenh/integration/ae2/Ae2Helpers.java @@ -59,7 +59,7 @@ /** * AE2 guide preview: applies server-authoritative AE2 preview bytes from {@link GuidebookLevel#previewAuthorityStore()} * ({@link Ae2ServerPreviewRegistration#SUPPLEMENT_ID} cable bus; {@link Ae2BaseTileNetworkStreamPreview#SUPPLEMENT_ID} - * other {@link AEBaseTile}), merged with locally inferred cable facings for the current preview layout. + * other {@link AEBaseTile}). Cable connection state comes from the exported stream whenever one is available. */ public class Ae2Helpers { @@ -172,7 +172,7 @@ public static void prepare(GuidebookLevel level) { } for (TileEntity te : level.getTileEntities()) { CableBusContainer container = resolveCableContainer(te); - if (container != null) { + if (container != null && !hasCableAuthoritySnapshot(container, level)) { container.updateConnections(); } } @@ -264,14 +264,16 @@ public static void syncCableBusConnections(CableBusContainer container, Guideboo Ae2CablePreviewSnapshot snap = raw != null ? Ae2CablePreviewWireCodec.decode(raw) : Ae2CablePreviewSnapshot.EMPTY; - int csDirections = computeCableConnectionMask(container, level); int csOut; int sideOut; if (snap.hasCableCore()) { - csOut = (snap.gridCsUnsigned() & ~CS_DIRECTION_MASK) | (csDirections & CS_DIRECTION_MASK); + // The exported cable stream is authoritative. A selected single cable may no longer + // have its original neighbours in the preview level, so recomputing these bits would + // erase valid connections that were present when the structure was captured. + csOut = snap.gridCsUnsigned(); sideOut = snap.sideOut(); } else { - csOut = csDirections; + csOut = computeCableConnectionMask(container, level); sideOut = 0; } @@ -338,6 +340,16 @@ public static void syncCableBusSidePartStreams(CableBusContainer container, Guid } } + @Optional.Method(modid = "appliedenergistics2") + private static boolean hasCableAuthoritySnapshot(CableBusContainer container, GuidebookLevel level) { + TileEntity tile = container.getTile(); + long posKey = GuidebookLevel.packPos(tile.xCoord, tile.yCoord, tile.zCoord); + byte[] raw = level.previewAuthorityStore() + .get(posKey, Ae2ServerPreviewRegistration.SUPPLEMENT_ID); + return raw != null && Ae2CablePreviewWireCodec.decode(raw) + .hasCableCore(); + } + @Optional.Method(modid = "appliedenergistics2") public static void appendCableBusStatStacks(@Nullable TileEntity tileEntity, List output) { if (!(tileEntity instanceof TileCableBus cableBusTile) || output == null) { diff --git a/src/main/java/com/hfstudio/guidenh/integration/betterquesting/compiler/QuestTagSupport.java b/src/main/java/com/hfstudio/guidenh/integration/betterquesting/compiler/QuestTagSupport.java index 07beb3d0..bca9abdc 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/betterquesting/compiler/QuestTagSupport.java +++ b/src/main/java/com/hfstudio/guidenh/integration/betterquesting/compiler/QuestTagSupport.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable; import com.hfstudio.guidenh.guide.PageAnchor; -import com.hfstudio.guidenh.guide.color.SymbolicColor; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.compiler.PageCompiler; import com.hfstudio.guidenh.guide.compiler.tags.MdxAttrs; import com.hfstudio.guidenh.guide.document.LytErrorSink; @@ -84,7 +84,7 @@ private static boolean shouldNavigateToGuidePage(PageCompiler compiler, PageAnch private static void applyQuestLinkStyle(LytFlowLink link, QuestDisplay display, String text, boolean showTooltip) { if (display.getState() == QuestState.COMPLETED) { - link.modifyStyle(style -> style.color(SymbolicColor.GREEN)); + link.modifyStyle(style -> style.color(ColorUtils.MC_GREEN)); } link.appendText(text); if (showTooltip) { diff --git a/src/main/java/com/hfstudio/guidenh/integration/nei/GuideScreenNeiNativeBridge.java b/src/main/java/com/hfstudio/guidenh/integration/nei/GuideScreenNeiNativeBridge.java index e58acf4b..a74f609c 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/nei/GuideScreenNeiNativeBridge.java +++ b/src/main/java/com/hfstudio/guidenh/integration/nei/GuideScreenNeiNativeBridge.java @@ -19,6 +19,7 @@ import org.lwjgl.opengl.GL12; import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.internal.GuideScreen; import com.hfstudio.guidenh.integration.Mods; import com.hfstudio.guidenh.integration.api.GuideNhIntegrationRegistry; @@ -286,7 +287,7 @@ public static void drawNativeNei(EditorAccess editorAccess, int mouseX, int mous GL11.glEnable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_DEPTH_TEST); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240.0F, 240.0F); - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); GL11.glTranslatef(editorAccess.containerLeft(), editorAccess.containerTop(), 0.0F); manager.renderObjects(mouseX, mouseY); } finally { @@ -295,7 +296,7 @@ public static void drawNativeNei(EditorAccess editorAccess, int mouseX, int mous GL11.glDisable(GL12.GL_RESCALE_NORMAL); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } return null; }); diff --git a/src/main/java/com/hfstudio/guidenh/integration/neicustomdiagram/NeiCustomDiagramBridge.java b/src/main/java/com/hfstudio/guidenh/integration/neicustomdiagram/NeiCustomDiagramBridge.java index 2166414e..a67a0e0a 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/neicustomdiagram/NeiCustomDiagramBridge.java +++ b/src/main/java/com/hfstudio/guidenh/integration/neicustomdiagram/NeiCustomDiagramBridge.java @@ -13,6 +13,7 @@ import org.lwjgl.opengl.GL11; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.interaction.GuideTooltip; import com.hfstudio.guidenh.guide.document.interaction.ItemTooltip; import com.hfstudio.guidenh.guide.document.interaction.TextTooltip; @@ -327,7 +328,7 @@ public static void renderEmbedded(Object handler, int recipeIndex, int renderX, applyAbsoluteGuiScissor(guiScissorAbsX, guiScissorAbsY, gw, gh); GL11.glEnable(GL11.GL_SCISSOR_TEST); GL11.glTranslatef(renderX, renderY, 0f); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); METHOD_DIAGRAM_DRAW_BACKGROUND.invoke(diagram, diagramState); renderForeground(diagram, diagramState, guiScissorAbsX, guiScissorAbsY, gw, gh); } catch (Throwable t) { @@ -340,7 +341,7 @@ public static void renderEmbedded(Object handler, int recipeIndex, int renderX, GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } @@ -490,7 +491,7 @@ private static void runPointConsumer(Object consumerObject, Object point) { private static void reapplyClipState(int absGuiX, int absGuiY, int absGuiW, int absGuiH) { applyAbsoluteGuiScissor(absGuiX, absGuiY, absGuiW, absGuiH); GL11.glEnable(GL11.GL_SCISSOR_TEST); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } private static GuideTooltip tooltipForInteractiveComponentGroup(Object hovered, Object diagramState) diff --git a/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibBuildService.java b/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibBuildService.java index 28599345..c8e5fd08 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibBuildService.java +++ b/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibBuildService.java @@ -43,12 +43,8 @@ public class StructureLibBuildService { public static final int SURVIVAL_BUDGET = Integer.MAX_VALUE; public static final int SURVIVAL_MAX_ROUNDS = 256; - // ========== DTO ========== - public record ResolvedController(String blockId, Block block, int meta) {} - // ========== Pipeline ========== - public StructureLibBuildResult build(StructureLibBuildRequest request) { try { return doBuild(request); @@ -96,8 +92,6 @@ private StructureLibBuildResult doBuild(StructureLibBuildRequest request) { return new StructureLibBuildResult(snapshotBlocks(level), true, null); } - // ========== Controller resolution ========== - public static ResolvedController resolveController(String controllerId) { GuideBlockMatcher matcher = GuideBlockMatcher.parse(controllerId); Block block = (Block) Block.blockRegistry.getObject(matcher.getBlockId()); @@ -107,8 +101,6 @@ public static ResolvedController resolveController(String controllerId) { return new ResolvedController(matcher.getBlockId(), block, matcher.getMeta() != null ? matcher.getMeta() : 0); } - // ========== Controller placement ========== - @Nullable public static TileEntity placeController(GuidebookLevel level, World world, ResolvedController controller) { for (StructureLibControllerPlacementIntegration integration : StructureLibControllerIntegrationRegistry.global() @@ -137,8 +129,6 @@ public static TileEntity placeController(GuidebookLevel level, World world, Reso return placed; } - // ========== Constructable resolution ========== - @Nullable public static IConstructable resolveConstructable(TileEntity controllerTile) { if (controllerTile instanceof IConstructableProvider provider) { @@ -159,8 +149,6 @@ public static IConstructable resolveConstructable(TileEntity controllerTile) { return null; } - // ========== Trigger stack ========== - public static ItemStack createTrigger(StructureLibBuildRequest request) { ItemStack stack = new ItemStack(StructureLibAPI.getDefaultHologramItem(), Math.max(MIN_TIER, request.tier())); for (Map.Entry entry : request.channels() @@ -177,8 +165,6 @@ public static ItemStack createTrigger(StructureLibBuildRequest request) { return stack; } - // ========== Structure construction ========== - private static void buildStructure(IConstructable constructable, ItemStack trigger, PreviewFakePlayer fakePlayer, StructureLibBuildRequest request, TileEntity controllerTile) { previewHook(controllerTile, trigger, true); @@ -225,8 +211,6 @@ private static IItemSource createItemSource() { return CreativeItemSource.instance; } - // ========== Preview state sync ========== - private static void syncPreviewState(TileEntity controllerTile, ItemStack trigger, StructureLibBuildRequest request) { for (StructureLibPreviewStateSynchronizer synchronizer : StructureLibControllerIntegrationRegistry.global() @@ -235,8 +219,6 @@ private static void syncPreviewState(TileEntity controllerTile, ItemStack trigge } } - // ========== Block snapshotting ========== - public static List snapshotBlocks(GuidebookLevel level) { List filledBlocks = new ArrayList<>(level.getFilledBlocks()); if (filledBlocks.isEmpty()) return List.of(); @@ -281,8 +263,6 @@ public static List snapshotBlocks(Guidebook return result; } - // ========== Utilities ========== - @Nullable public static NBTTagCompound serializeTile(@Nullable TileEntity tile) { if (tile == null) return null; diff --git a/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibSceneMetadata.java b/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibSceneMetadata.java index 77c0a273..c8f9c043 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibSceneMetadata.java +++ b/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibSceneMetadata.java @@ -54,8 +54,6 @@ private StructureLibSceneMetadata(String controller, @Nullable String piece, @Nu this.blockTooltipDataByPos = blockTooltipDataByPos != null ? blockTooltipDataByPos : Map.of(); } - // ========== Fluent factories (for programmatic construction) ========== - public StructureLibSceneMetadata withTierData(int minValue, int maxValue, int defaultValue, int currentValue) { return new StructureLibSceneMetadata( controller, @@ -83,8 +81,6 @@ public StructureLibSceneMetadata withChannelData(String channelId, String label, blockTooltipDataByPos); } - // ========== Tooltip data (deprecated — always empty) ========== - @Nullable public BlockTooltipData getBlockTooltipData(int x, int y, int z) { return null; @@ -102,8 +98,6 @@ public boolean hasHatchTooltipData() { return false; } - // ========== Getters ========== - @Nullable public TierData getTierData() { return tierData; @@ -142,8 +136,6 @@ public String getFlip() { return flip; } - // ========== Position encoding ========== - public static long packBlockPos(int x, int y, int z) { return (((long) x & 0x3FFFFFFL) << 38) | (((long) z & 0x3FFFFFFL) << 12) | ((long) y & 0xFFFL); } @@ -160,8 +152,6 @@ public static int unpackBlockPosZ(long packedPos) { return (int) (packedPos << 26 >> 38); } - // ========== Statics ========== - public static String requireController(@Nullable String controller) { if (controller == null) throw new IllegalArgumentException("StructureLib metadata controller cannot be null"); String trimmed = controller.trim(); @@ -197,8 +187,6 @@ public static int clamp(int value, int minValue, int maxValue) { return Math.min(value, maxValue); } - // ========== Inner types ========== - @Getter public static class BlockTooltipEntry { diff --git a/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibTooltipContentBuilder.java b/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibTooltipContentBuilder.java index ddda6ba6..555cc8b0 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibTooltipContentBuilder.java +++ b/src/main/java/com/hfstudio/guidenh/integration/structurelib/StructureLibTooltipContentBuilder.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable; import com.hfstudio.guidenh.config.ModConfig; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.color.ConstantColor; import com.hfstudio.guidenh.guide.document.block.LytParagraph; import com.hfstudio.guidenh.guide.document.block.LytSlotGrid; @@ -21,10 +22,13 @@ public class StructureLibTooltipContentBuilder { public static final int DEFAULT_CANDIDATE_COLUMNS = 6; public static final TextStyle HATCH_LABEL_STYLE = TextStyle.builder() - .color(new ConstantColor(0xFFFFCC55)) + .color(new ConstantColor(ColorUtils.ARGB_FFFFCC55.getColor())) .build(); - public static final int[] HINT_DOT_COLORS = new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFF00, 0xFFFF00FF, - 0xFF00FFFF, 0xFFFFA500, 0xFF800080, 0xFF006400, 0xFF8B0000, 0xFF00008B, 0xFF008B8B }; + public static final int[] HINT_DOT_COLORS = new int[] { ColorUtils.ARGB_FFFF0000.getColor(), + ColorUtils.ARGB_FF00FF00.getColor(), ColorUtils.ARGB_FF0000FF.getColor(), ColorUtils.ARGB_FFFFFF00.getColor(), + ColorUtils.ARGB_FFFF00FF.getColor(), ColorUtils.ARGB_FF00FFFF.getColor(), ColorUtils.ARGB_FFFFA500.getColor(), + ColorUtils.ARGB_FF800080.getColor(), ColorUtils.ARGB_FF006400.getColor(), ColorUtils.ARGB_FF8B0000.getColor(), + ColorUtils.ARGB_FF00008B.getColor(), ColorUtils.ARGB_FF008B8B.getColor() }; private StructureLibTooltipContentBuilder() {} @@ -151,7 +155,7 @@ public static int resolveHatchOverlayArgb(StructureLibSceneMetadata.BlockTooltip return (0x96 << 24) | (resolveHintDotColor(line.getHintDot()) & 0x00FFFFFF); } } - return 0x96D9B44A; + return ColorUtils.ARGB_96D9B44A.getColor(); } public static void appendCandidateGrid(LytVBox root, List candidates) { diff --git a/src/main/java/com/hfstudio/structurelibexport/StructureLibExportBackground.java b/src/main/java/com/hfstudio/structurelibexport/StructureLibExportBackground.java index 22e96134..841a8c36 100644 --- a/src/main/java/com/hfstudio/structurelibexport/StructureLibExportBackground.java +++ b/src/main/java/com/hfstudio/structurelibexport/StructureLibExportBackground.java @@ -4,12 +4,14 @@ import net.minecraft.command.CommandException; +import com.hfstudio.guidenh.guide.color.ColorUtils; + import lombok.Getter; @Getter public class StructureLibExportBackground { - public static final int DARK_ARGB = 0xFF121216; + public static final int DARK_ARGB = ColorUtils.ARGB_FF121216.getColor(); private final int argb; @@ -18,7 +20,7 @@ public StructureLibExportBackground(int argb) { } public static StructureLibExportBackground transparent() { - return new StructureLibExportBackground(0x00000000); + return new StructureLibExportBackground(ColorUtils.TRANSPARENT.getColor()); } public static StructureLibExportBackground parse(String raw) throws CommandException { diff --git a/src/main/java/com/hfstudio/structurelibexport/StructureLibExportLevelRenderer.java b/src/main/java/com/hfstudio/structurelibexport/StructureLibExportLevelRenderer.java index 7ead33d7..f9190575 100644 --- a/src/main/java/com/hfstudio/structurelibexport/StructureLibExportLevelRenderer.java +++ b/src/main/java/com/hfstudio/structurelibexport/StructureLibExportLevelRenderer.java @@ -2,7 +2,6 @@ import java.util.List; -import com.hfstudio.guidenh.guide.color.LightDarkMode; import com.hfstudio.guidenh.guide.scene.CameraSettings; import com.hfstudio.guidenh.guide.scene.GuidebookLevelRenderer; import com.hfstudio.guidenh.guide.scene.GuidebookSceneLayerSelection; @@ -42,7 +41,6 @@ public void renderExportTile(GuidebookLevel level, CameraSettings camera, Guideb tileHeight, 0f, annotations != null ? annotations : List.of(), - LightDarkMode.LIGHT_MODE, layers, List.of()); } diff --git a/src/main/java/com/hfstudio/structurelibexport/StructureLibExportOverlayRenderer.java b/src/main/java/com/hfstudio/structurelibexport/StructureLibExportOverlayRenderer.java index 1604520b..2df5026b 100644 --- a/src/main/java/com/hfstudio/structurelibexport/StructureLibExportOverlayRenderer.java +++ b/src/main/java/com/hfstudio/structurelibexport/StructureLibExportOverlayRenderer.java @@ -2,9 +2,7 @@ import java.util.List; -import org.lwjgl.opengl.GL11; - -import com.hfstudio.guidenh.guide.color.LightDarkMode; +import com.hfstudio.guidenh.guide.color.ColorUtils; import com.hfstudio.guidenh.guide.document.LytRect; import com.hfstudio.guidenh.guide.render.VanillaRenderContext; import com.hfstudio.guidenh.guide.scene.CameraSettings; @@ -18,10 +16,7 @@ public void render(CameraSettings camera, List overlays, int if (effectiveOverlays.isEmpty()) { return; } - VanillaRenderContext context = new VanillaRenderContext( - LightDarkMode.LIGHT_MODE, - new LytRect(0, 0, tileWidth, tileHeight), - tileHeight); + VanillaRenderContext context = new VanillaRenderContext(new LytRect(0, 0, tileWidth, tileHeight), tileHeight); context.setDocumentOrigin(0, 0); context.setScrollOffsetY(0); context.restoreExternalRenderState(); @@ -34,7 +29,7 @@ public void render(CameraSettings camera, List overlays, int } } finally { context.popScissor(); - GL11.glColor4f(1f, 1f, 1f, 1f); + ColorUtils.applyGlColor(ColorUtils.WHITE.getColor()); } } } diff --git a/src/main/resources/assets/guidenh/lang/en_US.lang b/src/main/resources/assets/guidenh/lang/en_US.lang index ef64c9c3..788b74ff 100644 --- a/src/main/resources/assets/guidenh/lang/en_US.lang +++ b/src/main/resources/assets/guidenh/lang/en_US.lang @@ -40,12 +40,6 @@ guideme.gui.config.debug.showmemory=Show Memory Usage guideme.gui.config.debug.showmemory.tooltip=Display memory usage statistics in the debug overlay. guideme.gui.config.debug.showmouseposition=Show Mouse Position guideme.gui.config.debug.showmouseposition.tooltip=Display current mouse coordinates in the debug overlay. -guideme.gui.config.debug.debugtextcolor=Debug Text Color -guideme.gui.config.debug.debugtextcolor.tooltip=ARGB color value for debug text overlay. -guideme.gui.config.debug.debugoutlinecolor=Debug Outline Color -guideme.gui.config.debug.debugoutlinecolor.tooltip=ARGB color value for element outlines (0 to mirror text color). -guideme.gui.config.debug.debugcursorcolor=Debug Cursor Color -guideme.gui.config.debug.debugcursorcolor.tooltip=ARGB color value for the cursor dot indicator. guideme.gui.config.debug.debugtextscale=Debug Text Scale guideme.gui.config.debug.debugtextscale.tooltip=Scale factor for debug text rendering. guideme.gui.config.debug.debugoutlinethickness=Debug Outline Thickness @@ -107,6 +101,8 @@ guideme.gui.config.ui.sceneblockstatsvisible=Show 3D Preview Block Stats guideme.gui.config.ui.sceneblockstatsvisible.tooltip=Controls whether 3D previews show the block statistics overlay by default. guideme.gui.config.ui.sceneeditorautopickenabled=Scene Editor Auto-Pick guideme.gui.config.ui.sceneeditorautopickenabled.tooltip=Controls whether auto-pick starts enabled in the scene editor and saves immediately after toggling. +guideme.gui.config.ui.sceneeditorexportopenfolderafterexport=Open Structure Folder After SNBT Export +guideme.gui.config.ui.sceneeditorexportopenfolderafterexport.tooltip=Controls whether the scene editor opens the exported structure folder after a successful SNBT export. guideme.gui.config.ui.sceneeditormarkdownpanelwidth=Scene Editor Markdown Panel Width guideme.gui.config.ui.sceneeditormarkdownpanelwidth.tooltip=Controls the expanded width of the markdown panel in the scene editor. guideme.gui.config.ui.sceneeditormarkdownwrapenabled=Guide and Scene Editor Word Wrap @@ -462,6 +458,7 @@ guideme.guidebook.SceneEditorElementTooltipEmpty=Empty guideme.guidebook.SceneEditorElementsPanel=Element List guideme.guidebook.SceneEditorExport=Export guideme.guidebook.SceneEditorExportSnbt=Export SNBT +guideme.guidebook.SceneEditorExportSnbtOpenFolder=Open Structure Folder After SNBT Export guideme.guidebook.SceneEditorCopyGameScene=Copy GameScene guideme.guidebook.SceneEditorCopyBlockImage=Copy BlockImage guideme.guidebook.SceneEditorHideElement=Hide Element diff --git a/src/main/resources/assets/guidenh/lang/zh_CN.lang b/src/main/resources/assets/guidenh/lang/zh_CN.lang index ee0e384d..56246566 100644 --- a/src/main/resources/assets/guidenh/lang/zh_CN.lang +++ b/src/main/resources/assets/guidenh/lang/zh_CN.lang @@ -40,12 +40,6 @@ guideme.gui.config.debug.showmemory=显示内存使用 guideme.gui.config.debug.showmemory.tooltip=在调试覆盖层显示内存使用统计。 guideme.gui.config.debug.showmouseposition=显示鼠标位置 guideme.gui.config.debug.showmouseposition.tooltip=在调试覆盖层显示当前鼠标坐标。 -guideme.gui.config.debug.debugtextcolor=调试文本颜色 -guideme.gui.config.debug.debugtextcolor.tooltip=调试文本覆盖层的 ARGB 颜色值。 -guideme.gui.config.debug.debugoutlinecolor=调试轮廓颜色 -guideme.gui.config.debug.debugoutlinecolor.tooltip=元素轮廓的 ARGB 颜色值(0 表示镜像文本颜色)。 -guideme.gui.config.debug.debugcursorcolor=调试光标颜色 -guideme.gui.config.debug.debugcursorcolor.tooltip=光标点指示器的 ARGB 颜色值。 guideme.gui.config.debug.debugtextscale=调试文本缩放 guideme.gui.config.debug.debugtextscale.tooltip=调试文本渲染的缩放因子。 guideme.gui.config.debug.debugoutlinethickness=调试轮廓厚度 @@ -107,6 +101,8 @@ guideme.gui.config.ui.sceneblockstatsvisible=显示 3D 预览方块统计 guideme.gui.config.ui.sceneblockstatsvisible.tooltip=控制 3D 预览是否默认显示方块统计叠加框。 guideme.gui.config.ui.sceneeditorautopickenabled=场景编辑器自动选择 guideme.gui.config.ui.sceneeditorautopickenabled.tooltip=控制场景编辑器中的自动选择开关默认是否开启,并在切换后立刻保存。 +guideme.gui.config.ui.sceneeditorexportopenfolderafterexport=导出 SNBT 后打开结构文件夹 +guideme.gui.config.ui.sceneeditorexportopenfolderafterexport.tooltip=控制场景编辑器成功导出 SNBT 后是否自动打开结构文件夹。 guideme.gui.config.ui.sceneeditormarkdownpanelwidth=场景编辑器 Markdown 面板宽度 guideme.gui.config.ui.sceneeditormarkdownpanelwidth.tooltip=控制场景编辑器中 Markdown 面板展开时的宽度。 guideme.gui.config.ui.sceneeditormarkdownwrapenabled=指南与场景编辑器自动换行 @@ -462,6 +458,7 @@ guideme.guidebook.SceneEditorElementTooltipEmpty=空 guideme.guidebook.SceneEditorElementsPanel=元素列表 guideme.guidebook.SceneEditorExport=导出 guideme.guidebook.SceneEditorExportSnbt=导出 SNBT +guideme.guidebook.SceneEditorExportSnbtOpenFolder=导出 SNBT 后打开结构文件夹 guideme.guidebook.SceneEditorCopyGameScene=复制 GameScene guideme.guidebook.SceneEditorCopyBlockImage=复制 BlockImage guideme.guidebook.SceneEditorHideElement=隐藏元素