Files
barotrauma-localmods/Quick Interactions/CSharp/Client/CrabUI/Global/CUIPalette.cs

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);
}
}
}
}