extends SceneTree const ACCENT = Color("ff7b00") const SECONDARY = Color("402e32") const CLEAR = Color.TRANSPARENT const HIGH_CONTRAST = { "text": Color("f5f1ed"), "muted_text": Color("b9b0b3"), "active_text": Color("141114"), "surface": Color("201b1f"), "panel": Color("201b1f"), "input": Color("141114"), "hover": SECONDARY, "pressed": ACCENT, "fill": ACCENT, "disabled": Color("191619"), "border": Color("817278"), "disabled_border": Color("51464c"), "focus": ACCENT, "separator": SECONDARY, "thumb": Color("b9b0b3"), "fill_text": Color("141114"), } const SOFT = { "text": Color("e7e0dd"), "muted_text": Color("ada2a8"), "active_text": Color("f5f1ed"), "surface": Color("292126"), "panel": Color("201b1f"), "input": Color("141114"), "hover": SECONDARY, "pressed": SECONDARY, "fill": ACCENT, "disabled": Color("211c20"), "border": CLEAR, "disabled_border": CLEAR, "focus": ACCENT, "separator": SECONDARY, "thumb": Color("d2c6c9"), "fill_text": Color("141114"), } func _initialize() -> void: for high_contrast in [false, true]: var palette: Dictionary = HIGH_CONTRAST if high_contrast else SOFT var path := "res://themes/theme_highcontrast.tres" if high_contrast else "res://themes/theme.tres" var error := ResourceSaver.save(_build_theme(palette, high_contrast), path) if error != OK: push_error("Could not save %s: %s" % [path, error_string(error)]) quit(error) return quit() func _build_theme(palette: Dictionary, high_contrast: bool) -> Theme: var theme := ThemeDB.get_default_theme().duplicate(true) as Theme theme.default_font_size = 18 for type in theme.get_type_list(): for name in theme.get_font_size_list(type): theme.set_font_size(name, type, 18) for type in theme.get_type_list(): for name in theme.get_color_list(type): var color: Color = palette.text if "disabled" in name or "placeholder" in name or "readonly" in name: color = palette.muted_text elif "selection" in name: color = SECONDARY elif name in ["font_pressed_color", "font_hover_pressed_color"] and type in ["Button", "OptionButton", "MenuButton"]: color = palette.active_text elif name == "font_selected_color" and type == "TabContainer": color = palette.active_text elif name == "font_color" and type == "ProgressBar": color = palette.fill_text elif "background" in name: color = CLEAR elif "caret" in name or "accent" in name: color = ACCENT elif "shadow" in name or "outline" in name: color = CLEAR theme.set_color(name, type, color) for name in theme.get_stylebox_list(type): var original := theme.get_stylebox(name, type) if original is StyleBoxEmpty: continue var style := StyleBoxFlat.new() for side in range(4): style.set_content_margin(side, maxf(original.get_content_margin(side), 4.0)) style.bg_color = palette.surface style.border_color = palette.border style.set_border_width_all(1 if high_contrast else 0) if "hover" in name: style.bg_color = palette.hover style.border_color = palette.focus if "pressed" in name or ("selected" in name and "unselected" not in name) or name == "fill" or name.begins_with("grabber"): style.bg_color = palette.pressed if not high_contrast: style.border_width_bottom = 1 style.border_color = palette.focus if name == "fill" or name.begins_with("grabber"): style.bg_color = palette.fill if not high_contrast: style.set_border_width_all(0) if "disabled" in name or "read_only" in name: style.bg_color = palette.disabled style.border_color = palette.disabled_border if "focus" in name: style.draw_center = false style.border_color = palette.focus style.set_border_width_all(2 if high_contrast else 1) if type in ["LineEdit", "TextEdit", "CodeEdit", "Tree", "ItemList"] and name == "normal": style.bg_color = palette.input if type in ["Panel", "PanelContainer", "PopupPanel", "PopupMenu", "Window", "AcceptDialog"]: style.bg_color = palette.panel if type in ["HSeparator", "VSeparator"]: style.bg_color = palette.separator style.border_color = palette.separator theme.set_stylebox(name, type, style) # Slider thumbs use square textures instead of the engine's round icons. for type in ["HSlider", "VSlider"]: for name in ["grabber", "grabber_highlight", "grabber_disabled"]: var bitmap := Image.create(14, 18, false, Image.FORMAT_RGBA8) bitmap.fill(ACCENT if name == "grabber_highlight" else palette.thumb) theme.set_icon(name, type, ImageTexture.create_from_image(bitmap)) # Dedicated panel states used by the keyboard focus containers. var panel := theme.get_stylebox("panel", "PanelContainer").duplicate() as StyleBoxFlat theme.set_stylebox("panel_inactive", "SurfaceSide", panel) var active := panel.duplicate() as StyleBoxFlat active.border_color = palette.focus active.set_border_width_all(2 if high_contrast else 0) if not high_contrast: active.border_width_top = 2 theme.set_stylebox("panel_active", "SurfaceSide", active) theme.set_color("accent", "SurfaceSide", ACCENT) theme.set_color("secondary", "SurfaceSide", SECONDARY) return theme