Files
Continentis/Assets/OtherPlugins/PixelFantasy/Common/Scripts/EditorScripts/CharacterEditor.cs
SoulliesOfficial 61a397dd4c MOD!
2025-10-23 00:49:44 -04:00

309 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Assets.PixelFantasy.Common.Scripts.CharacterScripts;
using Assets.PixelFantasy.Common.Scripts.CollectionScripts;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
namespace Assets.PixelFantasy.Common.Scripts.EditorScripts
{
public class CharacterEditor : MonoBehaviour
{
public SpriteCollection SpriteCollection;
public List<LayerEditor> Layers;
public CharacterBuilderBase CharacterBuilder;
public Sprite EmptyIcon;
public AudioSource AudioSource;
public AudioClip EquipSound;
public static event Action<string> SliceTextureRequest = _ => {};
public static event Action<string> CreateSpriteLibraryRequest = _ => { };
public void Start()
{
foreach (var layer in Layers)
{
if (layer.Controls)
{
if (layer.Default != "")
{
layer.Index = SpriteCollection.Layers.Single(i => i.Name == layer.Name).Textures.FindIndex(i => i.name == layer.Default);
}
else
{
layer.Index = -1;
}
layer.Content = SpriteCollection.Layers.Single(i => i.Name == layer.Name);
layer.Controls.Dropdown.options = new List<Dropdown.OptionData>();
if (layer.CanBeEmpty) layer.Controls.Dropdown.options.Add(new Dropdown.OptionData("Empty", EmptyIcon));
layer.Controls.Dropdown.options.AddRange(layer.Content.Textures.Select(i => new Dropdown.OptionData(GetDisplayName(i.name), layer.Content.GetIcon(i))));
layer.Controls.Dropdown.value = -1;
layer.Controls.Dropdown.value = layer.Index + (layer.CanBeEmpty ? 1 : 0);
layer.Controls.Dropdown.onValueChanged.AddListener(value => SetIndex(layer, value));
layer.Controls.Prev.onClick.AddListener(() => Switch(layer, -1));
layer.Controls.Next.onClick.AddListener(() => Switch(layer, +1));
layer.Controls.Hide.onClick.AddListener(() => Hide(layer));
layer.Controls.Paint.onClick.AddListener(() => Paint(layer));
layer.Controls.Hue.onValueChanged.AddListener(value => Rebuild());
layer.Controls.Saturation.onValueChanged.AddListener(value => Rebuild());
layer.Controls.Brightness.onValueChanged.AddListener(value => Rebuild());
layer.Controls.OnSelectFixedColor = color => Repaint(layer, color);
}
}
Rebuild();
}
private void Rebuild()
{
var layers = Layers.ToDictionary(i => i.Name, i => i.SpriteData);
CharacterBuilder.Head = layers["Head"];
CharacterBuilder.Ears = layers["Ears"];
CharacterBuilder.Eyes = layers["Eyes"];
CharacterBuilder.Body = layers["Body"];
CharacterBuilder.Hair = layers["Hair"];
CharacterBuilder.Armor = layers["Armor"];
CharacterBuilder.Helmet = layers["Helmet"];
CharacterBuilder.Weapon = layers["Weapon"];
CharacterBuilder.Firearm = layers["Firearm"];
CharacterBuilder.Shield = layers["Shield"];
CharacterBuilder.Cape = layers["Cape"];
CharacterBuilder.Back = layers["Back"];
CharacterBuilder.Mask = layers["Mask"];
CharacterBuilder.Horns = layers["Horns"];
CharacterBuilder.Rebuild();
if (AudioSource && EquipSound)
{
AudioSource.PlayOneShot(EquipSound, 0.5f);
}
}
public void Hide(LayerEditor layer)
{
layer.Hidden = !layer.Hidden;
Rebuild();
}
public void Paint(LayerEditor layer)
{
#if UNITY_EDITOR
ColorPicker.Open(layer.Color);
ColorPicker.OnColorPicked = color => { layer.Color = color; Rebuild(); };
#endif
}
public void Repaint(LayerEditor layer, Color color)
{
layer.Color = color;
if (layer.Name == "Body")
{
Layers.Single(i => i.Name == "Head").Color = color;
Layers.Single(i => i.Name == "Ears").Color = color;
}
if (layer.Name == "Head")
{
Layers.Single(i => i.Name == "Ears").Color = color;
}
Rebuild();
}
public void Preset(string preset)
{
var body = Layers.Single(i => i.Name == "Body");
var dropdown = body.Controls.Dropdown;
var index = dropdown.options.FindIndex(i => i.text == GetDisplayName(preset));
body.Color = Color.white;
if (index == -1)
{
dropdown.value = 0;
}
else if (index == dropdown.value)
{
dropdown.onValueChanged.Invoke(index);
}
else
{
dropdown.value = index;
}
Layers.Single(i => i.Name == "Body").Color = Color.white;
Layers.Single(i => i.Name == "Head").Color = Color.white;
Layers.Single(i => i.Name == "Ears").Color = Color.white;
Layers.Single(i => i.Name == "Eyes").Color = Color.white;
Layers.Single(i => i.Name == "Horns").Color = Color.white;
}
private void Switch(LayerEditor layer, int direction)
{
layer.Switch(direction);
Rebuild();
}
private LayerEditor _layer;
private int _index;
private void SetIndex(LayerEditor layer, int index)
{
if (layer == _layer && index == _index) return;
_layer = layer;
_index = index;
if (layer.CanBeEmpty) index--;
layer.SetIndex(index);
var caption = layer.Controls.Dropdown.options[layer.Controls.Dropdown.value].text;
if (layer.Name == "Body")
{
var head = Layers.Single(i => i.Name == "Head");
var ears = Layers.Single(i => i.Name == "Ears");
var eyes = Layers.Single(i => i.Name == "Eyes");
var hair = Layers.Single(i => i.Name == "Hair");
var horns = Layers.Single(i => i.Name == "Horns");
var headIndex = head.Controls.Dropdown.options.FindIndex(i => i.text == caption);
var earsIndex = ears.Controls.Dropdown.options.FindIndex(i => i.text == caption);
var eyesIndex = eyes.Controls.Dropdown.options.FindIndex(i => i.text == caption);
var hornsIndex = horns.Controls.Dropdown.options.FindIndex(i => i.text == caption);
if (headIndex == -1) headIndex = 0;
if (earsIndex == -1) earsIndex = 0;
if (eyesIndex == -1) eyesIndex = 0;
if (hornsIndex == -1) hornsIndex = 0;
head.Controls.Dropdown.value = headIndex;
ears.Controls.Dropdown.value = earsIndex;
eyes.Controls.Dropdown.value = eyesIndex;
horns.Controls.Dropdown.value = hornsIndex;
head.Color = layer.Color;
ears.Color = layer.Color;
if (caption != "Human")
{
hair.Controls.Dropdown.value = 0;
}
}
else if (layer.Name == "Weapon" && index != -1)
{
Layers.Single(i => i.Name == "Firearm").Controls.Dropdown.value = -1;
}
else if (layer.Name == "Firearm" && index != -1)
{
Layers.Single(i => i.Name == "Weapon").Controls.Dropdown.value = -1;
}
Rebuild();
}
private static string GetDisplayName(string fileName)
{
var displayName = Regex.Replace(fileName, @"\[\w+\]", "");
displayName = Regex.Replace(displayName, "([a-z])([A-Z])", "$1 $2");
return displayName.Trim();
}
public void Reset()
{
CharacterBuilder.Reset();
}
public void Randomize()
{
CharacterBuilder.Randomize();
}
public void Save()
{
CharacterBuilder.Rebuild(forceMerge: true);
var bytes = CharacterBuilder.Texture.EncodeToPNG();
CharacterBuilder.Rebuild(forceMerge: false);
SaveFileDialog("Save as PNG", "SpriteSheet", "Image", ".png", bytes);
}
private void SaveFileDialog(string title, string fileName, string fileType, string extension, byte[] bytes)
{
#if UNITY_EDITOR
var path = EditorUtility.SaveFilePanel(title, null, fileName + extension, extension.Replace(".", ""));
if (path == "") return;
File.WriteAllBytes(path, bytes);
if (path.StartsWith(Application.dataPath))
{
path = "Assets" + path.Substring(Application.dataPath.Length);
AssetDatabase.Refresh();
var importer = (TextureImporter) AssetImporter.GetAtPath(path);
importer.textureType = TextureImporterType.Sprite;
importer.maxTextureSize = 2048;
importer.SaveAndReimport();
AssetDatabase.Refresh();
SliceTextureRequest(path);
if (EditorUtility.DisplayDialog("Success", $"Texture saved and sliced:\n{path}\n\nDo you want to create Sprite Library Asset for it?", "Yes", "No"))
{
CreateSpriteLibraryRequest(path);
}
}
else
{
EditorUtility.DisplayDialog("Success", $"Texture saved:\n{path}\n\nTip: textures are automatically sliced when saving to Assets.", "OK");
}
#elif UNITY_STANDALONE
#if FILE_BROWSER
StartCoroutine(SimpleFileBrowserForWindows.WindowsFileBrowser.SaveFile(title, "", fileName, fileType, extension, bytes, (success, p) => { }));
#else
Debug.LogWarning("Please import this asset: http://u3d.as/2QLg");
#endif
#elif UNITY_WEBGL
#if FILE_BROWSER
SimpleFileBrowserForWebGL.WebFileBrowser.Download(fileName + extension, bytes);
#else
Debug.LogWarning("Please import this asset: http://u3d.as/2W52");
#endif
#endif
}
}
}