391 lines
11 KiB
C#
391 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Diagnostics;
|
|
|
|
using Barotrauma;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using HarmonyLib;
|
|
using System.IO;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
|
|
namespace QICrabUI
|
|
{
|
|
public enum PaletteOrder
|
|
{
|
|
Primary, Secondary, Tertiary, Quaternary
|
|
}
|
|
public record PaletteExtractResult(bool Ok, string Value = null);
|
|
/// <summary>
|
|
/// Contains abstract values that could be referenced in Styles
|
|
/// </summary>
|
|
public class CUIPalette
|
|
{
|
|
internal static void InitStatic()
|
|
{
|
|
CUI.OnInit += () =>
|
|
{
|
|
Initialize();
|
|
};
|
|
CUI.OnDispose += () =>
|
|
{
|
|
LoadedPalettes.Clear();
|
|
};
|
|
}
|
|
|
|
public override string ToString() => $"CUIPalette {Name}";
|
|
public static string PaletteSetsPath => Path.Combine(CUI.PalettesPath, "Sets");
|
|
public static string DefaultPalette = "Blue";
|
|
|
|
|
|
//TODO why is it here? how could sane person find these?
|
|
public static bool NotifyExcessivePropStyles { get; set; } = false;
|
|
public static bool NotifiMissingPropStyles { get; set; } = true;
|
|
|
|
public static PaletteExtractResult Extract(string nestedName, PaletteOrder order)
|
|
{
|
|
CUIPalette palette = order switch
|
|
{
|
|
PaletteOrder.Primary => Primary,
|
|
PaletteOrder.Secondary => Secondary,
|
|
PaletteOrder.Tertiary => Tertiary,
|
|
PaletteOrder.Quaternary => Quaternary,
|
|
_ => Empty,
|
|
};
|
|
if (!palette.Values.ContainsKey(nestedName)) return new PaletteExtractResult(false);
|
|
return new PaletteExtractResult(true, palette.Values[nestedName]);
|
|
}
|
|
|
|
public static CUIPalette Empty => new CUIPalette();
|
|
|
|
public static Dictionary<string, CUIPalette> LoadedPalettes = new();
|
|
public static string Default = "Blue";
|
|
|
|
private static CUIPalette primary = new CUIPalette();
|
|
public static CUIPalette Primary
|
|
{
|
|
get => primary;
|
|
set
|
|
{
|
|
if (value == null) return;
|
|
primary = value;
|
|
CUIGlobalStyleResolver.OnPaletteChange(primary);
|
|
}
|
|
}
|
|
|
|
private static CUIPalette secondary = new CUIPalette();
|
|
public static CUIPalette Secondary
|
|
{
|
|
get => secondary;
|
|
set
|
|
{
|
|
if (value == null) return;
|
|
secondary = value;
|
|
CUIGlobalStyleResolver.OnPaletteChange(secondary);
|
|
}
|
|
}
|
|
|
|
private static CUIPalette tertiary = new CUIPalette();
|
|
public static CUIPalette Tertiary
|
|
{
|
|
get => tertiary;
|
|
set
|
|
{
|
|
if (value == null) return;
|
|
tertiary = value;
|
|
CUIGlobalStyleResolver.OnPaletteChange(tertiary);
|
|
}
|
|
}
|
|
|
|
private static CUIPalette quaternary = new CUIPalette();
|
|
public static CUIPalette Quaternary
|
|
{
|
|
get => quaternary;
|
|
set
|
|
{
|
|
if (value == null) return;
|
|
quaternary = value;
|
|
CUIGlobalStyleResolver.OnPaletteChange(quaternary);
|
|
}
|
|
}
|
|
|
|
|
|
public Dictionary<string, string> Values = new();
|
|
public string Name = "???";
|
|
public string BaseColor { get; set; } = "";
|
|
|
|
|
|
|
|
public static void Initialize()
|
|
{
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
if (CUI.PalettesPath == null) return;
|
|
|
|
LoadedPalettes.Clear();
|
|
|
|
LoadPalettes();
|
|
|
|
LoadSet(Path.Combine(PaletteSetsPath, DefaultPalette + ".xml"));
|
|
// Primary = LoadedPalettes.GetValueOrDefault("red");
|
|
// Secondary = LoadedPalettes.GetValueOrDefault("purple");
|
|
// Tertiary = LoadedPalettes.GetValueOrDefault("blue");
|
|
// Quaternary = LoadedPalettes.GetValueOrDefault("cyan");
|
|
|
|
CUIDebug.Log($"CUIPalette.Initialize took {sw.ElapsedMilliseconds}ms");
|
|
}
|
|
|
|
public static void LoadPalettes()
|
|
{
|
|
foreach (string file in Directory.GetFiles(CUI.PalettesPath, "*.xml"))
|
|
{
|
|
CUIPalette palette = LoadFrom(file);
|
|
LoadedPalettes[palette.Name] = palette;
|
|
}
|
|
}
|
|
|
|
public static CUIPalette FromXML(XElement root)
|
|
{
|
|
CUIPalette palette = new CUIPalette();
|
|
|
|
palette.Name = root.Attribute("Name")?.Value.ToString();
|
|
|
|
foreach (XElement element in root.Elements())
|
|
{
|
|
foreach (XAttribute attribute in element.Attributes())
|
|
{
|
|
palette.Values[$"{element.Name}.{attribute.Name}"] = attribute.Value;
|
|
}
|
|
|
|
if (element.Value != "")
|
|
{
|
|
palette.Values[$"{element.Name}"] = element.Value;
|
|
}
|
|
}
|
|
|
|
return palette;
|
|
}
|
|
|
|
public static CUIPalette LoadFrom(string path)
|
|
{
|
|
CUIPalette palette = new CUIPalette();
|
|
try
|
|
{
|
|
XDocument xdoc = XDocument.Load(path);
|
|
XElement root = xdoc.Root;
|
|
|
|
palette = CUIPalette.FromXML(root);
|
|
palette.Name ??= Path.GetFileNameWithoutExtension(path);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
CUI.Warning($"Failed to load palette from {path}");
|
|
CUI.Warning(e);
|
|
}
|
|
|
|
return palette;
|
|
}
|
|
|
|
|
|
public XElement ToXML()
|
|
{
|
|
XElement root = new XElement("Palette");
|
|
root.Add(new XAttribute("Name", Name));
|
|
root.Add(new XAttribute("BaseColor", BaseColor));
|
|
|
|
foreach (string key in Values.Keys)
|
|
{
|
|
string component = key.Split('.').ElementAtOrDefault(0);
|
|
string prop = key.Split('.').ElementAtOrDefault(1);
|
|
|
|
if (component == null) continue;
|
|
|
|
if (root.Element(component) == null) root.Add(new XElement(component));
|
|
|
|
if (prop != null)
|
|
{
|
|
root.Element(component).Add(new XAttribute(prop, Values[key]));
|
|
}
|
|
else
|
|
{
|
|
root.Element(component).Value = Values[key];
|
|
}
|
|
}
|
|
return root;
|
|
}
|
|
public void SaveTo(string path)
|
|
{
|
|
try
|
|
{
|
|
XDocument xdoc = new XDocument();
|
|
xdoc.Add(this.ToXML());
|
|
xdoc.Save(path);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
CUI.Warning($"Failed to save palette to {path}");
|
|
CUI.Warning(e);
|
|
}
|
|
}
|
|
|
|
|
|
public static void PaletteDemo()
|
|
{
|
|
if (CUI.AssetsPath == null)
|
|
{
|
|
CUI.Warning($"Can't load PaletteDemo, CUI.AssetsPath is null");
|
|
return;
|
|
}
|
|
|
|
void loadFrame(Vector2 offset, PaletteOrder order)
|
|
{
|
|
CUIFrame frame = CUIComponent.LoadFromFile<CUIFrame>(Path.Combine(CUI.AssetsPath, $"PaletteDemo.xml"));
|
|
frame.DeepPalette = order;
|
|
frame.Absolute = frame.Absolute with { Position = offset };
|
|
frame.AddCommand("Close", (o) => frame.RemoveSelf());
|
|
CUI.TopMain.Append(frame);
|
|
}
|
|
|
|
loadFrame(new Vector2(0, 0), PaletteOrder.Primary);
|
|
loadFrame(new Vector2(180, 0), PaletteOrder.Secondary);
|
|
loadFrame(new Vector2(360, 0), PaletteOrder.Tertiary);
|
|
loadFrame(new Vector2(540, 0), PaletteOrder.Quaternary);
|
|
}
|
|
|
|
|
|
|
|
|
|
public static CUIPalette CreatePaletteFromColors(string name, Color colorA, Color? colorb = null)
|
|
{
|
|
CUIPalette palette = new CUIPalette()
|
|
{
|
|
Name = name,
|
|
BaseColor = CUIExtensions.ColorToString(colorA),
|
|
};
|
|
|
|
Color colorB = colorb ?? Color.Black;
|
|
|
|
Dictionary<string, Color> colors = new();
|
|
|
|
colors["Frame.Background"] = colorA.To(colorB, 1.0f);
|
|
colors["Header.Background"] = colorA.To(colorB, 0.7f);
|
|
colors["Nav.Background"] = colorA.To(colorB, 0.8f);
|
|
colors["Main.Background"] = colorA.To(colorB, 0.9f);
|
|
|
|
colors["Frame.Border"] = colorA.To(colorB, 0.5f);
|
|
colors["Header.Border"] = colorA.To(colorB, 0.6f);
|
|
colors["Nav.Border"] = colorA.To(colorB, 0.7f);
|
|
colors["Main.Border"] = colorA.To(colorB, 0.8f);
|
|
|
|
colors["Frame.Text"] = colorA.To(Color.White, 0.9f);
|
|
colors["Header.Text"] = colorA.To(Color.White, 0.9f);
|
|
colors["Nav.Text"] = colorA.To(Color.White, 0.8f);
|
|
colors["Main.Text"] = colorA.To(Color.White, 0.8f);
|
|
|
|
colors["Component.Background"] = Color.Transparent;
|
|
colors["Component.Border"] = Color.Transparent;
|
|
colors["Component.Text"] = colors["Main.Text"];
|
|
colors["Button.Background"] = colorA.To(colorB, 0.0f);
|
|
colors["Button.Border"] = colorA.To(colorB, 0.5f);
|
|
colors["Button.Disabled"] = colorA.To(new Color(16, 16, 16), 0.8f);
|
|
colors["CloseButton.Background"] = colorA.To(Color.White, 0.2f);
|
|
colors["DDOption.Background"] = colors["Header.Background"];
|
|
colors["DDOption.Border"] = colors["Main.Border"];
|
|
colors["DDOption.Hover"] = colorA.To(colorB, 0.5f);
|
|
colors["DDOption.Text"] = colors["Main.Text"];
|
|
colors["Handle.Background"] = colorA.To(colorB, 0.5f).To(Color.White, 0.2f);
|
|
colors["Handle.Grabbed"] = colorA.To(colorB, 0.0f).To(Color.White, 0.2f);
|
|
colors["Slider"] = colorA.To(Color.White, 0.7f);
|
|
colors["Input.Background"] = colors["Nav.Background"];
|
|
colors["Input.Border"] = colors["Nav.Border"];
|
|
colors["Input.Text"] = colors["Main.Text"];
|
|
colors["Input.Focused"] = colorA;
|
|
colors["Input.Invalid"] = Color.Red;
|
|
colors["Input.Valid"] = Color.Lime;
|
|
colors["Input.Selection"] = colorA.To(Color.White, 0.7f) * 0.5f;
|
|
colors["Input.Caret"] = colorA.To(Color.White, 0.7f) * 0.5f;
|
|
|
|
foreach (var (key, cl) in colors)
|
|
{
|
|
palette.Values[key] = CUIExtensions.ColorToString(cl);
|
|
}
|
|
|
|
palette.SaveTo(Path.Combine(CUI.PalettesPath, $"{name}.xml"));
|
|
LoadedPalettes[name] = palette;
|
|
CUI.Log($"Created {name} palette and saved it to {Path.Combine(CUI.PalettesPath, $"{name}.xml")}");
|
|
|
|
return palette;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Packs 4 palettes into 1 set
|
|
/// </summary>
|
|
/// <param name="setName"></param>
|
|
/// <param name="primary"></param>
|
|
/// <param name="secondary"></param>
|
|
/// <param name="tertiary"></param>
|
|
/// <param name="quaternary"></param>
|
|
public static void SaveSet(string setName, string primary = "", string secondary = "", string tertiary = "", string quaternary = "")
|
|
{
|
|
if (setName == null || setName == "") return;
|
|
|
|
string savePath = Path.Combine(PaletteSetsPath, $"{setName}.xml");
|
|
|
|
try
|
|
{
|
|
XDocument xdoc = new XDocument(new XElement("PaletteSet"));
|
|
XElement root = xdoc.Root;
|
|
|
|
root.Add(new XAttribute("Name", setName));
|
|
|
|
root.Add((LoadedPalettes.GetValueOrDefault(primary ?? "") ?? Primary).ToXML());
|
|
root.Add((LoadedPalettes.GetValueOrDefault(secondary ?? "") ?? Secondary).ToXML());
|
|
root.Add((LoadedPalettes.GetValueOrDefault(tertiary ?? "") ?? Tertiary).ToXML());
|
|
root.Add((LoadedPalettes.GetValueOrDefault(quaternary ?? "") ?? Quaternary).ToXML());
|
|
|
|
xdoc.Save(savePath);
|
|
|
|
CUI.Log($"Created {setName} palette set and saved it to {savePath}");
|
|
LoadSet(savePath);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
CUI.Warning($"Failed to save palette set to {savePath}");
|
|
CUI.Warning(e);
|
|
}
|
|
}
|
|
|
|
public static void LoadSet(string path)
|
|
{
|
|
if (path == null || path == "") return;
|
|
try
|
|
{
|
|
XDocument xdoc = XDocument.Load(path);
|
|
XElement root = xdoc.Root;
|
|
|
|
List<CUIPalette> palettes = new();
|
|
|
|
foreach (XElement element in root.Elements("Palette"))
|
|
{
|
|
palettes.Add(CUIPalette.FromXML(element));
|
|
}
|
|
|
|
Primary = palettes.ElementAtOrDefault(0) ?? Empty;
|
|
Secondary = palettes.ElementAtOrDefault(1) ?? Empty;
|
|
Tertiary = palettes.ElementAtOrDefault(2) ?? Empty;
|
|
Quaternary = palettes.ElementAtOrDefault(3) ?? Empty;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
CUI.Warning($"Failed to load palette set from {path}");
|
|
CUI.Warning(e);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
} |