Copie depuis Unity VCS vers GitHub

This commit is contained in:
Denis L.
2025-12-10 18:51:40 +01:00
parent 5cfd9de581
commit 7383621db3
902 changed files with 588195 additions and 0 deletions

View File

@@ -0,0 +1,194 @@
using System.Collections.Generic;
using System.Linq;
using CharacterCustomizationTool.Editor.MaterialManagement;
using CharacterCustomizationTool.Editor.Randomizer;
using CharacterCustomizationTool.Editor.SlotValidation;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Character
{
public class CustomizableCharacter
{
private static readonly SlotType[] AlwaysEnabledParts = { SlotType.Body, SlotType.Faces };
private readonly List<List<SavedSlot>> _savedCombinations = new();
private readonly GameObject _characterGameObject;
private readonly SlotValidator _slotValidator = new();
public SlotBase[] Slots { get; }
public int SavedCombinationsCount => _savedCombinations.Count;
public CustomizableCharacter(SlotLibrary slotLibrary)
{
_characterGameObject = LoadBaseMesh();
Slots = CreateSlots(slotLibrary);
}
public GameObject InstantiateCharacter()
{
var character = Object.Instantiate(_characterGameObject, Vector3.zero, Quaternion.identity);
return character;
}
public void SelectPrevious(SlotType slotType)
{
GetSlotBy(slotType).SelectPrevious();
}
public void SelectNext(SlotType slotType)
{
GetSlotBy(slotType).SelectNext();
}
public bool IsToggled(SlotType slotType)
{
return GetSlotBy(slotType).IsEnabled;
}
public void Toggle(SlotType type, bool isToggled)
{
GetSlotBy(type).Toggle(isToggled);
_slotValidator.Validate(this, type, isToggled);
}
public void Draw(int previewLayer, Camera camera)
{
var materialProvider = new MaterialProvider();
foreach (var slot in Slots)
{
slot.Draw(materialProvider.MainColor, previewLayer, camera, 0);
}
}
public void Randomize()
{
var randomCharacterGenerator = new RandomCharacterGenerator();
randomCharacterGenerator.Randomize(this);
}
public void SaveCombination()
{
var savedCombinations = Slots.Select(slot => new SavedSlot(slot.Type, slot.IsEnabled, slot.SelectedIndex)).ToList();
_savedCombinations.Add(savedCombinations);
while (_savedCombinations.Count > 4)
{
_savedCombinations.RemoveAt(0);
}
}
public void LastCombination()
{
var lastSavedCombination = _savedCombinations.Last();
if (IsSame())
{
_savedCombinations.Remove(lastSavedCombination);
lastSavedCombination = _savedCombinations.Last();
}
foreach (var slot in Slots)
{
var savedCombination = lastSavedCombination.Find(c => c.SlotType == slot.Type);
slot.Toggle(savedCombination.IsEnabled);
slot.Select(savedCombination.VariantIndex);
}
_savedCombinations.Remove(lastSavedCombination);
}
public bool IsSame()
{
var lastSavedCombination = _savedCombinations.Last();
return !Slots
.Select(slot => new { slot, savedCombination = lastSavedCombination.Find(c => c.SlotType == slot.Type) })
.Where(t => t.slot.IsEnabled != t.savedCombination.IsEnabled || t.slot.SelectedIndex != t.savedCombination.VariantIndex)
.Select(t => t.slot)
.Any();
}
public void PickGroup(GroupType groupType, int index, bool isEnabled)
{
foreach (var slot in Slots)
{
if (slot.TryPickInGroup(groupType, index, isEnabled))
{
break;
}
}
}
public int GetVariantsCountInGroup(GroupType groupType)
{
foreach (var slot in Slots)
{
if (slot.TryGetVariantsCountInGroup(groupType, out var count))
{
return count;
}
}
return 0;
}
public void ToDefault()
{
foreach (var slot in Slots)
{
if (slot.Type != SlotType.Body && slot.Type != SlotType.Faces)
{
slot.Toggle(false);
}
}
}
public List<SlotName> GetSlotNames()
{
var partNames = _characterGameObject.transform
.Cast<Transform>()
.Where(mesh => mesh.TryGetComponent<Renderer>(out _))
.Select(mesh => new SlotName(mesh.name)).ToList();
return partNames;
}
public static bool IsAlwaysEnabled(SlotType slotType)
{
return AlwaysEnabledParts.Contains(slotType);
}
private SlotBase GetSlotBy(SlotType slotType)
{
return Slots.FirstOrDefault(s => s.Type == slotType);
}
private static GameObject LoadBaseMesh()
{
var availableBaseMeshes = new List<GameObject>();
foreach (var keyword in AssetsPath.BaseMesh.Keywords)
{
var baseMeshes = AssetLoader.LoadAssets<GameObject>(keyword, AssetsPath.BaseMesh.Path);
availableBaseMeshes.AddRange(baseMeshes);
}
var baseMesh = availableBaseMeshes.First();
return baseMesh;
}
private static SlotBase[] CreateSlots(SlotLibrary slotLibrary)
{
var list = new List<SlotBase>();
list.Add(new FullBodySlot(slotLibrary.FullBodyCostumes));
list.AddRange(slotLibrary.Slots.Select(s => new Slot(s.Type, s.Groups)));
var sortedSlots = SlotSorter.Sort(list);
return sortedSlots.ToArray();
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: eb14e4484b804470a44337b79a7e352d
timeCreated: 1735056168
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/CustomizableCharacter.cs
uploadId: 780839

View File

@@ -0,0 +1,73 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Character
{
public class FullBodySlot : SlotBase
{
private readonly List<FullBodyVariant> _variants;
private FullBodyVariant _selected;
public override string Name => "Full Body";
public override GameObject Preview => _selected.PreviewObject;
public override int SelectedIndex => _variants.FindIndex(v => v.Name == _selected.Name);
public override int VariantsCount => _variants.Count;
public override (SlotType, Mesh)[] Meshes => _selected.Elements.Select(e => (e.Type, e.Mesh)).ToArray();
public FullBodySlot(FullBodyEntry[] fullBodyEntries) : base(SlotType.FullBody)
{
_variants = fullBodyEntries.Select(e => new FullBodyVariant(e)).ToList();
_selected = _variants.First();
}
public override void SelectNext()
{
_selected = _variants[GetNextIndex()];
}
public override void SelectPrevious()
{
_selected = _variants[GetPreviousIndex()];
}
public override void Select(int index)
{
_selected = _variants[index];
}
public override bool TryGetVariantsCountInGroup(GroupType groupType, out int count)
{
if (groupType == GroupType.Costumes)
{
count = _variants.Count;
return true;
}
count = 0;
return false;
}
public override bool TryPickInGroup(GroupType groupType, int index, bool isEnabled)
{
if (!isEnabled || groupType != GroupType.Costumes)
{
return false;
}
_selected = _variants[index];
Toggle(true);
return true;
}
protected override void DrawSlot(Material material, int previewLayer, Camera camera, int submeshIndex)
{
foreach (var element in _selected.Elements)
{
DrawMesh(element.Mesh, material, previewLayer, camera, submeshIndex);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8adf98cee48f47c099edca891fba555f
timeCreated: 1735290043
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/FullBodySlot.cs
uploadId: 780839

View File

@@ -0,0 +1,39 @@
using System.Linq;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Character
{
public class FullBodyVariant
{
public FullBodyElement[] Elements { get; }
public GameObject PreviewObject { get; }
public string Name => Elements.First().Mesh.name;
public FullBodyVariant(FullBodyEntry fullBodyEntry)
{
Elements = fullBodyEntry.Slots.Select(s => new FullBodyElement(s.Type, s.GameObject.GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh)).ToArray();
PreviewObject = PreviewCreator.CreateVariantPreview(GetPreviewMesh(Elements));
}
private static Mesh GetPreviewMesh(FullBodyElement[] elements)
{
var element = elements.FirstOrDefault(e => e.Type == SlotType.Hat)
?? elements.FirstOrDefault(e => e.Type == SlotType.Outerwear)
?? elements.First();
return element.Mesh;
}
}
public class FullBodyElement
{
public SlotType Type { get; }
public Mesh Mesh { get; }
public FullBodyElement(SlotType type, Mesh mesh)
{
Type = type;
Mesh = mesh;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 5936af340a884d9987333809fb1f3c4c
timeCreated: 1735290262
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/FullBodyVariant.cs
uploadId: 780839

View File

@@ -0,0 +1,24 @@
using CharacterCustomizationTool.Editor.MaterialManagement;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Character
{
public static class PreviewCreator
{
private static readonly MaterialProvider MaterialProvider = new();
public static GameObject CreateVariantPreview(Mesh mesh)
{
var variant = new GameObject(mesh.name);
variant.AddComponent<MeshFilter>().sharedMesh = mesh;
variant.transform.position = Vector3.one * int.MaxValue;
variant.hideFlags = HideFlags.HideAndDontSave;
var renderer = variant.AddComponent<MeshRenderer>();
renderer.sharedMaterial = MaterialProvider.MainColor;
return variant;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8556696d659d49f28660a23959766758
timeCreated: 1735298241
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/PreviewCreator.cs
uploadId: 780839

View File

@@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Character
{
public class Slot : SlotBase
{
private readonly SlotGroup[] _groups;
private readonly List<SlotVariant> _variants;
private SlotVariant _selected;
public override string Name => Type.ToString();
public override GameObject Preview => _selected.PreviewObject;
public override int SelectedIndex => _variants.FindIndex(v => v.Name == _selected.Name);
public override int VariantsCount => _variants.Count;
public override (SlotType, Mesh)[] Meshes => new[]
{
(Type, _selected.Mesh),
};
public Slot(SlotType type, SlotGroupEntry[] slotGroupEntries) : base(type)
{
_groups = slotGroupEntries.Select(TranslateGroup).ToArray();
_variants = FlattenVariants(_groups);
_selected = _variants.First();
}
public override void SelectNext()
{
_selected = _variants[GetNextIndex()];
}
public override void SelectPrevious()
{
_selected = _variants[GetPreviousIndex()];
}
public override void Select(int index)
{
_selected = _variants[index];
}
public override bool TryGetVariantsCountInGroup(GroupType stepGroupType, out int count)
{
var group = _groups.FirstOrDefault(g => g.Type == stepGroupType);
if (group != null)
{
count = group.Variants.Length;
return true;
}
count = 0;
return false;
}
public override bool TryPickInGroup(GroupType groupType, int index, bool isEnabled)
{
if (!isEnabled || _groups.All(g => g.Type != groupType))
{
return false;
}
var mesh = _groups.First(g => g.Type == groupType).Variants[index].Mesh;
_selected = new SlotVariant(mesh);
Toggle(true);
return true;
}
protected override void DrawSlot(Material material, int previewLayer, Camera camera, int submeshIndex)
{
DrawMesh(_selected.Mesh, material, previewLayer, camera, submeshIndex);
}
private static SlotGroup TranslateGroup(SlotGroupEntry entry)
{
var variants = entry.Variants
.Select(v => new SlotVariant(v.gameObject.GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh))
.ToArray();
return new SlotGroup(entry.Type, variants);
}
private static List<SlotVariant> FlattenVariants(SlotGroup[] groups)
{
var variants = new List<SlotVariant>();
foreach (var group in groups)
{
variants.AddRange(group.Variants);
}
return variants;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7be4a90f04ae0554bb98e8ad42eec182
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/Slot.cs
uploadId: 780839

View File

@@ -0,0 +1,73 @@
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Character
{
public abstract class SlotBase
{
public abstract string Name { get; }
public abstract GameObject Preview { get; }
public abstract int SelectedIndex { get; }
public abstract int VariantsCount { get; }
public abstract (SlotType, Mesh)[] Meshes { get; }
public SlotType Type { get; }
public bool IsEnabled { get; private set; } = true;
protected SlotBase(SlotType type)
{
Type = type;
}
public abstract void SelectNext();
public abstract void SelectPrevious();
public abstract void Select(int index);
public abstract bool TryGetVariantsCountInGroup(GroupType groupType, out int count);
public abstract bool TryPickInGroup(GroupType groupType, int index, bool isEnabled);
public void Draw(Material material, int previewLayer, Camera camera, int submeshIndex)
{
if (IsEnabled)
{
DrawSlot(material, previewLayer, camera, submeshIndex);
}
}
public bool IsOfType(SlotType type)
{
return Type == type;
}
public void Toggle(bool isToggled)
{
IsEnabled = isToggled;
}
protected abstract void DrawSlot(Material material, int previewLayer, Camera camera, int submeshIndex);
protected int GetNextIndex()
{
var targetIndex = SelectedIndex + 1;
if (targetIndex >= VariantsCount)
{
targetIndex = 0;
}
return targetIndex;
}
protected int GetPreviousIndex()
{
var targetIndex = SelectedIndex - 1;
if (targetIndex < 0)
{
targetIndex = VariantsCount - 1;
}
return targetIndex;
}
protected static void DrawMesh(Mesh mesh, Material material, int previewLayer, Camera camera, int submeshIndex)
{
Graphics.DrawMesh(mesh, new Vector3(0, -.01f, 0), Quaternion.identity, material, previewLayer, camera, submeshIndex);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4790fea957a0452c9b3fdafae8c50a85
timeCreated: 1735299299
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/SlotBase.cs
uploadId: 780839

View File

@@ -0,0 +1,14 @@
namespace CharacterCustomizationTool.Editor.Character
{
public class SlotGroup
{
public readonly GroupType Type;
public readonly SlotVariant[] Variants;
public SlotGroup(GroupType type, SlotVariant[] variants)
{
Type = type;
Variants = variants;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a8574b612b164d90a75a3fe20a376234
timeCreated: 1735291905
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/SlotGroup.cs
uploadId: 780839

View File

@@ -0,0 +1,12 @@
using UnityEditor;
namespace CharacterCustomizationTool.Editor.Character
{
public static class SlotLibraryLoader
{
public static SlotLibrary LoadSlotLibrary()
{
return AssetDatabase.LoadAssetAtPath<SlotLibrary>(AssetsPath.SlotLibrary);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3c3cb4b19185480caba797a0824231a7
timeCreated: 1735291150
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/SlotLibraryLoader.cs
uploadId: 780839

View File

@@ -0,0 +1,17 @@
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Character
{
public class SlotVariant
{
public Mesh Mesh { get; }
public GameObject PreviewObject { get; }
public string Name => Mesh.name;
public SlotVariant(Mesh mesh)
{
Mesh = mesh;
PreviewObject = PreviewCreator.CreateVariantPreview(mesh);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 2cea17fb1a249944b8f64f0a431b340d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 304841
packageName: Creative Characters FREE - Animated Low Poly 3D Models
packageVersion: 2.2
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/SlotVariant.cs
uploadId: 780839