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,8 @@
fileFormatVersion: 2
guid: f853990e5772f884290f13fd6d8555b0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,348 @@
using System;
using UnityEngine;
namespace Controller
{
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(Animator))]
[DisallowMultipleComponent]
public class CharacterMover : MonoBehaviour
{
[Header("Movement")]
[SerializeField]
private float m_WalkSpeed = 1f;
[SerializeField]
private float m_RunSpeed = 4f;
[SerializeField, Range(0f, 360f)]
private float m_RotateSpeed = 90f;
[SerializeField]
private Space m_Space = Space.Self;
[SerializeField]
private float m_JumpHeight = 5f;
[Header("Animator")]
[SerializeField]
private string m_HorizontalID = "Hor";
[SerializeField]
private string m_VerticalID = "Vert";
[SerializeField]
private string m_StateID = "State";
[SerializeField]
private string m_JumpID = "IsJump";
[SerializeField]
private LookWeight m_LookWeight = new(1f, 0.3f, 0.7f, 1f);
private Transform m_Transform;
private CharacterController m_Controller;
private Animator m_Animator;
private MovementHandler m_Movement;
private AnimationHandler m_Animation;
private Vector2 m_Axis;
private Vector3 m_Target;
private bool m_IsRun;
private bool m_IsJump;
private bool m_IsMoving;
public Vector2 Axis => m_Axis;
public Vector3 Target => m_Target;
public bool IsRun => m_IsRun;
private void OnValidate()
{
m_WalkSpeed = Mathf.Max(m_WalkSpeed, 0f);
m_RunSpeed = Mathf.Max(m_RunSpeed, m_WalkSpeed);
m_Movement?.SetStats(m_WalkSpeed / 3.6f, m_RunSpeed / 3.6f, m_RotateSpeed, m_JumpHeight, m_Space);
}
private void Awake()
{
m_Transform = transform;
m_Controller = GetComponent<CharacterController>();
m_Animator = GetComponent<Animator>();
m_Movement = new MovementHandler(m_Controller, m_Transform, m_WalkSpeed, m_RunSpeed, m_RotateSpeed, m_JumpHeight, m_Space);
m_Animation = new AnimationHandler(m_Animator, m_HorizontalID, m_VerticalID, m_StateID, m_JumpID);
}
private void Update()
{
m_Movement.Move(Time.deltaTime, in m_Axis, in m_Target, m_IsRun, m_IsJump, m_IsMoving, out var animAxis, out var isAir);
m_Animation.Animate(in animAxis, m_IsRun? 1f : 0f, isAir, Time.deltaTime);
}
private void OnAnimatorIK()
{
m_Animation.AnimateIK(in m_Target, m_LookWeight);
}
public void SetInput(in Vector2 axis, in Vector3 target, in bool isRun, in bool isJump)
{
m_Axis = axis;
m_Target = target;
m_IsRun = isRun;
m_IsJump = isJump;
if (m_Axis.sqrMagnitude < Mathf.Epsilon)
{
m_Axis = Vector2.zero;
m_IsMoving = false;
}
else
{
m_Axis = Vector3.ClampMagnitude(m_Axis, 1f);
m_IsMoving = true;
}
}
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if(hit.normal.y > m_Controller.stepOffset)
{
m_Movement.SetSurface(hit.normal);
}
}
[Serializable]
private struct LookWeight
{
public float weight;
public float body;
public float head;
public float eyes;
public LookWeight(float weight, float body, float head, float eyes)
{
this.weight = weight;
this.body = body;
this.head = head;
this.eyes = eyes;
}
}
#region Handlers
private class MovementHandler
{
private readonly CharacterController m_Controller;
private readonly Transform m_Transform;
private float m_WalkSpeed;
private float m_RunSpeed;
private float m_RotateSpeed;
private float m_JumpHeight;
private Space m_Space;
private readonly float m_Luft = 75f;
private readonly float m_JumpReload = 1f;
private float m_TargetAngle;
private bool m_IsRotating = false;
private Vector3 m_Normal;
private Vector3 m_GravityAcelleration = Physics.gravity;
private float m_jumpTimer;
public MovementHandler(CharacterController controller, Transform transform, float walkSpeed, float runSpeed, float rotateSpeed, float jumpHeight, Space space)
{
m_Controller = controller;
m_Transform = transform;
m_WalkSpeed = walkSpeed;
m_RunSpeed = runSpeed;
m_RotateSpeed = rotateSpeed;
m_JumpHeight = jumpHeight;
m_Space = space;
}
public void SetStats(float walkSpeed, float runSpeed, float rotateSpeed, float jumpHeight, Space space)
{
m_WalkSpeed = walkSpeed;
m_RunSpeed = runSpeed;
m_RotateSpeed = rotateSpeed;
m_JumpHeight = jumpHeight;
m_Space = space;
}
public void SetSurface(in Vector3 normal)
{
m_Normal = normal;
}
public void Move(float deltaTime, in Vector2 axis, in Vector3 target, bool isRun, bool isJump, bool isMoving, out Vector2 animAxis, out bool isAir)
{
var targetForward = Vector3.Normalize(target - m_Transform.position);
ConvertMovement(in axis, in targetForward, out var movement);
CaculateGravity(isJump, deltaTime, out isAir);
Displace(deltaTime, in movement, isRun);
Turn(in targetForward, isMoving);
UpdateRotation(deltaTime);
GenAnimationAxis(in movement, out animAxis);
}
private void ConvertMovement(in Vector2 axis, in Vector3 targetForward, out Vector3 movement)
{
Vector3 forward;
Vector3 right;
if (m_Space == Space.Self)
{
forward = new Vector3(targetForward.x, 0f, targetForward.z).normalized;
right = Vector3.Cross(Vector3.up, forward).normalized;
}
else
{
forward = Vector3.forward;
right = Vector3.right;
}
movement = axis.x * right + axis.y * forward;
movement = Vector3.ProjectOnPlane(movement, m_Normal);
}
private void Displace(float deltaTime, in Vector3 movement, bool isRun)
{
Vector3 displacement = (isRun ? m_RunSpeed : m_WalkSpeed) * movement;
displacement += m_GravityAcelleration;
displacement *= deltaTime;
m_Controller.Move(displacement);
}
private void CaculateGravity(bool isJump, float deltaTime, out bool isAir)
{
m_jumpTimer = Mathf.Max(m_jumpTimer - deltaTime, 0f);
if (m_Controller.isGrounded)
{
if (isJump && m_jumpTimer <= 0)
{
var gravity = Physics.gravity;
var length = gravity.magnitude;
m_GravityAcelleration += -(gravity / length) * Mathf.Sqrt(m_JumpHeight * 6f * length);
m_jumpTimer = m_JumpReload;
isAir = true;
return;
}
m_GravityAcelleration = Physics.gravity;
isAir = false;
return;
}
isAir = true;
m_GravityAcelleration += Physics.gravity * deltaTime;
return;
}
private void GenAnimationAxis(in Vector3 movement, out Vector2 animAxis)
{
if(m_Space == Space.Self)
{
animAxis = new Vector2(Vector3.Dot(movement, m_Transform.right), Vector3.Dot(movement, m_Transform.forward));
}
else
{
animAxis = new Vector2(Vector3.Dot(movement, Vector3.right), Vector3.Dot(movement, Vector3.forward));
}
}
private void Turn(in Vector3 targetForward, bool isMoving)
{
var angle = Vector3.SignedAngle(m_Transform.forward, Vector3.ProjectOnPlane(targetForward, Vector3.up), Vector3.up);
if (!m_IsRotating)
{
if (!isMoving && Mathf.Abs(angle) < m_Luft)
{
m_IsRotating = false;
return;
}
m_IsRotating = true;
}
m_TargetAngle = angle;
}
private void UpdateRotation(float deltaTime)
{
if(!m_IsRotating)
{
return;
}
var rotDelta = m_RotateSpeed * deltaTime;
if (rotDelta + Mathf.PI * 2f + Mathf.Epsilon >= Mathf.Abs(m_TargetAngle))
{
rotDelta = m_TargetAngle;
m_IsRotating = false;
}
else
{
rotDelta *= Mathf.Sign(m_TargetAngle);
}
m_Transform.Rotate(Vector3.up, rotDelta);
}
}
private class AnimationHandler
{
private readonly Animator m_Animator;
private readonly string m_HorizontalID;
private readonly string m_VerticalID;
private readonly string m_StateID;
private readonly string m_JumpID;
private readonly float k_InputFlow = 4.5f;
private float m_FlowState;
private Vector2 m_FlowAxis;
public AnimationHandler(Animator animator, string horizontalID, string verticalID, string stateID, string jumpID)
{
m_Animator = animator;
m_HorizontalID = horizontalID;
m_VerticalID = verticalID;
m_StateID = stateID;
m_JumpID = jumpID;
}
public void Animate(in Vector2 axis, float state, bool isJump, float deltaTime)
{
m_Animator.SetFloat(m_HorizontalID, m_FlowAxis.x);
m_Animator.SetFloat(m_VerticalID, m_FlowAxis.y);
m_Animator.SetFloat(m_StateID, Mathf.Clamp01(m_FlowState));
m_Animator.SetBool(m_JumpID, isJump);
m_FlowAxis = Vector2.ClampMagnitude(m_FlowAxis + k_InputFlow * deltaTime * (axis - m_FlowAxis).normalized, 1f);
m_FlowState = Mathf.Clamp01(m_FlowState + k_InputFlow * deltaTime * Mathf.Sign(state - m_FlowState));
}
public void AnimateIK(in Vector3 target, in LookWeight lookWeight)
{
m_Animator.SetLookAtPosition(target);
m_Animator.SetLookAtWeight(lookWeight.weight, lookWeight.body, lookWeight.head, lookWeight.eyes);
}
}
#endregion
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f75db5b538eef814b9775d744f05e3b5
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/Character_Controller/CharacterMover.cs
uploadId: 780839

View File

@@ -0,0 +1,86 @@
using UnityEngine;
namespace Controller
{
[RequireComponent(typeof(CharacterMover))]
public class MovePlayerInput : MonoBehaviour
{
[Header("Character")]
[SerializeField]
private string m_HorizontalAxis = "Horizontal";
[SerializeField]
private string m_VerticalAxis = "Vertical";
[SerializeField]
private string m_JumpButton = "Jump";
[SerializeField]
private KeyCode m_RunKey = KeyCode.LeftShift;
[Header("Camera")]
[SerializeField]
private PlayerCamera m_Camera;
[SerializeField]
private string m_MouseX = "Mouse X";
[SerializeField]
private string m_MouseY = "Mouse Y";
[SerializeField]
private string m_MouseScroll = "Mouse ScrollWheel";
private CharacterMover m_Mover;
private Vector2 m_Axis;
private bool m_IsRun;
private bool m_IsJump;
private Vector3 m_Target;
private Vector2 m_MouseDelta;
private float m_Scroll;
private void Awake()
{
m_Mover = GetComponent<CharacterMover>();
if(m_Camera == null )
{
m_Camera = Camera.main == null ? null : Camera.main.GetComponent<PlayerCamera>();
}
if(m_Camera != null) {
m_Camera.SetPlayer(transform);
}
}
private void Update()
{
GatherInput();
SetInput();
}
public void GatherInput()
{
m_Axis = new Vector2(Input.GetAxis(m_HorizontalAxis), Input.GetAxis(m_VerticalAxis));
m_IsRun = Input.GetKey(m_RunKey);
m_IsJump = Input.GetButton(m_JumpButton);
m_Target = (m_Camera == null) ? Vector3.zero : m_Camera.Target;
m_MouseDelta = new Vector2(Input.GetAxis(m_MouseX), Input.GetAxis(m_MouseY));
m_Scroll = Input.GetAxis(m_MouseScroll);
}
public void BindMover(CharacterMover mover)
{
m_Mover = mover;
}
public void SetInput()
{
if (m_Mover != null)
{
m_Mover.SetInput(in m_Axis, in m_Target, in m_IsRun, m_IsJump);
}
if (m_Camera != null)
{
m_Camera.SetInput(in m_MouseDelta, m_Scroll);
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: b2c67ce836140b4479603ebcf944cddd
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/Character_Controller/MovePlayerInput.cs
uploadId: 780839

View File

@@ -0,0 +1,64 @@
using UnityEngine;
namespace Controller
{
public abstract class PlayerCamera : MonoBehaviour
{
private const float MIN_DISTANCE = 1f;
private const float MAX_DISTANCE = 10f;
private const float TARGET_DISTANCE = MAX_DISTANCE * 2f;
protected Transform m_Player;
[SerializeField, Range(0f, 1f)]
private float m_SensitivityX = 0.1f;
[SerializeField, Range(0f, 1f)]
private float m_SensitivityY = 0.1f;
[SerializeField, Range(0f, 1f)]
private float m_Zoom = 0.5f;
[SerializeField, Range(0f, 1f)]
private float m_SensetivityZoom = 0.1f;
[SerializeField, Range(0, 90f)]
private float m_MinAngle = 0f;
[SerializeField, Range(0, 90f)]
private float m_MaxAngle = 50f;
protected Transform m_Target;
protected Transform m_Transform;
protected Vector2 m_Angles;
protected float m_Distance;
public Vector3 Target => m_Target.position;
public float TargetDistance => TARGET_DISTANCE;
protected virtual void Awake()
{
m_Transform = transform;
m_Target = new GameObject($"Target_{gameObject.name}").transform;
if(m_Transform.parent != null)
{
m_Target.transform.parent = m_Transform.parent;
}
}
public void SetPlayer(Transform player) {
m_Player = player;
}
public virtual void SetInput(in Vector2 delta, float scroll)
{
m_Angles += new Vector2(delta.y * m_SensitivityY, delta.x * m_SensitivityX) * 360f;
m_Angles.x = Mathf.Clamp(m_Angles.x, m_MinAngle, m_MaxAngle);
m_Zoom += scroll * m_SensetivityZoom;
m_Zoom = Mathf.Clamp01(m_Zoom);
m_Distance = (1f - m_Zoom) * (MAX_DISTANCE - MIN_DISTANCE) + MIN_DISTANCE;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 6e64ae1274b15fa4fbea3733685f5b29
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/Character_Controller/PlayerCamera.cs
uploadId: 780839

View File

@@ -0,0 +1,65 @@
using UnityEngine;
namespace Controller
{
public class ThirdPersonCamera : PlayerCamera
{
[SerializeField, Range(0f, 2f)]
private float m_Offset = 1.5f;
[SerializeField, Range(0f, 360f)]
private float m_CameraSpeed = 90f;
private Vector3 m_LookPoint;
private Vector3 m_TargetPos;
private void LateUpdate()
{
Move(Time.deltaTime);
}
public override void SetInput(in Vector2 delta, float scroll)
{
base.SetInput(delta, scroll);
var dir = new Vector3(0, 0, -m_Distance);
var rot = Quaternion.Euler(m_Angles.x, m_Angles.y, 0f);
var playerPos = (m_Player == null) ? Vector3.zero : m_Player.position;
m_LookPoint = playerPos + m_Offset * Vector3.up;
m_TargetPos = m_LookPoint + rot * dir;
}
private void Move(float deltaTime)
{
camera();
target();
void camera()
{
var direction = m_TargetPos - m_Transform.position;
var delta = m_CameraSpeed * deltaTime;
if(delta * delta > direction.sqrMagnitude)
{
m_Transform.position = m_TargetPos;
}
else
{
m_Transform.position += delta * direction.normalized;
}
m_Transform.LookAt(m_LookPoint);
}
void target()
{
if(m_Target == null)
{
return;
}
m_Target.position = m_Transform.position + m_Transform.forward * TargetDistance;
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: b7f4329458cdb464796191393167d4f9
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/Character_Controller/ThirdPersonCamera.cs
uploadId: 780839

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e288d36454b64b945931064f52313219
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace CharacterCustomizationTool.Editor
{
public static class AssetLoader
{
public static IEnumerable<T> LoadAssets<T>(string filter, string folder)
where T : Object
{
var assets = AssetDatabase.FindAssets(filter, new[] { folder })
.Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<T>)
.ToArray();
return assets;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: b259f0c39cff4c16a0d6aa27f0286f0b
timeCreated: 1733473579
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/AssetLoader.cs
uploadId: 780839

View File

@@ -0,0 +1,36 @@
namespace CharacterCustomizationTool.Editor
{
public static class AssetsPath
{
public const string PackageName = "Creative_Characters_FREE";
public static string AnimationController => _root + "Animations/Animation_Controllers/Character_Movement.controller";
public static string SavedCharacters => _root + "Saved_Characters/";
public static string SlotLibrary => _root + "Configs/SlotLibrary.asset";
private static string _root = "Assets/ithappy/" + PackageName + "/";
public static void SetRoot(string root)
{
_root = root;
}
public static class BaseMesh
{
public static readonly string[] Keywords =
{
"Base",
"Basic"
};
public static string Path => _root + "Meshes/";
}
public static class Folder
{
public static string Materials => _root + "Materials/";
public static string Meshes => _root + "Meshes";
public static string Faces => _root + "Meshes/Faces/";
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f2c2e9af7f6a4a1f957a9b57889e19c9
timeCreated: 1712417480
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/AssetsPath.cs
uploadId: 780839

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 82adddc3dfd448ad99ece633e5e75695
timeCreated: 1735290032

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

View File

@@ -0,0 +1,253 @@
using System.IO;
using System.Linq;
using CharacterCustomizationTool.Editor.Character;
using CharacterCustomizationTool.Editor.FaceEditor;
using CharacterCustomizationTool.Editor.MaterialManagement;
using Controller;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
namespace CharacterCustomizationTool.Editor
{
public class CharacterCustomizationWindow : EditorWindow
{
private const string PreviewLayerName = "Character Preview";
private CustomizableCharacter _customizableCharacter;
private PartsEditor _partsEditor;
private Camera _camera;
private int _previewLayer;
private RenderTexture _renderTexture;
private string _prefabPath;
[MenuItem("Tools/Character Customization")]
private static void Init()
{
FindRoot();
var window = GetWindow<CharacterCustomizationWindow>("Character Customization");
window.minSize = new Vector2(990, 655);
window.Show();
}
private void OnEnable()
{
_customizableCharacter = new CustomizableCharacter(SlotLibraryLoader.LoadSlotLibrary());
_partsEditor = new PartsEditor();
LayerMaskUtility.CreateLayer(PreviewLayerName);
_previewLayer = LayerMask.NameToLayer(PreviewLayerName);
}
private void OnGUI()
{
var rect = new Rect(10, 10, 300, 300);
CreateRenderTexture();
InitializeCamera();
DrawCharacter();
_partsEditor.OnGUI(new Rect(330, 10, position.width - 330, position.height), _customizableCharacter);
GUI.DrawTexture(rect, _renderTexture, ScaleMode.StretchToFill, false);
GUI.Label(new Rect(10, 320, 100, 25), "Prefab folder:");
GUI.Label(new Rect(10, 345, 350, 25), AssetsPath.SavedCharacters);
_prefabPath = GUI.TextField(new Rect(10, 372, 300, 20), _prefabPath);
var saveButtonRect = new Rect(10, 400, 300, 40);
if (GUI.Button(saveButtonRect, "Save Prefab"))
{
SavePrefab();
}
var randomizeButtonRect = new Rect(85, 450, 150, 30);
if (GUI.Button(randomizeButtonRect, "Randomize"))
{
Randomize();
}
var isZero = _customizableCharacter.SavedCombinationsCount == 0;
var isSame = false;
var lessThenTwo = false;
if (!isZero)
{
isSame = _customizableCharacter.IsSame();
lessThenTwo = _customizableCharacter.SavedCombinationsCount < 2;
}
using (new EditorGUI.DisabledScope(isZero || (isSame && lessThenTwo)))
{
var lastButtonRect = new Rect(240, 450, 50, 30);
if (GUI.Button(lastButtonRect, "Last"))
{
_customizableCharacter.LastCombination();
}
}
}
private void SavePrefab()
{
var character = _customizableCharacter.InstantiateCharacter();
var materialProvider = new MaterialProvider();
var enabledSlots = _customizableCharacter.Slots.Where(s => s.IsEnabled).ToArray();
foreach (var slot in enabledSlots)
{
foreach (var mesh in slot.Meshes)
{
var child = character.transform.Cast<Transform>().First(t => t.name.StartsWith(mesh.Item1.ToString()));
if (child.TryGetComponent<SkinnedMeshRenderer>(out var skinnedMeshRenderer))
{
skinnedMeshRenderer.sharedMesh = mesh.Item2;
skinnedMeshRenderer.sharedMaterial = materialProvider.MainColor;
skinnedMeshRenderer.localBounds = skinnedMeshRenderer.sharedMesh.bounds;
}
}
}
FaceLoader.AddFaces(character);
AddAnimator(character);
AddMovementComponents(character);
var prefabPath = AssetsPath.SavedCharacters + _prefabPath;
Directory.CreateDirectory(prefabPath);
var path = AssetDatabase.GenerateUniqueAssetPath($"{prefabPath}/Character.prefab");
PrefabUtility.SaveAsPrefabAsset(character, path);
DestroyImmediate(character);
}
private static void AddAnimator(GameObject character)
{
var controller = AssetDatabase.LoadAssetAtPath<AnimatorController>(AssetsPath.AnimationController);
var animator = character.GetComponent<Animator>();
animator.runtimeAnimatorController = controller;
animator.applyRootMotion = false;
}
private static void AddMovementComponents(GameObject character)
{
AddCharacterController(character);
character.AddComponent<CharacterMover>();
character.AddComponent<MovePlayerInput>();
}
private static void AddCharacterController(GameObject character)
{
var characterController = character.AddComponent<CharacterController>();
characterController.center = new Vector3(0, .95f, 0);
characterController.radius = .4f;
characterController.height = 1.8f;
}
private void Randomize()
{
_customizableCharacter.Randomize();
_customizableCharacter.SaveCombination();
}
private void InitializeCamera()
{
if (_camera)
{
return;
}
var cameraPivot = new GameObject("CameraPivot").transform;
cameraPivot.gameObject.hideFlags = HideFlags.HideAndDontSave;
var cameraObject = new GameObject("PreviewCamera")
{
hideFlags = HideFlags.HideAndDontSave
};
_camera = cameraObject.AddComponent<Camera>();
_camera.targetTexture = _renderTexture;
_camera.clearFlags = CameraClearFlags.SolidColor;
_camera.renderingPath = RenderingPath.Forward;
_camera.enabled = false;
_camera.useOcclusionCulling = false;
_camera.cameraType = CameraType.Preview;
_camera.fieldOfView = 4.5f;
_camera.clearFlags = CameraClearFlags.SolidColor;
_camera.transform.SetParent(cameraPivot);
_camera.cullingMask = 1 << _previewLayer;
cameraPivot.Rotate(Vector3.up, 150, Space.Self);
}
private void CreateRenderTexture()
{
if (_renderTexture)
{
return;
}
_renderTexture = new RenderTexture(300, 300, 30, RenderTextureFormat.ARGB32)
{
antiAliasing = 1
};
}
private void DrawCharacter()
{
_camera.transform.localPosition = new Vector3(0, 1.1f, -36);
_customizableCharacter.Draw(_previewLayer, _camera);
_camera.Render();
}
private static void FindRoot()
{
var anchorAssetGuid = string.Empty;
foreach (var keyword in AssetsPath.BaseMesh.Keywords)
{
var assetGuids = AssetDatabase.FindAssets(keyword);
foreach (var guid in assetGuids)
{
if (AssetDatabase.GUIDToAssetPath(guid).Contains("Meshes"))
{
anchorAssetGuid = guid;
break;
}
}
if (!string.IsNullOrEmpty(anchorAssetGuid))
{
break;
}
}
var anchorAssetPath = AssetDatabase.GUIDToAssetPath(anchorAssetGuid);
var pathParts = anchorAssetPath.Split('/');
var packTitleParts = AssetsPath.PackageName.Split('_');
var rootFound = false;
for (var i = pathParts.Length - 1; i >= 0; i--)
{
if (rootFound)
{
break;
}
foreach (var part in packTitleParts)
{
rootFound = false;
if (!pathParts[i].Contains(part))
{
pathParts[i] = string.Empty;
break;
}
rootFound = true;
}
}
var root = string.Join("/", pathParts.Where(p => !string.IsNullOrEmpty(p)).ToArray()) + "/";
AssetsPath.SetRoot(root);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 09a7b34151da87d46a6e0cff3b379e11
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/CharacterCustomizationWindow.cs
uploadId: 780839

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bf7c23847d84410d81a5e3b60afd39cf
timeCreated: 1733473101

View File

@@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Linq;
using CharacterCustomizationTool.FaceManagement;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.FaceEditor
{
public static class FaceLoader
{
public static void AddFaces(GameObject gameObject)
{
var faceMeshes = AssetLoader.LoadAssets<Mesh>("t:Mesh", AssetsPath.Folder.Faces).ToArray();
var maleFace = FilterBy("Male", faceMeshes);
var femaleFace = FilterBy("Female", faceMeshes);
var groupedMaleFaces = Group(maleFace);
var groupedFemaleFaces = Group(femaleFace);
var skinnedMeshRenderer = gameObject.transform
.Cast<Transform>()
.First(t => t.name.StartsWith("Face"))
.GetComponent<SkinnedMeshRenderer>();
if (skinnedMeshRenderer.sharedMesh)
{
var facePicker = gameObject.AddComponent<FacePicker>();
var nameSections = skinnedMeshRenderer.sharedMesh.name.Split("_");
var groupedFaces = nameSections.First() == "Male" ? groupedMaleFaces : groupedFemaleFaces;
var faces = ChooseFaces(skinnedMeshRenderer.sharedMesh.name, groupedFaces);
facePicker.SetFaces(faces);
}
}
private static Mesh[] ChooseFaces(string faceName, Dictionary<string, Mesh[]> groupedFaces)
{
var faceKey = faceName.Split("_")[3];
var faces = groupedFaces[faceKey];
return faces;
}
private static IEnumerable<Mesh> FilterBy(string keyword, IEnumerable<Mesh> meshes)
{
return meshes.Where(m => m.name.StartsWith(keyword)).ToArray();
}
private static Dictionary<string, Mesh[]> Group(IEnumerable<Mesh> meshes)
{
var groupedMeshes = meshes
.GroupBy(m => m.name.Split("_")[3])
.ToDictionary(g => g.Key, g => g.ToArray());
return groupedMeshes;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9c4ca2ceb1694e368fdc48fb95737e0d
timeCreated: 1733473111
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/FaceEditor/FaceLoader.cs
uploadId: 780839

View File

@@ -0,0 +1,39 @@
using System;
using System.Linq;
using CharacterCustomizationTool.FaceManagement;
using UnityEditor;
namespace CharacterCustomizationTool.Editor.FaceEditor
{
[CustomEditor(typeof(FacePicker))]
public class FacePickerEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var facePicker = (FacePicker)target;
var previousFace = facePicker.ActiveFace;
var availableFaces =
Enum.GetValues(typeof(FaceType))
.Cast<FaceType>()
.Where(facePicker.HasFace)
.ToArray();
var activeFaceIndex = Array.IndexOf(availableFaces, facePicker.ActiveFace);
var newFaceIndex = EditorGUILayout.Popup("Face", activeFaceIndex, availableFaces.Select(f => f.ToString()).ToArray());
var newFace = availableFaces[newFaceIndex];
if (newFace != previousFace)
{
facePicker.PickFace(newFace);
EditorUtility.SetDirty(facePicker.gameObject);
AssetDatabase.SaveAssetIfDirty(facePicker.gameObject);
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d12dd8e2ab416fc47b32a9c0579cfb40
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/FaceEditor/FacePickerEditor.cs
uploadId: 780839

View File

@@ -0,0 +1,23 @@
namespace CharacterCustomizationTool.Editor
{
public enum GroupType
{
Body,
Costumes,
FaceAccessories,
Faces,
Glasses,
Gloves,
Hairstyle,
HairstyleSingle,
Hat,
HatSingle,
Mascots,
Outfit,
Outwear,
Pants,
Shoes,
Shorts,
Socks,
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7b59a73d0010b514bb4dc68df2e34a23
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/GroupType.cs
uploadId: 780839

View File

@@ -0,0 +1,50 @@
using System;
using UnityEditor;
using UnityEngine;
namespace CharacterCustomizationTool.Editor
{
public class LayerMaskUtility
{
public static void CreateLayer(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name), "New layer name string is either null or empty.");
}
var tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
var layerProps = tagManager.FindProperty("layers");
var propCount = layerProps.arraySize;
SerializedProperty firstEmptyProp = null;
for (var i = 0; i < propCount; i++)
{
var layerProp = layerProps.GetArrayElementAtIndex(i);
var stringValue = layerProp.stringValue;
if (stringValue == name)
{
return;
}
if (i < 8 || stringValue != string.Empty)
{
continue;
}
firstEmptyProp ??= layerProp;
}
if (firstEmptyProp == null)
{
Debug.LogError("Maximum limit of " + propCount + " layers exceeded. Layer \"" + name + "\" not created.");
return;
}
firstEmptyProp.stringValue = name;
tagManager.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 496fab0852c0452fad73654ac2a8306d
timeCreated: 1737047512
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/LayerMaskUtility.cs
uploadId: 780839

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0bf47c2abc5e479abe7e9c7250f2f869
timeCreated: 1733383645

View File

@@ -0,0 +1,35 @@
using System;
using UnityEditor;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.MaterialManagement
{
public class MaterialOnDemand
{
private readonly string[] _paths;
private Material _value;
public Material Value => _value ? _value : LoadMaterial();
public MaterialOnDemand(params string[] paths)
{
_paths = paths;
}
private Material LoadMaterial()
{
foreach (var path in _paths)
{
var loadedMaterial = AssetDatabase.LoadAssetAtPath<Material>(path);
if (loadedMaterial != null)
{
return loadedMaterial;
}
}
throw new Exception();
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 64d9492e12b140e5a5d41e01cd21f244
timeCreated: 1733383656
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/MaterialManagement/MaterialOnDemand.cs
uploadId: 780839

View File

@@ -0,0 +1,20 @@
using System.Linq;
namespace CharacterCustomizationTool.Editor.MaterialManagement
{
public static class MaterialPaths
{
private static readonly string[] MainColorNames = { "Material", "Color" };
private static readonly string GlassName = "Glass";
private static readonly string EmissionName = "Emission";
public static readonly string[] MainColorPaths = MainColorNames.Select(GetMaterialPath).ToArray();
public static readonly string GlassPath = GetMaterialPath(GlassName);
public static readonly string EmissionPath = GetMaterialPath(EmissionName);
private static string GetMaterialPath(string materialName)
{
return $"{AssetsPath.Folder.Materials}{materialName}.mat";
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: dcdec3d40fc84864a9f14ccc7367a694
timeCreated: 1733383685
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/MaterialManagement/MaterialPaths.cs
uploadId: 780839

View File

@@ -0,0 +1,15 @@
using UnityEngine;
namespace CharacterCustomizationTool.Editor.MaterialManagement
{
public class MaterialProvider
{
private readonly MaterialOnDemand _mainColor = new(MaterialPaths.MainColorPaths);
private readonly MaterialOnDemand _glass = new(MaterialPaths.GlassPath);
private readonly MaterialOnDemand _emission = new(MaterialPaths.EmissionPath);
public Material MainColor => _mainColor.Value;
public Material Glass => _glass.Value;
public Material Emission => _emission.Value;
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 706da59b74ca42979c0359ece9905274
timeCreated: 1733381019
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/MaterialManagement/MaterialProvider.cs
uploadId: 780839

View File

@@ -0,0 +1,118 @@
using CharacterCustomizationTool.Editor.Character;
using UnityEditor;
using UnityEngine;
namespace CharacterCustomizationTool.Editor
{
public class PartsEditor
{
private const float Width = 150;
private Vector2 _scrollPosition;
public void OnGUI(Rect rect, CustomizableCharacter character)
{
var slots = character.Slots;
using (new GUI.GroupScope(rect))
{
using (var scrollViewScope = new GUILayout.ScrollViewScope(_scrollPosition))
{
_scrollPosition = scrollViewScope.scrollPosition;
using (new GUILayout.HorizontalScope())
{
const int step = 3;
var index = 0;
while (index < slots.Length)
{
using (new GUILayout.VerticalScope(GUILayout.Width(100)))
{
for (var i = index; i < index + step; i++)
{
if (i < slots.Length)
{
RenderPart(character, slots[i]);
}
}
}
index += step;
}
}
}
}
}
private static void RenderPart(CustomizableCharacter character, SlotBase slot)
{
using (new GUILayout.VerticalScope(EditorStyles.helpBox, GUILayout.Width(Width)))
{
GUILayout.Label(slot.Name);
GUILayout.Box(AssetPreview.GetAssetPreview(slot.Preview));
if (CustomizableCharacter.IsAlwaysEnabled(slot.Type))
{
using (new EditorGUI.DisabledScope(true))
{
RenderToggle(character, slot.Type);
}
}
else if (slot.Type == SlotType.FullBody)
{
RenderToggle(character, slot.Type);
}
else
{
using (new EditorGUI.DisabledScope(false))
{
RenderToggle(character, slot.Type);
}
}
using (new EditorGUI.DisabledScope(!slot.IsEnabled))
{
using (new GUILayout.HorizontalScope(EditorStyles.helpBox, GUILayout.Width(Width)))
{
RenderLeftButton(character, slot.Type);
RenderCounter(slot);
RenderRightButton(character, slot.Type);
}
}
}
}
private static void RenderToggle(CustomizableCharacter character, SlotType type)
{
var isToggled = EditorGUILayout.ToggleLeft("Enabled", character.IsToggled(type), GUILayout.Width(100));
character.Toggle(type, isToggled);
}
private static void RenderLeftButton(CustomizableCharacter character, SlotType slotType)
{
if (GUILayout.Button("<"))
{
character.SelectPrevious(slotType);
}
}
private static void RenderRightButton(CustomizableCharacter character, SlotType slotType)
{
if (GUILayout.Button(">"))
{
character.SelectNext(slotType);
}
}
private static void RenderCounter(SlotBase slot)
{
var style = new GUIStyle
{
alignment = TextAnchor.MiddleCenter,
normal =
{
textColor = Color.white
},
fixedWidth = 70,
};
GUILayout.Label($"{slot.SelectedIndex + 1}/{slot.VariantsCount}", style);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 5823a3186511e4043be688c233988ff0
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/PartsEditor.cs
uploadId: 780839

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ccc51c69798f84d438888c8c9eef01e8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
using System;
using System.Linq;
using CharacterCustomizationTool.Editor.Character;
using CharacterCustomizationTool.Editor.Randomizer.Steps;
using CharacterCustomizationTool.Editor.Randomizer.Steps.Impl;
namespace CharacterCustomizationTool.Editor.Randomizer
{
public class RandomCharacterGenerator
{
private readonly IRandomizerStep[] _randomizerSteps =
{
new FaceStep(),
new BodyStep(),
new CostumesStep(),
new MascotsStep(),
new OutfitStep(),
new OutwearStep(),
new PantsStep(),
new ShortsStep(),
new SocksStep(),
new HatStep(),
new HatSingleStep(),
new FaceAccessoriesStep(),
new GlassesStep(),
new ShoesStep(),
new HairstyleSingleStep(),
new HairstyleStep(),
new GlovesStep(),
};
public void Randomize(CustomizableCharacter character)
{
character.ToDefault();
var groups = Enum.GetValues(typeof(GroupType)).Cast<GroupType>().ToArray();
foreach (var step in _randomizerSteps)
{
var variantsCount = character.GetVariantsCountInGroup(step.GroupType);
var stepResult = step.Process(variantsCount, groups);
groups = stepResult.AvailableGroups;
character.PickGroup(step.GroupType, stepResult.Index, stepResult.IsActive);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 90f894f9feef4ac9997c9a681333e648
timeCreated: 1736350992
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/Randomizer/RandomCharacterGenerator.cs
uploadId: 780839

View File

@@ -0,0 +1,16 @@
namespace CharacterCustomizationTool.Editor.Randomizer
{
public class StepResult
{
public int Index { get; }
public bool IsActive { get; }
public GroupType[] AvailableGroups { get; }
public StepResult(int index, bool isActive, GroupType[] availableGroups)
{
Index = index;
IsActive = isActive;
AvailableGroups = availableGroups;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: cd07b1e4f88a4af696f5614472c15f13
timeCreated: 1736972446
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/Randomizer/StepResult.cs
uploadId: 780839

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 13350f8e69d34f0ab019a0b7ce981866
timeCreated: 1736674860

View File

@@ -0,0 +1,9 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps
{
public interface IRandomizerStep
{
GroupType GroupType { get; }
StepResult Process(int count, GroupType[] groups);
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: c471afe9dd44d074f99841183c4cf278
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/Randomizer/Steps/IRandomizerStep.cs
uploadId: 780839

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fe8f5cfcc1874a58b1af97c477b086f4
timeCreated: 1736674865

View File

@@ -0,0 +1,17 @@
using System.Linq;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class BodyStep : IRandomizerStep
{
public GroupType GroupType => GroupType.Body;
public StepResult Process(int count, GroupType[] groups)
{
var newGroups = groups.Where(g => g != GroupType.Body).ToArray();
return new StepResult(Random.Range(0, count), true, newGroups);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: da95423e69334f7e96f7fe9f3db0ef5f
timeCreated: 1736599151
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/Randomizer/Steps/Impl/BodyStep.cs
uploadId: 780839

View File

@@ -0,0 +1,22 @@
using System;
using Random = UnityEngine.Random;
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class CostumesStep : StepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Costumes;
protected override float Probability => .2f;
public override StepResult Process(int count, GroupType[] groups)
{
if (Random.value > Probability)
{
return new StepResult(0, false, RemoveSelf(groups));
}
return new StepResult(Random.Range(0, count), true, Array.Empty<GroupType>());
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f1cd3103d9d741ff9aed903f55545928
timeCreated: 1736674915
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/Randomizer/Steps/Impl/CostumesStep.cs
uploadId: 780839

View File

@@ -0,0 +1,16 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class FaceAccessoriesStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.FaceAccessories;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Glasses,
GroupType.Shoes,
GroupType.HairstyleSingle,
GroupType.Hairstyle,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f44888e8146b4a57b11907b4ef3f6d22
timeCreated: 1736681858
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/Randomizer/Steps/Impl/FaceAccessoriesStep.cs
uploadId: 780839

View File

@@ -0,0 +1,17 @@
using System.Linq;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class FaceStep : IRandomizerStep
{
public GroupType GroupType => GroupType.Faces;
public StepResult Process(int count, GroupType[] groups)
{
var newGroups = groups.Where(g => g != GroupType.Faces).ToArray();
return new StepResult(Random.Range(0, count), true, newGroups);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9d3b7299fb554507b6a7aa4398dd60db
timeCreated: 1736350792
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/Randomizer/Steps/Impl/FaceStep.cs
uploadId: 780839

View File

@@ -0,0 +1,15 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class GlassesStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Glasses;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Shoes,
GroupType.HairstyleSingle,
GroupType.Hairstyle,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 42b88327cc4b4059a9900d7451f2b1ad
timeCreated: 1736681911
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/Randomizer/Steps/Impl/GlassesStep.cs
uploadId: 780839

View File

@@ -0,0 +1,11 @@
using System;
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class GlovesStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Gloves;
protected override GroupType[] CompatibleGroups => Array.Empty<GroupType>();
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 369aa049cb934312955bdfbcbfb0cf6c
timeCreated: 1736682133
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/Randomizer/Steps/Impl/GlovesStep.cs
uploadId: 780839

View File

@@ -0,0 +1,12 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class HairstyleSingleStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.HairstyleSingle;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4dbf3a338f2e4959976c21ad98480d91
timeCreated: 1736682038
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/Randomizer/Steps/Impl/HairstyleSingleStep.cs
uploadId: 780839

View File

@@ -0,0 +1,12 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class HairstyleStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Hairstyle;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: bd5070c46d6e4eba9378623e5ab9b2b0
timeCreated: 1736682092
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/Randomizer/Steps/Impl/HairstyleStep.cs
uploadId: 780839

View File

@@ -0,0 +1,14 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class HatSingleStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.HatSingle;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.FaceAccessories,
GroupType.Shoes,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 7b225042b1974444979dbc9e3040da4a
timeCreated: 1736681763
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/Randomizer/Steps/Impl/HatSingleStep.cs
uploadId: 780839

View File

@@ -0,0 +1,15 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class HatStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Hat;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.FaceAccessories,
GroupType.Glasses,
GroupType.Shoes,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 030380cece0448e394e70c7c7022f2a8
timeCreated: 1736681665
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/Randomizer/Steps/Impl/HatStep.cs
uploadId: 780839

View File

@@ -0,0 +1,17 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class MascotsStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Mascots;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Pants,
GroupType.Shorts,
GroupType.FaceAccessories,
GroupType.Glasses,
GroupType.Shoes,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 793ebe74e68a4bf0afaa3eb68e2387c9
timeCreated: 1736676749
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/Randomizer/Steps/Impl/MascotsStep.cs
uploadId: 780839

View File

@@ -0,0 +1,19 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class OutfitStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Outfit;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Hat,
GroupType.HatSingle,
GroupType.FaceAccessories,
GroupType.Glasses,
GroupType.Shoes,
GroupType.HairstyleSingle,
GroupType.Hairstyle,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a9f1c016b047465b971475eddd6d9e6f
timeCreated: 1736677982
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/Randomizer/Steps/Impl/OutfitStep.cs
uploadId: 780839

View File

@@ -0,0 +1,21 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class OutwearStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Outwear;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Pants,
GroupType.Shorts,
GroupType.Hat,
GroupType.HatSingle,
GroupType.FaceAccessories,
GroupType.Glasses,
GroupType.Shoes,
GroupType.HairstyleSingle,
GroupType.Hairstyle,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 74f9991652aa46348c881d0e7908b073
timeCreated: 1736678464
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/Randomizer/Steps/Impl/OutwearStep.cs
uploadId: 780839

View File

@@ -0,0 +1,19 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class PantsStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Pants;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Hat,
GroupType.HatSingle,
GroupType.FaceAccessories,
GroupType.Glasses,
GroupType.Shoes,
GroupType.HairstyleSingle,
GroupType.Hairstyle,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2967f0c46bdd4c818e3a8a951b2652a2
timeCreated: 1736678855
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/Randomizer/Steps/Impl/PantsStep.cs
uploadId: 780839

View File

@@ -0,0 +1,14 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class ShoesStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Shoes;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.HairstyleSingle,
GroupType.Hairstyle,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 10cfdcedf32c4647a6b2f6c62d9529c4
timeCreated: 1736681964
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/Randomizer/Steps/Impl/ShoesStep.cs
uploadId: 780839

View File

@@ -0,0 +1,39 @@
using System.Linq;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class ShortsStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Shorts;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Hat,
GroupType.HatSingle,
GroupType.FaceAccessories,
GroupType.Glasses,
GroupType.Shoes,
GroupType.HairstyleSingle,
GroupType.Hairstyle,
GroupType.Gloves,
};
public override StepResult Process(int count, GroupType[] groups)
{
var cannotProcess = !groups.Contains(GroupType);
groups = RemoveSelf(groups);
if (cannotProcess || Random.value > Probability)
{
return new StepResult(0, false, groups);
}
var newGroups = groups.Where(g => CompatibleGroups.Contains(g)).ToArray();
var finalGroups = newGroups.ToList();
finalGroups.Add(GroupType.Socks);
return new StepResult(Random.Range(0, count), true, finalGroups.ToArray());
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2b73523352e7483bbe87c1ebc732a1ff
timeCreated: 1736679843
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/Randomizer/Steps/Impl/ShortsStep.cs
uploadId: 780839

View File

@@ -0,0 +1,25 @@
using System.Linq;
using UnityEngine;
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public abstract class SlotStepBase : StepBase, IRandomizerStep
{
protected abstract GroupType[] CompatibleGroups { get; }
public override StepResult Process(int count, GroupType[] groups)
{
var cannotProcess = !groups.Contains(GroupType);
groups = RemoveSelf(groups);
if (cannotProcess || Random.value > Probability)
{
return new StepResult(0, false, groups);
}
var newGroups = groups.Where(g => CompatibleGroups.Contains(g)).ToArray();
return new StepResult(Random.Range(0, count), true, newGroups);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: c680eeb9d4824f80853cbb97cd228aab
timeCreated: 1736678645
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/Randomizer/Steps/Impl/SlotStepBase.cs
uploadId: 780839

View File

@@ -0,0 +1,21 @@
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public class SocksStep : SlotStepBase, IRandomizerStep
{
public override GroupType GroupType => GroupType.Socks;
protected override float Probability => .5f;
protected override GroupType[] CompatibleGroups => new[]
{
GroupType.Hat,
GroupType.HatSingle,
GroupType.FaceAccessories,
GroupType.Glasses,
GroupType.Shoes,
GroupType.HairstyleSingle,
GroupType.Hairstyle,
GroupType.Gloves,
};
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 246406a9e2694ee199d27d33b1a5abd2
timeCreated: 1736681519
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/Randomizer/Steps/Impl/SocksStep.cs
uploadId: 780839

View File

@@ -0,0 +1,18 @@
using System.Linq;
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
{
public abstract class StepBase : IRandomizerStep
{
public abstract GroupType GroupType { get; }
protected virtual float Probability => .35f;
public abstract StepResult Process(int count, GroupType[] groups);
protected GroupType[] RemoveSelf(GroupType[] groups)
{
return groups.Where(g => g != GroupType).ToArray();
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3e2f5ffd08ce455b937d13c7d07ece65
timeCreated: 1736685991
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/Randomizer/Steps/Impl/StepBase.cs
uploadId: 780839

Some files were not shown because too many files have changed in this diff Show More