Genesis Game Client Project Setup

This commit is contained in:
2026-03-13 12:43:28 +09:00
commit af885151b3
832 changed files with 630533 additions and 0 deletions

View File

@@ -0,0 +1,247 @@
using UnityEngine;
using System.Collections.Generic;
namespace Bozo.AnimeCharacters
{
public class BodyShapeModifier : MonoBehaviour
{
private OutfitSystem system;
public string shapeName;
public string sorting;
public bool useScale;
public float scaleValue = 1;
public float xScaleValue = 1;
public float yScaleValue = 1;
public float zScaleValue = 1;
public BodyShapeModifier[] counterScale;
private Vector3 counterValue;
public Dictionary<string, Vector3> counterSources = new Dictionary<string, Vector3>();
public bool useXScale;
public bool useYScale;
public bool useZScale;
public bool linkScaleAxis;
public Vector2 scaleRange = new Vector2(0.5f, 2f);
public bool usePosition;
private Vector3 initalPosition;
private Vector3 initalMirrorPosition;
public float posValue = 0;
public float xPosValue = 0;
public float yPosValue = 0;
public float zPosValue = 0;
public bool useXPos;
public bool useYPos;
public bool useZPos;
public Vector2 posRange = new Vector2(-0.02f, 0.02f);
public bool useRotation;
public float rotation;
public Vector3 rotationAxis;
public Vector2 rotRange = new Vector2(-90f, 90f);
[SerializeField] bool MirrorTransform;
private Transform mirror;
private bool initalized;
private void Awake()
{
}
private void Start()
{
Init();
}
public void Init()
{
if (initalized) return;
system = GetComponentInParent<OutfitSystem>();
initalPosition = transform.localPosition;
if (!system)
{
return;
}
if (MirrorTransform)
{
var boneName = name;
boneName = boneName.Replace("_l", "_r");
var bones = system.GetBones();
mirror = bones[boneName];
initalMirrorPosition = mirror.localPosition;
}
initalized = true;
}
public void SetScale(float x, float y, float z, float v)
{
xScaleValue = x;
yScaleValue = y;
zScaleValue = z;
scaleValue = v;
ApplyScale();
}
public void SetScale(float value)
{
scaleValue = value;
ApplyScale();
}
public void SetPosition(float x, float y, float z)
{
xPosValue = x;
yPosValue = y;
zPosValue = z;
ApplyPosition();
}
public void SetRotation(float value)
{
rotation = value;
ApplyRotation();
}
public void Apply()
{
if (!initalized) Init();
if (usePosition) ApplyPosition();
if (useRotation) ApplyRotation();
if (useScale) ApplyScale();
}
public void ApplyScale()
{
scaleValue = Mathf.Clamp(scaleValue, scaleRange.x, scaleRange.y);
xScaleValue = Mathf.Clamp(xScaleValue, scaleRange.x, scaleRange.y);
yScaleValue = Mathf.Clamp(yScaleValue, scaleRange.x, scaleRange.y);
zScaleValue = Mathf.Clamp(zScaleValue, scaleRange.x, scaleRange.y);
var xSca = 1f;
var ySca = 1f;
var zSca = 1f;
if (linkScaleAxis)
{
if (useXScale) xSca = scaleValue;
if (useYScale) ySca = scaleValue;
if (useZScale) zSca = scaleValue;
}
else
{
if (useXScale) xSca = xScaleValue;
if (useYScale) ySca = yScaleValue;
if (useZScale) zSca = zScaleValue;
}
var scale = new Vector3(xSca, ySca, zSca);
var counter = new Vector3(xSca - 1, ySca - 1, zSca - 1);
counterValue = Vector3.zero;
foreach (var item in counterSources.Values)
{
counterValue += item;
}
transform.localScale = scale - counterValue;
if (mirror) mirror.localScale = scale - counterValue;
foreach (var item in counterScale)
{
if (!item) continue;
item.counterSources[this.name] = counter; item.ApplyScale();
}
}
public void ApplyPosition()
{
xPosValue = Mathf.Clamp(xPosValue, posRange.x, posRange.y);
yPosValue = Mathf.Clamp(yPosValue, posRange.x, posRange.y);
zPosValue = Mathf.Clamp(zPosValue, posRange.x, posRange.y);
var xPos = 0f;
var yPos = 0f;
var zPos = 0f;
if (useXPos) xPos = xPosValue;
if (useYPos) yPos = yPosValue;
if (useZPos) zPos = zPosValue;
var position = new Vector3(xPos, yPos, zPos);
var mirrorPosition = new Vector3(-xPos, yPos, zPos);
transform.localPosition = position + initalPosition;
if (mirror) mirror.localPosition = mirrorPosition + initalMirrorPosition;
}
public void ApplyRotation()
{
rotation = Mathf.Clamp(rotation, rotRange.x, rotRange.y);
var rot = new Vector3(rotation * rotationAxis.x, rotation * rotationAxis.y, rotation * rotationAxis.z);
transform.localRotation = Quaternion.Euler(rot);
if (mirror) mirror.localRotation = Quaternion.Euler(-rot);
}
public BodyModData GetData()
{
var data = new BodyModData();
data.scaleValue = scaleValue;
data.scale = new Vector3(xScaleValue, yScaleValue, zScaleValue);
data.posValue = posValue;
data.position = new Vector3(xPosValue, yPosValue, zPosValue);
data.rotation = rotation;
return data;
}
public void SetData(BodyModData data)
{
scaleValue = data.scaleValue;
xScaleValue = data.scale.x;
yScaleValue = data.scale.y;
zScaleValue = data.scale.z;
posValue = data.posValue;
xPosValue = data.position.x;
yPosValue = data.position.y;
zPosValue = data.position.z;
rotation = data.rotation;
Apply();
}
}
[System.Serializable]
public class BodyModData
{
public float scaleValue = 1;
public Vector3 scale;
public float posValue = 1;
public Vector3 position;
public float rotation;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8039adc7b05144b4d913dc2c1c09d964

View File

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

View File

@@ -0,0 +1,339 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using System.Threading.Tasks;
namespace Bozo.AnimeCharacters
{
public static class BMAC_SaveSystem
{
public static string filePath = Application.persistentDataPath + "/BoZo_ModularAnimeCharacters/CharacterSaves";
public static string iconFilePath = Application.persistentDataPath + "/BoZo_ModularAnimeCharacters/CharacterSaves/Icons";
public static string assetPath = "Assets/BoZo_ModularAnimeCharacters/CharacterSaves/Resources/";
public static string iconAssetPath = "Assets/BoZo_ModularAnimeCharacters/CharacterSaves/Icons/";
public static void SaveCharacter(OutfitSystem outfitSystem, string saveName, Texture2D icon = null)
{
var data = GetCharacterData(outfitSystem);
data.characterName = saveName;
#if UNITY_EDITOR
var CharacterSave = ScriptableObject.CreateInstance<CharacterObject>();
CharacterSave.data = data;
CharacterSave.icon = icon;
AssetDatabase.CreateAsset(CharacterSave, assetPath + "/" + saveName + ".asset");
AssetDatabase.Refresh();
#endif
string saveData = JsonUtility.ToJson(data);
System.IO.File.WriteAllText(filePath + "/" + saveName + ".json", saveData);
Debug.Log("Character Saved:" + filePath + "/" + saveName + ".json");
}
public static CharacterData GetCharacterData(OutfitSystem outfitSystem)
{
if (outfitSystem.mergedMode) return outfitSystem.data;
var data = new CharacterData();
//Saving BlendShapes
var bodyShapeValues = outfitSystem.GetBodyShapeValues();
data.bodyIDs = bodyShapeValues.Keys.ToList();
data.bodyShapes = bodyShapeValues.Values.ToList();
var faceShapeValues = outfitSystem.GetFaceShapeValues();
data.faceIDs = faceShapeValues.Keys.ToList();
data.faceShapes = faceShapeValues.Values.ToList();
//Saving Body Mods
var modData = new List<BodyModData>();
var modKeys = outfitSystem.bodyModifiers.Keys.ToList();
for (int i = 0; i < modKeys.Count; i++)
{
var mod = outfitSystem.bodyModifiers[modKeys[i]].GetData();
modData.Add(mod);
}
data.bodyMods = modData;
data.bodyModsKeys = modKeys;
//Saving Outfits
var outfits = outfitSystem.GetOutfits();
var outfitDataList = new List<OutfitData>();
for (int i = 0; i < outfits.Count; i++)
{
if (outfits[i] == null) continue;
outfitDataList.Add(outfits[i].GetOutfitData());
}
data.stance = outfitSystem.stance;
data.outfitDatas = outfitDataList;
return data;
}
public static async Task LoadCharacter(OutfitSystem outfitSystem, CharacterData characterObject = null, bool manualShapeApply = false, bool async = false)
{
CharacterData loadData = characterObject;
//Loading Outfits
bool hasBody = false;
List<Outfit> outfits = new List<Outfit>();
if (async)
{
outfits = await LoadOutfits(loadData.outfitDatas);
}
else
{
foreach (var item in loadData.outfitDatas)
{
outfits.Add(Resources.Load<Outfit>(item.outfit));
}
}
outfitSystem.RemoveAllOutfits();
for (int i = 0; i < loadData.outfitDatas.Count; i++)
{
var outfitData = loadData.outfitDatas[i];
var outfit = outfits[i];
if (outfit == null)
{
Debug.LogWarning("Outfit Path: " + outfitData.outfit + " returns null make sure Prefab is named correctly");
continue;
}
//Check If Outfit is the same
var inst = outfitSystem.InstantiateOutfit(outfit);
//Checking For Old Data
if (outfit.Type.name == "Body") hasBody = true;
inst.Attach();
if (inst.customShader)
{
inst.SetSwatch(outfitData.swatch);
inst.SetColor(outfitData.color);
}
else
{
for (int c = 0; c < 9; c++)
{
if (outfitData.colors.Count > c)
{
inst.SetColor(outfitData.colors[c], c + 1);
}
if(c + 1 <= 2 && outfitData.decal != "")
{
inst.SetDecalColor(outfitData.decalColors[c], c + 1);
}
if (c + 1 <= 2 && outfitData.pattern != "")
{
inst.SetPatternColor(outfitData.patternColors[c], c + 1);
}
}
var decal = Resources.Load<Texture>(outfitData.decal);
inst.SetDecal(decal);
inst.SetDecalSize(outfitData.decalScale);
var pattern = Resources.Load<Texture>(outfitData.pattern);
inst.SetPattern(pattern);
inst.SetPatternSize(outfitData.patternScale);
}
}
//LEGACY Loading Body
if(!hasBody)
{
var body = outfitSystem.GetOutfit("Body");
if(body == null)
{
var bodyPrefab = Resources.Load<Outfit>("Body/Body_BasicBody");
body = outfitSystem.InstantiateOutfit(bodyPrefab);
}
for (int i = 0; i < loadData.bodyData.colors.Count; i++)
{
body.SetColor(loadData.bodyData.colors[i], i + 1);
}
var bodyDecal = Resources.Load<Texture>(loadData.bodyData.decal);
body.SetDecal(bodyDecal);
for (int i = 0; i < loadData.bodyData.decalColors.Count; i++)
{
body.SetDecalColor(loadData.bodyData.decalColors[i], i + 1);
}
var bodyPattern = Resources.Load<Texture>(loadData.bodyData.pattern);
body.SetPattern(bodyPattern);
for (int i = 0; i < loadData.bodyData.patternColors.Count; i++)
{
body.SetPatternColor(loadData.bodyData.patternColors[i], i + 1);
}
}
//Loading Body Morphs
for (int i = 0; i < loadData.bodyIDs.Count; i++)
{
outfitSystem.SetShape(loadData.bodyIDs[i], loadData.bodyShapes[i]);
}
for (int i = 0; i < loadData.faceIDs.Count; i++)
{
outfitSystem.SetShape(loadData.faceIDs[i], loadData.faceShapes[i]);
}
if(!manualShapeApply) LoadBodyMods(outfitSystem, loadData);
outfitSystem.animator.Rebind();
outfitSystem.SetStance(loadData.stance);
}
public static void LoadBodyMods(OutfitSystem outfitSystem, CharacterData loadData)
{
for (int i = 0; i < loadData.bodyModsKeys.Count; i++)
{
outfitSystem.bodyModifiers[loadData.bodyModsKeys[i]].SetData(loadData.bodyMods[i]);
}
}
public static CharacterData GetDataFromID(string saveName)
{
CharacterData loadData;
Debug.Log("Attempted Load at: " + filePath + "/" + saveName + ".json");
if (!System.IO.File.Exists(filePath + "/" + saveName + ".json"))
{
Debug.LogWarning($"Save ID: {saveName} does not exist. Make sure input matches an existing Save");
return null;
}
else
{
string data = System.IO.File.ReadAllText(filePath + "/" + saveName + ".json");
loadData = JsonUtility.FromJson<CharacterData>(data);
return loadData;
}
}
public static string GetJsonFromID(string saveName)
{
Debug.Log("Attempted Load at: " + filePath + "/" + saveName + ".json");
if (!System.IO.File.Exists(filePath + "/" + saveName + ".json"))
{
Debug.LogWarning($"Save ID: {saveName} does not exist. Make sure input matches an existing Save");
return null;
}
else
{
string data = System.IO.File.ReadAllText(filePath + "/" + saveName + ".json");
return data;
}
}
public static async Task<List<Outfit>> LoadOutfits(List<OutfitData> outfitDatas)
{
var loadTasks = outfitDatas.Select(data => LoadResourceAsync<Outfit>(data.outfit));
return (await Task.WhenAll(loadTasks)).ToList();
}
public static async Task<T> LoadResourceAsync<T>(string path) where T : UnityEngine.Object
{
ResourceRequest request = Resources.LoadAsync<T>(path);
var tcs = new TaskCompletionSource<T>();
request.completed += operation =>
{
if (request.asset == null)
{
tcs.SetResult(null);
}
else if (request.asset is not T result)
{
tcs.SetResult(null);
}
else
{
tcs.SetResult(result);
}
};
return await tcs.Task;
}
public static void DeleteCharacter(string characterName)
{
System.IO.File.Delete(filePath + "/" + characterName + ".json");
System.IO.File.Delete(iconFilePath + "/" + characterName + ".png");
System.IO.File.Delete(assetPath + "/" + characterName + ".asset");
System.IO.File.Delete(assetPath + "/" + characterName + ".meta");
System.IO.File.Delete(iconAssetPath + characterName + ".png");
System.IO.File.Delete(iconAssetPath + characterName + ".meta");
#if UNITY_EDITOR
AssetDatabase.Refresh();
#endif
}
}
[System.Serializable]
public class CharacterData
{
public string characterName;
public List<string> bodyIDs;
public List<float> bodyShapes;
public List<string> faceIDs;
public List<float> faceShapes;
public List<string> bodyModsKeys;
public List<BodyModData> bodyMods;
public List<OutfitData> outfitDatas;
public OutfitData bodyData;
public float stance;
}
[System.Serializable]
public class OutfitData
{
public string outfit;
public List<Color> colors;
public string decal;
public List<Color> decalColors;
public Vector4 decalScale;
public string pattern;
public List<Color> patternColors;
public Vector4 patternScale;
//Custom Shader Data
public Color color = Color.white;
public int swatch;
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: b719335614062204d9ab42ec5bfab351
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/BMAC_SaveSystem.cs
uploadId: 853356

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 64cef876055435e43aba052093527416
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/BoZoCharacterOptimizer.cs
uploadId: 853356

View File

@@ -0,0 +1,37 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class BoZo_Links : MonoBehaviour
{
private void Awake()
{
#if !UNITY_EDITOR
Destroy(this.gameObject);
#endif
}
public void Documentation()
{
Application.OpenURL("https://docs.google.com/document/d/1kf1KGT-OqV3Ecvnej0mpmgIOkc-_e7UJp-BkGuZfuN4/edit?usp=sharing");
}
public void Discord()
{
Application.OpenURL("https://discord.gg/UCbRjUy7m7");
}
public void Twitter()
{
}
public void Youtube()
{
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: bf7b6117bf8d6a6489dcc7b01c90a2be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/BoZo_Links.cs
uploadId: 853356

View File

@@ -0,0 +1,117 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
namespace Bozo.AnimeCharacters
{
public class BodyShapeSliders : MonoBehaviour
{
private OutfitSystem system;
private BodyShapeModifier bodyShape;
[SerializeField] TMP_Text title;
[SerializeField] Transform scaleContainer;
[SerializeField] Slider scaleSlider;
[SerializeField] Slider xScaleSlider;
[SerializeField] Slider yScaleSlider;
[SerializeField] Slider zScaleSlider;
[SerializeField] Transform positionContainer;
[SerializeField] Slider xPositionSlider;
[SerializeField] Slider yPositionSlider;
[SerializeField] Slider zPositionSlider;
[SerializeField] Transform rotationContainer;
[SerializeField] Slider rotationSlider;
private void Start()
{
if(system != null && bodyShape != null)
{
Init(system, bodyShape);
}
}
public void Init(OutfitSystem system, BodyShapeModifier mod)
{
this.system = system;
bodyShape = mod;
title.text = mod.shapeName;
if (bodyShape.useScale)
{
if (bodyShape.linkScaleAxis)
{
xScaleSlider.transform.parent.gameObject.SetActive(false);
yScaleSlider.transform.parent.gameObject.SetActive(false);
zScaleSlider.transform.parent.gameObject.SetActive(false);
}
else
{
if (!bodyShape.useXScale) xScaleSlider.transform.parent.gameObject.SetActive(false);
if (!bodyShape.useYScale) yScaleSlider.transform.parent.gameObject.SetActive(false);
if (!bodyShape.useZScale) zScaleSlider.transform.parent.gameObject.SetActive(false);
scaleSlider.transform.parent.gameObject.SetActive(false);
scaleSlider.onValueChanged.AddListener(SetScale);
}
scaleSlider.onValueChanged.AddListener(SetScale);
xScaleSlider.onValueChanged.AddListener(SetScale);
yScaleSlider.onValueChanged.AddListener(SetScale);
zScaleSlider.onValueChanged.AddListener(SetScale);
scaleSlider.minValue = bodyShape.scaleRange.x; scaleSlider.maxValue = bodyShape.scaleRange.y;
xScaleSlider.minValue = bodyShape.scaleRange.x; xScaleSlider.maxValue = bodyShape.scaleRange.y;
yScaleSlider.minValue = bodyShape.scaleRange.x; yScaleSlider.maxValue = bodyShape.scaleRange.y;
zScaleSlider.minValue = bodyShape.scaleRange.x; zScaleSlider.maxValue = bodyShape.scaleRange.y;
}
else
{
scaleContainer.gameObject.SetActive(false);
}
if (bodyShape.usePosition)
{
if (!bodyShape.useXPos) xPositionSlider.transform.parent.gameObject.SetActive(false);
if (!bodyShape.useYPos) yPositionSlider.transform.parent.gameObject.SetActive(false);
if (!bodyShape.useZPos) zPositionSlider.transform.parent.gameObject.SetActive(false);
xPositionSlider.minValue = bodyShape.posRange.x; xPositionSlider.maxValue = bodyShape.posRange.y;
yPositionSlider.minValue = bodyShape.posRange.x; yPositionSlider.maxValue = bodyShape.posRange.y;
zPositionSlider.minValue = bodyShape.posRange.x; zPositionSlider.maxValue = bodyShape.posRange.y;
xPositionSlider.onValueChanged.AddListener(SetPosition);
yPositionSlider.onValueChanged.AddListener(SetPosition);
zPositionSlider.onValueChanged.AddListener(SetPosition);
}
else
{
positionContainer.gameObject.SetActive(false);
}
if (bodyShape.useRotation)
{
rotationSlider.onValueChanged.AddListener(SetRotation);
rotationSlider.minValue = bodyShape.rotRange.x; rotationSlider.maxValue = bodyShape.rotRange.y;
}
else
{
rotationContainer.gameObject.SetActive(false);
}
}
public void SetScale(float v)
{
bodyShape.SetScale(xScaleSlider.value, yScaleSlider.value, zScaleSlider.value, scaleSlider.value);
}
public void SetPosition(float v)
{
bodyShape.SetPosition(xPositionSlider.value, yPositionSlider.value, zPositionSlider.value);
}
public void SetRotation(float v)
{
bodyShape.SetRotation(rotationSlider.value);
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5e1babcebe207f94b9aa4a53a2626694
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/BodyShapeSliders.cs
uploadId: 853356

View File

@@ -0,0 +1,99 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Bozo.AnimeCharacters
{
public class CameraController : MonoBehaviour
{
Camera cam;
float position;
public float scrollSpeed;
public Transform startPosition;
public Transform endPosition;
public Vector2 fov;
public Slider slider;
public float tweenSpeed;
float tweenTimer;
float currentPosition;
float targetPosition;
[SerializeField] CameraPositions[] cameraPositions;
Dictionary<OutfitType, CameraPositions> camPos = new Dictionary<OutfitType, CameraPositions>();
private void Awake()
{
cam = Camera.main;
foreach (var item in cameraPositions)
{
camPos.Add(item.type, item);
}
}
private void Update()
{
if (Input.GetAxis("Mouse ScrollWheel") > 0f) // forward
{
position += scrollSpeed;
tweenTimer = -1;
}
else if (Input.GetAxis("Mouse ScrollWheel") < 0f) // backwards
{
position -= scrollSpeed;
tweenTimer = -1;
}
slider.value = position;
position = Mathf.Clamp(position, 0, 1);
if (tweenTimer >= 0)
{
position = Mathf.Lerp(targetPosition, currentPosition, tweenTimer);
tweenTimer -= Time.deltaTime * tweenSpeed;
}
cam.transform.position = Vector3.Lerp(startPosition.position, endPosition.position, position);
cam.transform.rotation = Quaternion.Lerp(startPosition.rotation, endPosition.rotation, position);
cam.fieldOfView = Mathf.Lerp(fov.x, fov.y, position);
}
public void SetPosition(float value)
{
position = value;
}
public void tweenPosition(float value)
{
tweenTimer = 1;
targetPosition = value;
currentPosition = position;
}
public void TweenPosition(OutfitType type)
{
CameraPositions settings = null;
if(!camPos.TryGetValue(type, out settings)) { settings = cameraPositions[0]; }
startPosition = settings.ZoomOutPos;
endPosition = settings.ZoomInPos;
fov.x = settings.fovOut;
fov.y = settings.fovIn;
tweenTimer = 1;
targetPosition = settings.startingPosition;
currentPosition = position;
}
[System.Serializable]
private class CameraPositions
{
public OutfitType type;
public Transform ZoomOutPos;
public Transform ZoomInPos;
public float fovOut;
public float fovIn;
public float startingPosition;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8de4c66bd7f475d4faab94d46d62a3f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/CameraController.cs
uploadId: 853356

View File

@@ -0,0 +1,471 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Collections;
using TMPro;
using System.Linq;
namespace Bozo.AnimeCharacters
{
public class CharacterCreator : MonoBehaviour
{
[Header("Creator Dependencies")]
public OutfitSystem character;
[SerializeField] ColorPickerControl colorPickerControl;
[SerializeField] CharacterSpinner Spinner;
[SerializeField] Camera iconCamera;
[SerializeField] RenderTexture iconTexture;
public OutfitType[] outfitTypes;
[Header("Outfit Dependencies")]
private Dictionary<string, Outfit> OutfitDataBase = new Dictionary<string, Outfit>();
[SerializeField] OutfitSelector outfitSelectorObject;
private List<OutfitSelector> outfitSelectors = new List<OutfitSelector>();
[SerializeField] Transform outfitContainer;
[Header("Texture Dependencies")]
[SerializeField] TextureSelector textureSelectorObject;
private List<TextureSelector> textureSelectors = new List<TextureSelector>();
[SerializeField] Transform decalContainer;
[SerializeField] Transform patternContainer;
[Header("BodyShape Dependencies")]
[SerializeField] BlendSlider blendSliderObject;
private List<BlendSlider> blendSliders = new List<BlendSlider>();
private List<BlendSlider> faceBlendSliders = new List<BlendSlider>();
[SerializeField] BodyShapeSliders modSliderObject;
private List<BodyShapeSliders> ModSliders = new List<BodyShapeSliders>();
[SerializeField] Transform bodyShapeContainer;
[SerializeField] Transform bodyModContainer;
[SerializeField] Transform faceShapeContainer;
[SerializeField] Transform faceModContainer;
[SerializeField] GameObject currentPage;
private GameObject previousPage;
private Dictionary<string, List<GameObject>> outfits = new Dictionary<string, List<GameObject>>();
private List<TexturePackage> textures = new List<TexturePackage>();
[Header("Save Dependencies")]
[SerializeField] SaveSelector saveSelector;
[SerializeField] Dictionary<string, SaveSelector> saveSlots = new Dictionary<string, SaveSelector>();
[SerializeField] Transform saveContainer;
[SerializeField] GameObject DeleteConfirmWindow;
[SerializeField] TMP_Text loadedCharacterNameText;
[SerializeField] TMP_Text DeleteCharacterNameText;
private OutfitType type;
[Header("Save Options")]
public TMP_InputField CharacterName;
private void Awake()
{
outfits.Clear();
OutfitDataBase.Clear();
var ob = Resources.LoadAll<Outfit>("");
var textureObjects = Resources.LoadAll<TexturePackage>("");
foreach (var item in ob)
{
if (!item.showCharacterCreator) continue;
OutfitDataBase.Add(item.name, item.GetComponent<Outfit>());
}
foreach (var item in textureObjects)
{
textures.Add(item.GetComponent<TexturePackage>());
}
GenerateOutfitSelection();
GenerateTextureSelection();
}
private void OnEnable()
{
character.OnOutfitChanged += OnOutfitUpdate;
character.OnRigChanged += OnRigUpdate;
}
private void OnDisable()
{
character.OnOutfitChanged -= OnOutfitUpdate;
character.OnRigChanged -= OnRigUpdate;
}
public void Start()
{
GetBodyBlends();
GetFaceBlends();
GetBodyMods();
SwitchCatagory("Top");
UpdateCharacterSaves();
}
public void GenerateOutfitSelection()
{
var outfits = OutfitDataBase.Values.ToArray();
foreach (var item in outfits)
{
var selector = Instantiate(outfitSelectorObject, outfitContainer);
selector.Init(item, this);
outfitSelectors.Add(selector);
}
}
public void GenerateTextureSelection()
{
foreach (var item in textures)
{
Transform container = null;
if (item.type == TextureType.Decal) container = decalContainer;
if (item.type == TextureType.Pattern) container = patternContainer;
var selector = Instantiate(textureSelectorObject, container);
selector.Init(item, this);
textureSelectors.Add(selector);
}
}
public void GetBodyBlends()
{
for (int i = 0; i < blendSliders.Count; i++)
{
Destroy(blendSliders[i].gameObject);
}
blendSliders.Clear();
var shapes = character.GetShapes();
foreach (var item in shapes)
{
var blendSlider = Instantiate(blendSliderObject, bodyShapeContainer);
blendSlider.Init(character, item);
blendSliders.Add(blendSlider);
}
}
public void GetFaceBlends()
{
for (int i = 0; i < faceBlendSliders.Count; i++)
{
Destroy(faceBlendSliders[i].gameObject);
}
faceBlendSliders.Clear();
var shapes = character.GetFaceShapes();
foreach (var item in shapes)
{
var blendSlider = Instantiate(blendSliderObject, faceShapeContainer);
blendSlider.Init(character, item);
faceBlendSliders.Add(blendSlider);
}
}
public void GetBodyMods()
{
var mods = character.GetMods().Values.ToList();
for (int i = 0; i < ModSliders.Count; i++)
{
Destroy(ModSliders[i].gameObject);
}
ModSliders.Clear();
var container = bodyShapeContainer;
foreach (var item in mods)
{
if (item.sorting == "Head") container = faceModContainer;
else container = bodyModContainer;
var blendSlider = Instantiate(modSliderObject, container);
blendSlider.Init(character, item);
ModSliders.Add(blendSlider);
}
}
public void UpdateCharacterSaves()
{
var saves = saveSlots.Values.ToArray();
foreach (var item in saves)
{
Destroy(item.gameObject);
}
saveSlots.Clear();
if (!System.IO.Directory.Exists(Application.persistentDataPath + "/BoZo_ModularAnimeCharacters"))
{
System.IO.Directory.CreateDirectory(Application.persistentDataPath + "/BoZo_ModularAnimeCharacters/CharacterSaves/Icons/");
print("Created Save JSON save Location At: " + Application.persistentDataPath + "/BoZo_ModularAnimeCharacters");
}
string path = BMAC_SaveSystem.filePath;
string[] jsonFiles = System.IO.Directory.GetFiles(path, "*.json");
string[] icons = System.IO.Directory.GetFiles(path + "/Icons", "*.png");
for (int i = 0; i < jsonFiles.Length; i++)
{
var json = System.IO.File.ReadAllText(jsonFiles[i]);
var data = JsonUtility.FromJson<CharacterData>(json);
var image = System.IO.File.ReadAllBytes(icons[i]);
var texture = new Texture2D(2, 2);
Sprite icon = null;
if (texture.LoadImage(image))
{
icon = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
}
var selector = Instantiate(saveSelector, saveContainer);
selector.Init(data, icon, this);
saveSlots.Add(data.characterName, selector);
}
var saveObjects = Resources.LoadAll<CharacterObject>("");
for (int i = 0; i < saveObjects.Length; i++)
{
var ob = saveObjects[i];
if (saveSlots.ContainsKey(ob.data.characterName))
{
continue;
}
else
{
var selector = Instantiate(saveSelector, saveContainer);
Sprite icon = null;
if(ob.icon != null)
{
icon = Sprite.Create(ob.icon, new Rect(0, 0, ob.icon.width, ob.icon.height), new Vector2(0.5f, 0.5f));
}
selector.Init(ob.data, icon, this);
saveSlots.Add(ob.data.characterName, selector);
}
}
}
public void OpenPage(GameObject page)
{
currentPage.SetActive(false);
previousPage = currentPage;
currentPage = page;
currentPage.SetActive(true);
}
public void BackPage()
{
currentPage.SetActive(false);
currentPage = previousPage;
currentPage.SetActive(true);
colorPickerControl.RemoveObject();
}
public void SetOutfit(Outfit outfit)
{
var inst = Instantiate(outfit, character.transform);
SetColorPickerObject(inst);
SwitchTextureCatagory(outfit.TextureCatagory);
type = outfit.Type;
// var type = (OutfitType)Enum.Parse(typeof(OutfitType), catagory);
}
public void OnOutfitUpdate(Outfit outfit)
{
if (outfit == null) return;
if(outfit.Type.name == "Head")
{
GetFaceBlends();
}
if (outfit.Type.name == "Body")
{
GetBodyBlends();
}
}
public void OnRigUpdate(SkinnedMeshRenderer rig)
{
//GetBodyBlends();
GetBodyMods();
}
public void SetOutfitDecal(Texture texture)
{
if (!colorPickerControl.colorObject) return;
colorPickerControl.colorObject.SetDecal(texture);
}
public void SetOutfitPattern(Texture texture)
{
if (!colorPickerControl.colorObject) return;
colorPickerControl.colorObject.SetPattern(texture);
}
public void RemoveOutfit()
{
if (type == null) return;
character.RemoveOutfit(type, true);
colorPickerControl.RemoveObject();
}
public void RemoveOutfitDecal()
{
if (!colorPickerControl.colorObject) return;
colorPickerControl.colorObject.SetDecal(null);
}
public void RemoveOutfitPattern()
{
if (!colorPickerControl.colorObject) return;
colorPickerControl.colorObject.SetPattern(null);
}
public void SwitchCatagory(string catagory)
{
foreach (var item in outfitSelectors)
{
item.SetVisable(catagory);
}
var outfit = character.GetOutfit(catagory);
SetColorPickerObject(outfit);
if (outfit == null) return;
SwitchTextureCatagory(outfit.TextureCatagory);
type = outfit.Type;
}
public void SwitchTextureCatagory(string catagory)
{
if (catagory == "")
{
catagory = "Outfit";
}
foreach (var item in textureSelectors)
{
item.SetVisable(catagory);
}
}
public void SetColorPickerObject(string type)
{
var outfit = character.GetOutfit(type);
colorPickerControl.ChangeObject(outfit);
}
public void SetColorPickerObject(Outfit outfit)
{
colorPickerControl.ChangeObject(outfit);
}
public void ReplaceCharacter(OutfitSystem character)
{
Destroy(this.character.gameObject);
this.character = character;
Spinner.SetCharacter(character.transform);
}
public void GetCurrentCatagory()
{
if (type == null) return;
SwitchCatagory(type.name);
}
public void CopyColor(string copyTo)
{
var copyOutfit = character.GetOutfit((OutfitType)Enum.Parse(typeof(OutfitType), copyTo));
colorPickerControl.CopyColor(copyOutfit);
}
public void ToggleWalk(bool value)
{
character.animator.SetBool("isWalk", value);
}
public void SaveCharacter()
{
StartCoroutine(Save());
}
public Outfit GetOutfit(string outfitName)
{
return OutfitDataBase[outfitName];
}
[ContextMenu("Save")]
private IEnumerator Save()
{
yield return new WaitForEndOfFrame();
if(CharacterName.text.Length == 0)
{
Debug.LogWarning("Please enter in a name with at least one letter");
yield break;
}
RenderTexture.active = iconTexture;
Texture2D icon = new Texture2D(iconTexture.width, iconTexture.height, TextureFormat.RGBA32, false);
Rect rect = new Rect(new Rect(0, 0, iconTexture.width, iconTexture.height));
icon.ReadPixels(rect, 0,0);
icon.Apply();
byte[] bytes = icon.EncodeToPNG();
Texture2D characterIcon = null;
#if UNITY_EDITOR
System.IO.File.WriteAllBytes(Application.dataPath + "/BoZo_ModularAnimeCharacters/CharacterSaves/Icons/" + CharacterName.text + ".png", bytes);
AssetDatabase.Refresh();
characterIcon = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/BoZo_ModularAnimeCharacters/CharacterSaves/Icons/" + CharacterName.text + ".png");
TextureImporter importer = AssetImporter.GetAtPath("Assets/BoZo_ModularAnimeCharacters/CharacterSaves/Icons/" + CharacterName.text + ".png") as TextureImporter;
if (importer != null)
{
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Single;
importer.SaveAndReimport();
}
#endif
if(!System.IO.Directory.Exists(Application.persistentDataPath + "/BoZo_ModularAnimeCharacters/CharacterSaves/Icons/"))
{
System.IO.Directory.CreateDirectory(Application.persistentDataPath + "/BoZo_ModularAnimeCharacters/CharacterSaves/Icons/");
}
System.IO.File.WriteAllBytes(Application.persistentDataPath + "/BoZo_ModularAnimeCharacters/CharacterSaves/Icons/" + CharacterName.text + ".png", bytes);
BMAC_SaveSystem.SaveCharacter(character, CharacterName.text, characterIcon);
UpdateCharacterSaves();
}
public void LoadCharacter(CharacterData data)
{
loadedCharacterNameText.text = data.characterName;
_ = BMAC_SaveSystem.LoadCharacter(character, data, false, true);
}
public void DeleteCharacter()
{
if (loadedCharacterNameText.text == "") return;
DeleteCharacterNameText.text = "Delete: " + loadedCharacterNameText.text;
DeleteConfirmWindow.SetActive(true);
}
public void ConfirmDelete()
{
BMAC_SaveSystem.DeleteCharacter(loadedCharacterNameText.text);
loadedCharacterNameText.text = "";
UpdateCharacterSaves();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: a7ff0168c5a8aae45abec3f8e5dc6957
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/CharacterCreator.cs
uploadId: 853356

View File

@@ -0,0 +1,67 @@
using UnityEngine;
using UnityEngine.EventSystems;
namespace Bozo.AnimeCharacters
{
public class CharacterSpinner : MonoBehaviour, IDragHandler, IPointerClickHandler
{
public float spinDir;
public Transform character;
private Animator anim;
float dizzyTimer = 1;
bool spinning;
public void SetCharacter(Transform character)
{
this.character = character;
anim = character.GetComponentInChildren<Animator>();
}
public void OnDrag(PointerEventData eventData)
{
spinning = true;
}
public void OnPointerClick(PointerEventData eventData)
{
spinning = true;
}
private void Start()
{
SetCharacter(character);
}
private void Update()
{
if (spinning)
{
spinDir = -Input.GetAxis("Mouse X") * 5;
dizzyTimer = 0.5f;
}
if (Input.GetMouseButtonUp(0))
{
spinning = false;
}
character.Rotate(0, spinDir, 0);
spinDir = Mathf.Lerp(spinDir, 0, Time.deltaTime);
dizzyTimer -= Time.deltaTime;
if (dizzyTimer <= 0)
{
if (spinDir >= 5 || spinDir <= -5)
{
anim.SetBool("Dizzy", true);
}
else
{
anim.SetBool("Dizzy", false);
}
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 52defae866fd958429021f2e841897ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/CharacterSpinner.cs
uploadId: 853356

View File

@@ -0,0 +1,575 @@
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Bozo.AnimeCharacters
{
public class ColorPickerControl : MonoBehaviour
{
[Header("Picker Dependencies")]
public CharacterCreator creator;
public SVImageControl svContoller;
[Header("Picker")]
public float currentHue;
public float currentSat;
public float currentVal;
public float currentColor;
[SerializeField] private RawImage hueImage;
[SerializeField] private RawImage satValImage;
[SerializeField] private RawImage outputImage;
[SerializeField] private Slider hueSlider;
private Texture2D hueTexture;
private Texture2D svTexture;
private Texture2D outputTexture;
public OutfitBase colorObject;
public OutfitType outfitType;
public Material colorMaterial;
public int MaterialSlot;
[Header("Editor")]
[SerializeField] OutfitSystem outfitSystem;
[SerializeField] TMP_Text objectName;
[SerializeField] TMP_Text channelText;
[SerializeField] Image Swatch;
[SerializeField] TMP_Text CopyCatagoryText;
public List<string> outfitTypes = new List<string>();
private int copyIndex;
[SerializeField] TextureType mode = TextureType.Base;
[SerializeField] int currentChannel;
[SerializeField] int maxChannel;
[SerializeField] string[] channelNames;
[Header("Decal Editor")]
[SerializeField] GameObject decalContainer;
[SerializeField] Slider DecalXSlider;
[SerializeField] Slider DecalYSlider;
private Vector2 outfitDefaultDecalSize;
[Header("Pattern Editor")]
[SerializeField] GameObject patternContainer;
[SerializeField] Slider patternXSlider;
[SerializeField] Slider patternYSlider;
private Vector2 outfitDefaultPatternSize;
[Header("Swatch Editor")]
[SerializeField] GameObject swatchParentContainer;
[SerializeField] Transform swatchContainer;
[SerializeField] SwatchSelector swatchSelectorObject;
private List<SwatchSelector> swatchSelectors = new List<SwatchSelector>();
[Header("AdvancedEditor")]
[SerializeField] TMP_Text hexValueTex;
[SerializeField] List<Color> HeldColors = new List<Color>();
[SerializeField] bool maintainColors;
[SerializeField] Toggle maintainColorsToggle;
[SerializeField] TMP_InputField inputR;
[SerializeField] TMP_InputField inputG;
[SerializeField] TMP_InputField inputB;
[SerializeField] TMP_InputField inputH;
[SerializeField] TMP_InputField inputS;
[SerializeField] TMP_InputField inputV;
private Dictionary<OutfitType, OutfitPickerSettings> outfitPickerSettings = new Dictionary<OutfitType, OutfitPickerSettings>();
private void Awake()
{
CreateHueImage();
CreateSVImage();
CreateOutputImage();
UpdateOutputImage();
foreach (var type in creator.outfitTypes)
{
outfitTypes.Add(type.name);
}
CopyCatagoryText.text = outfitTypes[0];
if (colorObject == null) gameObject.SetActive(false);
}
private void CreateHueImage()
{
hueTexture = new Texture2D(1, 16);
hueTexture.wrapMode = TextureWrapMode.Clamp;
hueTexture.name = "HueTexture";
for (int i = 0; i < hueTexture.height; i++)
{
hueTexture.SetPixel(0, i, Color.HSVToRGB((float)i / hueTexture.height, 1, 1));
}
hueTexture.Apply();
currentHue = 0;
hueImage.texture = hueTexture;
}
private void CreateSVImage()
{
svTexture = new Texture2D(16, 16);
svTexture.wrapMode = TextureWrapMode.Clamp;
svTexture.name = "SVTexture";
for (int y = 0; y < svTexture.height; y++)
{
for (int x = 0; x < svTexture.width; x++)
{
svTexture.SetPixel(x, y, Color.HSVToRGB(currentHue, (float)x / svTexture.width, (float)y / svTexture.height));
}
}
svTexture.Apply();
currentSat = 0;
currentVal = 0;
satValImage.texture = svTexture;
}
private void CreateOutputImage()
{
outputTexture = new Texture2D(1, 16);
outputTexture.wrapMode = TextureWrapMode.Clamp;
outputTexture.name = "OutputTexture";
Color currentColor = Color.HSVToRGB(currentHue, currentSat, currentVal);
for (int i = 0; i < hueTexture.height; i++)
{
outputTexture.SetPixel(0, 1, currentColor);
}
outputTexture.Apply();
currentHue = 0;
outputImage.texture = outputTexture;
}
private void UpdateOutputImage()
{
Color currentColor = Color.HSVToRGB(currentHue, currentSat, currentVal);
for (int i = 0; i < outputTexture.height; i++)
{
outputTexture.SetPixel(0, i, currentColor);
}
//Updating RBG Input
inputR.text = ((int)(currentColor.r * 255f)).ToString();
inputG.text = ((int)(currentColor.g * 255f)).ToString();
inputB.text = ((int)(currentColor.b * 255f)).ToString();
//Updating HSV Input
inputH.text = (currentHue.ToString("F2"));
inputS.text = (currentSat.ToString("F2"));
inputV.text = (currentVal.ToString("F2"));
//Updating Hex Input
string hexRGB = ColorUtility.ToHtmlStringRGB(currentColor);
hexValueTex.text = "#" + hexRGB;
outputTexture.Apply();
if (!colorObject) return;
Swatch.color = currentColor;
SetColor(currentColor, currentChannel);
channelText.color = new Color( 1 - currentVal, 1 - currentVal, 1 - currentVal, 1);
svContoller.setPickerPosition(currentSat, currentVal);
}
public void SetSV(float S, float V)
{
currentSat = S;
currentVal = V;
UpdateOutputImage();
}
public void SetHSV(float H, float S, float V)
{
currentHue = H;
currentSat = S;
currentVal = V;
UpdateOutputImage();
}
public void SetHSV()
{
float.TryParse(inputH.text, out currentHue);
float.TryParse(inputS.text, out currentSat);
float.TryParse(inputV.text, out currentVal);
UpdateOutputImage();
}
public void SetRGB()
{
byte r = 0;
byte.TryParse(inputR.text, out r);
byte g = 0;
byte.TryParse(inputG.text, out g);
byte b = 0;
byte.TryParse(inputB.text, out b);
var color = new Color32(r,g,b, 255);
Color.RGBToHSV(color, out float h, out float s, out float v);
SetHSV(h, s, v);
}
public void UpdateSVImage()
{
currentHue = hueSlider.value;
for (int y = 0; y < svTexture.height; y++)
{
for (int x = 0; x < svTexture.width; x++)
{
svTexture.SetPixel(x, y, Color.HSVToRGB(currentHue, (float)x / svTexture.width, (float)y / svTexture.height));
}
}
svTexture.Apply();
UpdateOutputImage();
}
private void SetColor(Color color, int channel)
{
switch (mode)
{
case TextureType.Base:
colorObject.SetColor(color, channel);
break;
case TextureType.Decal:
maxChannel = 3;
colorObject.SetDecalColor(color, channel);
break;
case TextureType.Pattern:
maxChannel = 3;
colorObject.SetPatternColor(color, channel);
break;
}
}
public void ChangeSwatch(int value)
{
currentChannel += value;
if(currentChannel > maxChannel) { currentChannel = 1; }
if(currentChannel < 1) { currentChannel = maxChannel; };
Color swatchColor = Color.black;
switch (mode)
{
case TextureType.Base:
swatchColor = colorObject.GetColor(currentChannel);
break;
case TextureType.Decal:
swatchColor = colorObject.GetDecalColor(currentChannel);
break;
case TextureType.Pattern:
swatchColor = colorObject.GetPatternColor(currentChannel);
break;
default:
break;
}
Swatch.color = swatchColor;
SetChannelName();
Color.RGBToHSV(swatchColor, out float h, out float s, out float v);
hueSlider.value = h;
SetHSV(h, s, v);
UpdateSVImage();
}
public void ChangeObject(OutfitBase ob)
{
if (!ob) {RemoveObject(); return; }
var colorOutfit = ob.GetComponent<Outfit>();
//Keeping color of previous Outfit if turned on and type is the same
if (maintainColors && !colorOutfit.customShader && colorObject != null)
{
HeldColors = colorObject.GetColors();
if(colorOutfit.Type == outfitType)
{
for (int i = 0; i < HeldColors.Count; i++)
{
colorOutfit.SetColor(HeldColors[i], i + 1);
}
}
}
//initalizing values
channelNames = new string[] { "Base" };
outfitType = colorOutfit.Type;
mode = TextureType.Base;
colorObject = ob;
//RememberSettings
if (!outfitPickerSettings.ContainsKey(colorOutfit.Type))
{
var newSettings = new OutfitPickerSettings();
outfitPickerSettings.Add(colorOutfit.Type, newSettings);
}
var settings = outfitPickerSettings[colorOutfit.Type];
SetMaintainColors(settings.maintainColors);
SetCopyIndex(settings.copyIndex);
//Custom Shaders
if(colorObject.customShader == true)
{
decalContainer.SetActive(false);
patternContainer.SetActive(false);
swatchParentContainer.SetActive(true);
maxChannel = 1;
foreach (var item in swatchSelectors)
{
Destroy(item.gameObject);
}
swatchSelectors.Clear();
for (int i = 0; i < colorOutfit.outfitSwatches.Count; i++)
{
var swatch = Instantiate(swatchSelectorObject, swatchContainer);
swatch.Init(this, colorOutfit.outfitSwatches[i], i);
swatchSelectors.Add(swatch);
}
}
//BoZo_Toon Shader
else
{
var color = colorObject.GetColor(1);
color.a = 1;
currentChannel = 1;
Swatch.color = color;
decalContainer.SetActive(true);
patternContainer.SetActive(true);
channelNames = colorOutfit.ColorChannels;
if (colorOutfit)
{
maxChannel = colorOutfit.ColorChannels.Length;
if (!colorOutfit.supportDecals) decalContainer.SetActive(false);
if (!colorOutfit.supportPatterns) patternContainer.SetActive(false);
swatchParentContainer.SetActive(false);
}
else
{
maxChannel = 9;
}
var decalSize = colorObject.GetDecalSize();
DecalXSlider.value = decalSize.x;
DecalYSlider.value = decalSize.y;
var patternSize = colorObject.GetPatternSize();
patternXSlider.value = patternSize.x;
patternYSlider.value = patternSize.y;
}
SetChannelName();
ChangeSwatch(0);
objectName.text = colorObject.name.Replace("(Clone)", "");
if (colorObject == null) gameObject.SetActive(false);
else gameObject.SetActive(true);
}
public void SetDecalSize()
{
var scale = new Vector2(DecalXSlider.value, DecalYSlider.value);
colorObject.SetDecalSize(scale);
}
public void SetPatternSize()
{
var scale = new Vector2(patternXSlider.value, patternYSlider.value);
colorObject.SetPatternSize(scale);
}
public void RemoveObject()
{
colorObject = null;
SetMaintainColors(false);
gameObject.SetActive(false);
}
public void SetBaseTexture(int textureIndex)
{
var outfit = colorObject.GetComponent<Outfit>();
outfit.SetSwatch(textureIndex);
}
public void SwitchMode(string mode)
{
var type = (TextureType)Enum.Parse(typeof(TextureType), mode);
this.mode = type;
switch (this.mode)
{
case TextureType.Base:
ChangeObject(colorObject);
break;
case TextureType.Decal:
maxChannel = 3;
channelText.text = "1/" + maxChannel;
var decal = colorObject.GetDecalColor(1);
decal.a = 1;
currentChannel = 1;
Swatch.color = decal;
break;
case TextureType.Pattern:
maxChannel = 3;
channelText.text = "1/" + maxChannel;
var pattern = colorObject.GetPatternColor(1);
pattern.a = 1;
currentChannel = 1;
Swatch.color = pattern;
break;
}
}
public void ChangeCopyIndex(int value)
{
copyIndex += value;
if(copyIndex > outfitTypes.Count - 1)
{
copyIndex = 0;
}
else if (copyIndex < 0)
{
copyIndex = outfitTypes.Count - 1;
}
CopyCatagoryText.text = outfitTypes[copyIndex];
if(outfitType != null)
{
outfitPickerSettings[outfitType].copyIndex = copyIndex;
}
}
public void SetCopyIndex(int value)
{
copyIndex = value;
CopyCatagoryText.text = outfitTypes[copyIndex];
outfitPickerSettings[outfitType].copyIndex = copyIndex;
}
public void CopyColor(OutfitBase copyOutfit)
{
var from = colorObject;
var to = copyOutfit;
for (int i = 1; i < 9; i++)
{
to.SetColor(from.GetColor(i), i);
}
}
public void CopyColor()
{
var from = colorObject;
var to = outfitSystem.GetOutfit(CopyCatagoryText.text);
if (to == null) return;
for (int i = 1; i < 9; i++)
{
to.SetColor(from.GetColor(i), i);
}
}
public void SetColorByHex(string hex)
{
if (hex[0].ToString() != "#")
{
hex = "#" + hex;
}
if (ColorUtility.TryParseHtmlString(hex, out Color hexColor))
{
print(hexColor);
Color.RGBToHSV(hexColor, out float h, out float s, out float v);
SetHSV(h, s, v);
}
else
{
Debug.LogWarning("Invalid hex string!");
}
}
public void CopyHex()
{
GUIUtility.systemCopyBuffer = hexValueTex.text;
print("Copied HEX to Clipboard: " + hexValueTex.text);
}
public void SetChannelName()
{
var channelName = "";
switch (mode)
{
case TextureType.Base:
if (colorObject.customShader) break;
if (currentChannel - 1 < channelNames.Length)
{
channelName = channelNames[currentChannel - 1];
}
break;
case TextureType.Decal:
channelName = "Decal";
break;
case TextureType.Pattern:
channelName = "Pattern";
break;
}
channelText.text = channelName + " " + currentChannel + "/" + maxChannel;
}
public void SetMaintainColors(bool value)
{
if (value && colorObject != null)
{
HeldColors = colorObject.GetColors();
}
maintainColors = value;
maintainColorsToggle.isOn = maintainColors;
if(outfitType != null)
{
outfitPickerSettings[outfitType].maintainColors = maintainColors;
}
}
private class OutfitPickerSettings
{
public bool maintainColors = false;
public int copyIndex = 0;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 6ad41dc542643ad4994079a3430133a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/ColorPickerControl.cs
uploadId: 853356

View File

@@ -0,0 +1,47 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
namespace Bozo.AnimeCharacters
{
public class BlendSlider : MonoBehaviour
{
Slider slider;
[SerializeField] TMP_Text title;
[SerializeField] TMP_Text sliderValue;
[SerializeField] OutfitSystem system;
[SerializeField] string shape;
public void Init(OutfitSystem system, string key)
{
slider = GetComponentInChildren<Slider>();
slider.onValueChanged.AddListener(Apply);
this.system = system;
title.text = key;
shape = key;
var weight = system.GetShapeValue(key);
slider.value = weight;
}
private void OnEnable()
{
var weight = system.GetShapeValue(shape);
slider.value = weight;
}
private void UpdateSlider()
{
}
public void Apply(float value)
{
system.SetShape(shape, value);
sliderValue.text = $"{slider.value}%";
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: bf57ed88aed245749b3cc66844288e5b
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/Creator_BlendSlider.cs
uploadId: 853356

View File

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

View File

@@ -0,0 +1,38 @@
using UnityEditor;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
[CustomEditor(typeof(CharacterObject))]
public class CharacterEditor : Editor
{
public override void OnInspectorGUI()
{
CharacterObject myObj = (CharacterObject)target;
serializedObject.Update();
float size = 128f;
EditorGUILayout.PropertyField(serializedObject.FindProperty("icon"));
if (myObj.icon != null)
{
// Define a clean Unity-style frame using GUIStyle
GUIStyle frameStyle = new GUIStyle(GUI.skin.box);
frameStyle.padding = new RectOffset(10, 10, 10, 10);
frameStyle.margin = new RectOffset(5, 5, 5, 5);
frameStyle.margin = new RectOffset(5, 5, 5, 5);
GUILayout.BeginHorizontal(frameStyle);
Rect previewRect = GUILayoutUtility.GetRect(size, size, GUILayout.ExpandWidth(true));
EditorGUI.DrawPreviewTexture(previewRect, myObj.icon, null, ScaleMode.ScaleToFit);
GUILayout.EndHorizontal();
}
EditorGUILayout.PropertyField(serializedObject.FindProperty("data"));
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 03ad0fb1979a42547bfd21ad94bb5ffb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/Editor/CharacterEditor.cs
uploadId: 853356

View File

@@ -0,0 +1,26 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
[CustomEditor(typeof(IconCapture))]
public class IconCaptureEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
IconCapture icon = (IconCapture)target;
GUILayout.BeginHorizontal();
if (GUILayout.Button("Take ScreenShot"))
{
icon.Capture();
}
GUILayout.EndHorizontal();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f87dc63653e81464eb2154dd1728e834
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/Editor/IconCaptureEditor.cs
uploadId: 853356

View File

@@ -0,0 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace Bozo.AnimeCharacters
{
[CustomEditor(typeof(TextureBaker))]
public class TextureBakerEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
TextureBaker baker = (TextureBaker)target;
GUILayout.BeginHorizontal();
if(GUILayout.Button("Export Outfit"))
{
baker.ExportOutfit();
}
if (GUILayout.Button("Create Swatch"))
{
baker.CreateSwatch();
}
GUILayout.EndHorizontal();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 6fcb6ec024ec6474a93423073e9f2f71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/Editor/TextureBakerEditor.cs
uploadId: 853356

View File

@@ -0,0 +1,41 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class ExpressionSelect : MonoBehaviour
{
public OutfitSystem outfitSystem;
public Animator animator;
public string parameterID;
private void OnEnable()
{
outfitSystem.OnOutfitChanged += GetHead;
}
private void GetHead(Outfit outfit)
{
var head = outfitSystem.GetOutfit("Head");
if (head) animator = head.GetComponentInChildren<Animator>();
else animator = outfitSystem.animator;
}
private void OnDisable()
{
outfitSystem.OnOutfitChanged -= GetHead;
}
public void SetExpression(float value)
{
if(animator == null)
{
var head = outfitSystem.GetOutfit("Head");
if (head) animator = head.GetComponentInChildren<Animator>();
else animator = outfitSystem.animator;
}
animator.SetFloat(parameterID, value);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 57776f57f2fa13549ab17323a6064af0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/ExpressionSelect.cs
uploadId: 853356

View File

@@ -0,0 +1,161 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class IconCapture : MonoBehaviour
{
[SerializeField] RenderTexture iconTexture;
[SerializeField] Camera iconCamera;
[SerializeField] Transform parent;
[SerializeField] string path = "BoZo_ModularAnimeCharacters/Textures/OutfitIcons";
[SerializeField] GameObject BackingBody;
[SerializeField] GameObject BackingHead;
[SerializeField] List<Outfit> outfits = new List<Outfit>();
[SerializeField] Color[] Colors;
private Camera activeCam;
[SerializeField] IconCaptureSettings[] cameraSettings;
[SerializeField] Dictionary<OutfitType, IconCaptureSettings> cameras = new Dictionary<OutfitType, IconCaptureSettings>();
private void Awake()
{
foreach (var item in cameraSettings)
{
cameras.Add(item.type, item);
}
}
[ContextMenu("Capture")]
public void Capture()
{
#if UNITY_EDITOR
StartCoroutine(CaptureCoroutine());
#endif
}
public void Capture(GameObject gameObject)
{
#if UNITY_EDITOR
outfits.Clear();
var outfit = gameObject.GetComponent<Outfit>();
if (outfit == null) return;
path = AssetDatabase.GetAssetPath(gameObject.gameObject);
path = path.Replace(gameObject.name + ".prefab", "");
path = path.Replace("Assets", "");
outfits.Add(outfit);
StartCoroutine(CaptureCoroutine());
#endif
}
#if UNITY_EDITOR
private IEnumerator CaptureCoroutine()
{
if(outfits.Count == 0)
{
yield return new WaitForEndOfFrame();
RenderTexture.active = iconTexture;
Texture2D icon = new Texture2D(iconTexture.width, iconTexture.height, TextureFormat.RGBA32, false);
Rect rect = new Rect(new Rect(0, 0, iconTexture.width, iconTexture.height));
icon.ReadPixels(rect, 0, 0);
icon.Apply();
byte[] bytes = icon.EncodeToPNG();
System.IO.File.WriteAllBytes(Application.dataPath + "/" + path + "/" + "ICON" + ".png", bytes);
AssetDatabase.Refresh();
TextureImporter importer = AssetImporter.GetAtPath("Assets/" + path + "/" + "ICON" + ".png") as TextureImporter;
if (importer != null)
{
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Single;
importer.SaveAndReimport();
}
yield return null;
}
foreach (var item in outfits)
{
//Match the camera to the outfit
if (activeCam != null) activeCam.gameObject.SetActive(false);
activeCam = cameras[item.Type].camera;
activeCam.gameObject.SetActive(true);
BackingBody.SetActive(cameras[item.Type].showBody);
BackingHead.SetActive(cameras[item.Type].showHead);
var outfit = Instantiate(item, parent);
if (!outfit.customShader)
{
for (int i = 0; i < Colors.Length; i++)
{
outfit.SetColor(Colors[i], i + 1);
}
}
activeCam.Render();
yield return new WaitForEndOfFrame();
RenderTexture.active = iconTexture;
Texture2D icon = new Texture2D(iconTexture.width, iconTexture.height, TextureFormat.RGBA32, false);
Rect rect = new Rect(new Rect(0, 0, iconTexture.width, iconTexture.height));
icon.ReadPixels(rect, 0, 0);
icon.Apply();
byte[] bytes = icon.EncodeToPNG();
System.IO.File.WriteAllBytes(Application.dataPath + "/" + path + "/" + item.name + ".png", bytes);
AssetDatabase.Refresh();
print("IconCreated: " + Application.dataPath + "/" + path + "/" + item.name + ".png");
TextureImporter importer = AssetImporter.GetAtPath("Assets/" + path + "/" + item.name + ".png") as TextureImporter;
Destroy(outfit.gameObject);
if (importer != null)
{
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Single;
importer.SaveAndReimport();
}
if (outfit)
{
var spritrIcon = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/" + path + "/" + item.name + ".png");
item.OutfitIcon = spritrIcon;
EditorUtility.SetDirty(item);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
if (activeCam != null) activeCam.gameObject.SetActive(false);
yield return null;
}
}
#endif
[System.Serializable]
public class IconCaptureSettings
{
public OutfitType type;
public Camera camera;
public bool showHead = true;
public bool showBody = true;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 4e147bfe656788040a25848b79cbab1f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/IconCapture.cs
uploadId: 853356

View File

@@ -0,0 +1,94 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace Bozo.AnimeCharacters
{
public class SVImageControl : MonoBehaviour, IDragHandler, IPointerClickHandler
{
[SerializeField] Image PickerImage;
private RawImage SVImage;
private ColorPickerControl CC;
private RectTransform rect;
private RectTransform pickerTransform;
private void Awake()
{
SVImage = GetComponent<RawImage>();
CC = FindFirstObjectByType<ColorPickerControl>();
rect = GetComponent<RectTransform>();
pickerTransform = PickerImage.GetComponent<RectTransform>();
pickerTransform = PickerImage.GetComponent<RectTransform>();
pickerTransform.position = new Vector2(-(rect.sizeDelta.x * 0.5f), -(rect.sizeDelta.y * 0.5f));
}
private void UpdateColor(PointerEventData eventData)
{
Vector3 pos = rect.InverseTransformPoint(eventData.position);
float deltaX = rect.sizeDelta.x * 0.5f;
float deltaY = rect.sizeDelta.y * 0.5f;
if (pos.x < -deltaX)
{
pos.x = -deltaX;
}
if (pos.x > deltaX)
{
pos.x = deltaX;
}
if (pos.y < -deltaY)
{
pos.y = -deltaY;
}
if (pos.y > deltaY)
{
pos.y = deltaY;
}
float x = pos.x + deltaX;
float y = pos.y + deltaY;
float xNorm = x / rect.sizeDelta.x;
float YNorm = y / rect.sizeDelta.y;
//pickerTransform.localPosition = pos;
PickerImage.color = Color.HSVToRGB(0, 0, 1 - YNorm);
CC.SetSV(xNorm, YNorm);
}
public void setPickerPosition(float x, float y)
{
if(!rect) rect = GetComponent<RectTransform>();
if(!pickerTransform) pickerTransform = PickerImage.GetComponent<RectTransform>();
var xPos = Mathf.Lerp(-rect.sizeDelta.x / 2, rect.sizeDelta.x/ 2, x);
var yPos = Mathf.Lerp(-rect.sizeDelta.y / 2, rect.sizeDelta.y / 2, y);
var pos = new Vector2(xPos, yPos);
pickerTransform.localPosition = pos;
}
public void OnDrag(PointerEventData eventData)
{
UpdateColor(eventData);
}
public void OnPointerClick(PointerEventData eventData)
{
UpdateColor(eventData);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: ed18d41614dff814fa3781f04180cd92
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/SVImageControl.cs
uploadId: 853356

View File

@@ -0,0 +1,27 @@
using UnityEngine;
using UnityEngine.UI;
namespace Bozo.AnimeCharacters
{
public class SaveSelector : MonoBehaviour
{
public Image icon;
private CharacterData data;
private CharacterCreator characterCreator;
private Button button;
public void Init(CharacterData characterData, Sprite icon, CharacterCreator characterCreator)
{
button = GetComponentInChildren<Button>();
button.onClick.AddListener(OnSelect);
this.data = characterData;
this.characterCreator = characterCreator;
this.icon.overrideSprite = icon;
}
private void OnSelect()
{
characterCreator.LoadCharacter(data);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 76c84ed6450e2b142b4db815c7ddb7a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/SaveSelector.cs
uploadId: 853356

View File

@@ -0,0 +1,28 @@
using UnityEngine;
using UnityEngine.UI;
namespace Bozo.AnimeCharacters
{
public class SwatchSelector : MonoBehaviour
{
ColorPickerControl picker;
public int swatchIndex;
//these are for setting the swatch icon colors
public Image color1;
public Image color2;
public void Init(ColorPickerControl colorPickerControl, OutfitSwatch swatchData, int swatchIndex)
{
picker = colorPickerControl;
this.swatchIndex = swatchIndex;
color1.color = swatchData.IconColorTop;
color2.color = swatchData.IconColorBottom;
}
public void SetSwatch()
{
picker.SetBaseTexture(swatchIndex);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: a233887b31097fe4e8887eb7056865c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/SwatchSelector.cs
uploadId: 853356

View File

@@ -0,0 +1,337 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
namespace Bozo.AnimeCharacters
{
public class TextureBaker : MonoBehaviour
{
#if UNITY_EDITOR
public CharacterCreator characterCreator;
public Material BakeMaterial;
public Material UserMaterial;
public IconCapture IconCapture;
[Header("ExportSettings")]
[SerializeField] string outfitName;
[SerializeField] OutfitType OutfitToExport;
[SerializeField] int textureDilation = 20;
private string savePath = Application.dataPath + "/BoZo_ModularAnimeCharacters/CustomOutfits/Resources";
private string AssetPath = "Assets/BoZo_ModularAnimeCharacters/CustomOutfits/Resources";
[ContextMenu("ExportOutfit")]
public void ExportOutfit()
{
if (!Application.isPlaying)
{
Debug.LogWarning("Please Enter Play Mode to export an Outfit");
return;
}
if (outfitName.Length == 0)
{
Debug.LogWarning("Please enter name for export");
return;
}
if (UserMaterial == null)
{
Debug.LogWarning("Material Empty please select a source material");
return;
}
if (OutfitToExport == null)
{
Debug.LogWarning("Empty OutfitType Please Provide an Outfit Type");
return;
}
var character = characterCreator.character;
var sourceOutfit = character.GetOutfit(OutfitToExport);
if (sourceOutfit == null)
{
Debug.LogWarning("Outfit is Null make sure outfit exists on character");
return;
}
var cleanName = sourceOutfit.name;
cleanName = cleanName.Replace("(Clone)", "");
var NewOutfit = Instantiate(characterCreator.GetOutfit(cleanName));
BakeOutfit(sourceOutfit, NewOutfit, outfitName);
}
public void CreateOutfit()
{
var character = characterCreator.character;
var sourceOutfit = character.GetOutfit(OutfitToExport);
if (sourceOutfit == null)
{
Debug.LogWarning("Outfit is Null make sure outfit exists on character");
return;
}
var cleanName = sourceOutfit.name;
cleanName = cleanName.Replace("(Clone)", "");
var NewOutfit = Instantiate(characterCreator.GetOutfit(cleanName));
BakeOutfit(sourceOutfit, NewOutfit, outfitName);
}
public void BakeOutfit(Outfit sourceOutfit, Outfit newOutfit, string outfitName = "NewOutfit")
{
Renderer renderer = newOutfit.GetComponentInChildren<Renderer>();
var tex = CreateTexture(sourceOutfit, newOutfit);
//Create Save Path
string folderPath = sourceOutfit.Type.name;
if (!AssetDatabase.IsValidFolder(AssetPath + "/" + folderPath))
{
AssetDatabase.CreateFolder(AssetPath, folderPath);
}
// Save PNG
byte[] bytes = tex.EncodeToPNG();
System.IO.File.WriteAllBytes(savePath + "/" + folderPath + "/" + folderPath + "_" + outfitName + "_Swatch_1.png", bytes);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
//Save Asset
string path = AssetPath + "/" + folderPath + "/" + folderPath + "_" + outfitName;
Material newMaterial = new Material(UserMaterial);
var newTex = AssetDatabase.LoadAssetAtPath<Texture2D>(path + "_Swatch_1.png");
newMaterial.mainTexture = newTex;
AssetDatabase.CreateAsset(newMaterial, path + "_mat.mat");
var newMat = AssetDatabase.LoadAssetAtPath<Material>(path + "_mat.mat");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
newMat.mainTexture = newTex;
renderer.material = newMat;
AssetDatabase.DeleteAsset(path + ".prefab");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
var swatch = new OutfitSwatch();
swatch.swatchID = folderPath + "/" + folderPath + "_" + outfitName + "_Swatch_" + 1;
newOutfit.outfitSwatches.Add(swatch);
newOutfit.customShader = true;
var savedPrefab = PrefabUtility.SaveAsPrefabAsset(newOutfit.gameObject, path + ".prefab");
EditorUtility.SetDirty(savedPrefab);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Destroy(newOutfit.gameObject);
IconCapture.Capture(savedPrefab);
Debug.Log("Swatched Created: " + path);
}
[ContextMenu("CreateSwatch")]
public void CreateSwatch()
{
if (!Application.isPlaying)
{
Debug.LogWarning("Please Enter Play Mode to create Swatch");
return;
}
if (outfitName.Length == 0)
{
Debug.LogWarning("Please enter name for export");
return;
}
var character = characterCreator.character;
var sourceOutfit = character.GetOutfit(OutfitToExport);
var cleanName = sourceOutfit.name;
cleanName = cleanName.Replace("(Clone)", "");
var newOutfit = Instantiate(characterCreator.GetOutfit(cleanName));
string folderPath = sourceOutfit.Type.name;
string path = AssetPath + "/" + folderPath + "/" + folderPath + "_" + outfitName + ".prefab";
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
print(path);
if (prefab == null)
{
Debug.LogWarning("Custom Outfit does not exist. Please Use Export before creating swatches");
Destroy(newOutfit.gameObject);
return;
}
int count = 1;
string SwatchPath = savePath + "/" + folderPath + "/" + folderPath + "_" + outfitName + "_Swatch_" + count + ".png";
do
{
count++;
SwatchPath = savePath + "/" + folderPath + "/" + folderPath + "_" + outfitName + "_Swatch_" + count + ".png";
print(count);
} while (System.IO.File.Exists(SwatchPath));
var tex = CreateTexture(sourceOutfit, newOutfit);
byte[] bytes = tex.EncodeToPNG();
System.IO.File.WriteAllBytes(SwatchPath, bytes);
var outfit = prefab.GetComponent<Outfit>();
var swatch = new OutfitSwatch();
swatch.swatchID = folderPath + "/" + folderPath + "_" + outfitName + "_Swatch_" + count;
outfit.outfitSwatches.Add(swatch);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Destroy(newOutfit.gameObject);
Debug.Log("Swatched Created: " + path);
}
Texture2D CreateTexture(Outfit sourceOutfit, Outfit newOutfit)
{
Mesh mesh = null;
Renderer renderer = newOutfit.GetComponentInChildren<Renderer>();
Material sourceMaterial = sourceOutfit.GetComponentInChildren<Renderer>().material;
if (renderer.TryGetComponent<MeshRenderer>(out MeshRenderer meshRenderer))
{
mesh = meshRenderer.GetComponent<MeshFilter>().sharedMesh;
}
else if (renderer.TryGetComponent<SkinnedMeshRenderer>(out SkinnedMeshRenderer skinnedMeshRenderer))
{
mesh = skinnedMeshRenderer.sharedMesh;
}
else
{
return null;
}
renderer.material = BakeMaterial;
Material material = renderer.material;
//Copy All Colors and Data To Bake Material
material.mainTexture = sourceMaterial.mainTexture;
material.SetTexture("_DecalMap", sourceMaterial.GetTexture("_DecalMap"));
material.SetFloat("_DecalUVSet", sourceMaterial.GetFloat("_DecalUVSet"));
material.SetFloat("_DecalBlend", sourceMaterial.GetFloat("_DecalBlend"));
material.SetVector("_DecalScale", sourceMaterial.GetVector("_DecalScale"));
material.SetTexture("_PatternMap", sourceMaterial.GetTexture("_PatternMap"));
material.SetFloat("_PatternUVSet", sourceMaterial.GetFloat("_PatternUVSet"));
material.SetFloat("_PatternBlend", sourceMaterial.GetFloat("_PatternBlend"));
material.SetVector("_PatternScale", sourceMaterial.GetVector("_PatternScale"));
for (int i = 0; i < 8; i++)
{
material.SetColor("_Color_" + (i + 1), sourceMaterial.GetColor("_Color_" + (i + 1)));
material.SetColor("_Color_" + (i + 1), sourceMaterial.GetColor("_Color_" + (i + 1)));
if (i + 1 <= 3)
{
material.SetColor("_DecalColor_" + (i + 1), sourceMaterial.GetColor("_DecalColor_" + (i + 1)));
material.SetColor("_PatternColor_" + (i + 1), sourceMaterial.GetColor("_PatternColor_" + (i + 1)));
}
}
var textureSize = 2048;
// Create RenderTexture
RenderTexture rt = new RenderTexture(textureSize, textureSize, 0);
rt.wrapMode = TextureWrapMode.Clamp;
// Create command buffer to render the mesh
CommandBuffer cb = new CommandBuffer();
cb.SetRenderTarget(rt);
cb.ClearRenderTarget(true, true, Color.clear);
Matrix4x4 identity = Matrix4x4.identity;
cb.DrawMesh(mesh, identity, material);
// Execute
Graphics.ExecuteCommandBuffer(cb);
cb.Release();
// Read pixels
RenderTexture.active = rt;
Texture2D tex = new Texture2D(textureSize, textureSize, TextureFormat.RGBA32, false);
tex.ReadPixels(new Rect(0, 0, textureSize, textureSize), 0, 0);
tex = DilateTexture(tex);
tex.Apply();
RenderTexture.active = null;
return tex;
}
Texture2D DilateTexture(Texture2D tex)
{
var iterations = textureDilation;
int w = tex.width;
int h = tex.height;
Color32[] pixels = tex.GetPixels32();
Color32[] temp = new Color32[pixels.Length];
for (int it = 0; it < iterations; it++)
{
pixels.CopyTo(temp, 0);
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int idx = y * w + x;
if (pixels[idx].a != 0) continue;
// Look around
for (int dy = -1; dy <= 1; dy++)
{
for (int dx = -1; dx <= 1; dx++)
{
int nx = x + dx;
int ny = y + dy;
if (nx < 0 || nx >= w || ny < 0 || ny >= h) continue;
int nIdx = ny * w + nx;
if (pixels[nIdx].a != 0)
{
temp[idx] = pixels[nIdx];
goto NextPixel;
}
}
}
NextPixel:;
}
}
// Swap buffers
Color32[] swap = pixels;
pixels = temp;
temp = swap;
}
tex.SetPixels32(pixels);
tex.Apply();
return tex;
}
#endif
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 85387e6ed0b4b7c44aa6a96bbdc3b578
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/TextureBaker.cs
uploadId: 853356

View File

@@ -0,0 +1,14 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public enum TextureType {Base, Decal, Pattern}
public class TexturePackage : MonoBehaviour
{
public Texture texture;
public Texture normalTexture;
public Sprite icon;
public TextureType type;
public string catagory;
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3ebda9b78a726204ca1dde4751c2a906
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/TexturePackage.cs
uploadId: 853356

View File

@@ -0,0 +1,48 @@
using UnityEngine;
using UnityEngine.UI;
namespace Bozo.AnimeCharacters
{
public class TextureSelector : MonoBehaviour
{
public Image icon;
private TexturePackage texture;
private CharacterCreator characterCreator;
private Button button;
public void Init(TexturePackage texture, CharacterCreator characterCreator)
{
button = GetComponentInChildren<Button>();
button.onClick.AddListener(OnSelect);
this.texture = texture;
this.characterCreator = characterCreator;
icon.overrideSprite = texture.icon;
}
private void OnSelect()
{
if (texture.type == TextureType.Decal)
{
characterCreator.SetOutfitDecal(texture.texture);
}
if (texture.type == TextureType.Pattern)
{
characterCreator.SetOutfitPattern(texture.texture);
}
}
public void SetVisable(string type)
{
if (texture.catagory == type)
{
gameObject.SetActive(true);
}
else
{
gameObject.SetActive(false);
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: ac4a46d3ea472c148948989f6e8cbb94
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/CharacterCreator/TextureSelector.cs
uploadId: 853356

View File

@@ -0,0 +1,12 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
[CreateAssetMenu(fileName = "BMAC_CharacterObject", menuName = "BoZo/BMAC_CharacterObject")]
public class CharacterObject : ScriptableObject
{
public Texture2D icon;
public CharacterData data;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3673d1a705285cd45860e82c86312ef5

View File

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

View File

@@ -0,0 +1,128 @@
using UnityEditor;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
[CustomEditor(typeof(Outfit))]
[CanEditMultipleObjects]
public class OutfitEditor : Editor
{
public override void OnInspectorGUI()
{
Outfit outfit = (Outfit)target;
Color originalColor = GUI.color;
GUIStyle frameStyle = new GUIStyle(GUI.skin.box);
serializedObject.Update();
EditorGUILayout.Space(20);
GUILayout.Label("Character Creator Settings");
GUILayout.BeginVertical(frameStyle);
GUILayout.BeginHorizontal(frameStyle);
GUILayout.BeginVertical(frameStyle);
EditorGUILayout.PropertyField(serializedObject.FindProperty("OutfitName"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("OutfitIcon"));
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("ColorChannels"));
EditorGUI.indentLevel--;
EditorGUILayout.PropertyField(serializedObject.FindProperty("TextureCatagory"));
GUILayout.BeginHorizontal(frameStyle);
var decalsupport = serializedObject.FindProperty("supportDecals");
EditorGUILayout.LabelField("Supports Decal", GUILayout.Width(200));
decalsupport.boolValue = EditorGUILayout.Toggle(decalsupport.boolValue);
var patternsupport = serializedObject.FindProperty("supportPatterns");
EditorGUILayout.LabelField("Supports Pattern", GUILayout.Width(200));
patternsupport.boolValue = EditorGUILayout.Toggle(patternsupport.boolValue);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(frameStyle);
EditorGUILayout.LabelField("Available In Character Creator", GUILayout.Width(200));
EditorGUILayout.Space(20);
var buttonText = "";
if (outfit.showCharacterCreator)
{
buttonText = "(Available)";
}
else
{
GUI.color = Color.yellow;
buttonText = "(Hidden)";
}
if (GUILayout.Button(buttonText))
{
outfit.showCharacterCreator = !outfit.showCharacterCreator;
}
GUI.color = originalColor;
GUILayout.EndHorizontal();
GUILayout.EndVertical();
if (outfit.OutfitIcon != null)
{
// Control the size of the image
float size = 128;
Rect rect = GUILayoutUtility.GetRect(size, size, GUILayout.ExpandWidth(false));
EditorGUI.DrawTextureTransparent(rect, outfit.OutfitIcon.texture);
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
EditorGUILayout.Space(20);
GUILayout.Label("Outfit Settings");
GUILayout.BeginVertical(frameStyle);
EditorGUILayout.PropertyField(serializedObject.FindProperty("Type"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("AttachPoint"));
GUILayout.BeginHorizontal(frameStyle);
var customShader = serializedObject.FindProperty("customShader");
EditorGUILayout.LabelField("Uses Custom Shader", GUILayout.Width(200));
customShader.boolValue = EditorGUILayout.Toggle(customShader.boolValue);
var attachEditMode = serializedObject.FindProperty("AttachInEditMode");
EditorGUILayout.LabelField("Follow Skeleton In Edit Mode", GUILayout.Width(200));
attachEditMode.boolValue = EditorGUILayout.Toggle(attachEditMode.boolValue);
GUILayout.EndHorizontal();
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("defaultColors"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("tags"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("LinkedColorSets"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("IncompatibleSets"));
EditorGUI.indentLevel--;
GUILayout.EndVertical();
EditorGUILayout.Space(20);
GUILayout.Label("Custom Settings");
GUILayout.BeginVertical(frameStyle);
EditorGUILayout.PropertyField(serializedObject.FindProperty("currentSwatch"));
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("outfitSwatches"));
EditorGUI.indentLevel--;
GUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
//base.OnInspectorGUI();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8f3ec7e868ad30a4f991d95602aa2a40
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/Editor/OutfitEditor.cs
uploadId: 853356

View File

@@ -0,0 +1,167 @@
using UnityEditor;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
[CustomEditor(typeof(OutfitSystem))]
public class OutfitSystemEditor : Editor
{
private bool showMergedOptions;
private bool dependencies;
private Texture2D banner;
private void OnEnable()
{
banner = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Bozo_ModularAnimeCharacters/Textures/Editor/Banner_OutfitSystem.png");
}
public override void OnInspectorGUI()
{
OutfitSystem system = (OutfitSystem)target;
Color originalColor = GUI.color;
GUIStyle frameStyle = new GUIStyle(GUI.skin.box);
serializedObject.Update();
if (banner != null)
{
float maxWidth = EditorGUIUtility.currentViewWidth - 20;
float aspect = (float)banner.width / banner.height;
float desiredWidth = Mathf.Min(banner.width, maxWidth);
float height = desiredWidth / aspect;
// Center it using flexible space
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.Label(banner, GUILayout.Width(desiredWidth), GUILayout.Height(height));
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
GUILayout.BeginHorizontal(frameStyle);
GUILayout.BeginVertical();
EditorGUILayout.PropertyField(serializedObject.FindProperty("characterData"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("SaveID"));
GUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(serializedObject.FindProperty("loadMode"), GUILayout.ExpandWidth(true));
var async = serializedObject.FindProperty("async");
EditorGUILayout.LabelField("Async", GUILayout.Width(50));
async.boolValue = EditorGUILayout.Toggle(async.boolValue, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Save Character ID"))
{
system.SaveByID();
}
if (GUILayout.Button("Load Character ID"))
{
system.LoadFromID();
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
if (system.characterData)
{
if (system.characterData.icon != null)
{
// Control the size of the image
float size = 64;
Rect rect = GUILayoutUtility.GetRect(size, size, GUILayout.ExpandWidth(false));
EditorGUI.DrawTextureTransparent(rect, system.characterData.icon);
}
}
GUILayout.EndHorizontal();
GUIContent mergedTooltip = new GUIContent("(Merged Mode)", "");
GUIContent dyanmicTooltip = new GUIContent("(Dynamic Mode)", "");
if (system.mergedMode)
{
GUI.color = Color.green;
if (GUILayout.Button(mergedTooltip, GUILayout.Height(30)))
{
system.mergedMode = false;
}
GUI.color = originalColor;
}
else
{
GUI.color = Color.yellow;
if (GUILayout.Button(dyanmicTooltip, GUILayout.Height(30)))
{
system.mergedMode = true;
}
GUI.color = originalColor;
}
//MERGED OPTIONS
showMergedOptions = EditorGUILayout.Foldout(showMergedOptions, "Merge Options", true);
GUILayout.BeginVertical(frameStyle);
if (showMergedOptions)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(serializedObject.FindProperty("mergeMaterial"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("prefabName"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("materialData"));
GUILayout.BeginHorizontal(frameStyle);
EditorGUILayout.PropertyField(serializedObject.FindProperty("mergeOnAwake"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("autoUpdate"));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(frameStyle);
if (GUILayout.Button("Merge Character"))
{
system.MergeCharacter();
}
if (GUILayout.Button("Save as Prefab"))
{
system.SaveCharacterToPrefab();
}
GUILayout.EndHorizontal();
EditorGUI.indentLevel--;
}
GUILayout.EndVertical();
dependencies = EditorGUILayout.Foldout(dependencies, "Dependencies", true);
if (dependencies)
{
GUILayout.BeginHorizontal(frameStyle);
EditorGUILayout.PropertyField(serializedObject.FindProperty("CharacterBody"));
GUILayout.EndHorizontal();
}
serializedObject.ApplyModifiedProperties();
//base.OnInspectorGUI();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: b5460613c21ed8c41b9ed135d1a20b49
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/Editor/OutfitSystemEditor.cs
uploadId: 853356

View File

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

View File

@@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public interface IOutfitExtension
{
string GetID();
void Initalize(OutfitSystem outfitSystem, Outfit outfit);
void Execute(OutfitSystem outfitSystem, Outfit outfit);
//Return Something from this object
//Great when you have a Custom Map that you need read for the CharacterOptimizer
object GetValue();
System.Type GetValueType();
}
public interface IOutfitExtension<T> : IOutfitExtension
{
//Return Something from this object
//Great when you have a Custom Map that you need read for the CharacterOptimizer
new T GetValue();
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 95def551e1cef5f45bbb17fef6f038b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/Interfaces/IOutfitExtension.cs
uploadId: 853356

View File

@@ -0,0 +1,470 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class Outfit : OutfitBase
{
public bool Initalized { get; set; }
[SerializeField] bool AttachInEditMode;
private OutfitSystem system;
//[Header("Character Creator Settings")]
public string OutfitName;
public Sprite OutfitIcon;
public string[] ColorChannels = new string[] { "Base" };
public string TextureCatagory;
public bool supportDecals;
public bool supportPatterns;
public bool showCharacterCreator = true;
public SkinnedMeshRenderer skinnedRenderer { get; private set; }
public SkinnedMeshRenderer[] skinnedRenderers { get; private set; }
public Renderer outfitRenderer { get; private set; }
//[field: Header("Outfit Settings")]
[SerializeField] public OutfitType Type;
public string AttachPoint;
public Color[] defaultColors;
public string[] tags;
private Dictionary<string, int> tagShapes = new Dictionary<string, int>();
private Dictionary<string, int> shapes = new Dictionary<string, int>();
public LinkedColorSets[] LinkedColorSets;
public OutfitType[] IncompatibleSets;
//[Header("User Settings")]
public int currentSwatch;
public List<OutfitSwatch> outfitSwatches = new List<OutfitSwatch>();
public Transform[] originalBones;
public Transform originalRootBone;
public Transform editorAttachPoint;
private void OnValidate()
{
if (Application.isPlaying && gameObject.scene.isLoaded)
{
if (system == null) system = GetComponentInParent<OutfitSystem>();
SetColorInital();
}
#if UNITY_EDITOR
if (AttachInEditMode && !Application.isPlaying) SoftAttach();
#endif
}
private void Awake()
{
skinnedRenderer = GetComponentInChildren<SkinnedMeshRenderer>();
if (skinnedRenderer) material = skinnedRenderer.material;
skinnedRenderers = GetComponentsInChildren<SkinnedMeshRenderer>();
outfitRenderer = GetComponentInChildren<Renderer>();
foreach (var smr in skinnedRenderers)
{
smr.sharedMaterial = material;
}
InitSetUpShapes();
}
private void OnEnable()
{
if (!Initalized) Attach();
}
private void OnDisable()
{
if (!system) return;
system.OnOutfitChanged -= OnOutfitUpdate;
system.OnShapeChanged -= SetShape;
system.RemoveOutfit(this, false);
}
private void OnDestroy()
{
if (!system) return;
system.OnOutfitChanged -= OnOutfitUpdate;
}
private void Start()
{
if (Application.isPlaying && gameObject.scene.isLoaded)
{
if (!Initalized) Attach();
}
SetColorInital();
}
public void Attach(Transform parent)
{
transform.parent = parent;
Attach();
}
public void Attach(OutfitSystem system)
{
transform.parent = system.transform;
Attach();
}
public void Attach()
{
system = GetComponentInParent<OutfitSystem>();
skinnedRenderer = GetComponentInChildren<SkinnedMeshRenderer>();
outfitRenderer = GetComponentInChildren<Renderer>();
if (system == null) return;
if (!system.initalized) return;
var extensions = GetComponentsInChildren<IOutfitExtension>();
foreach (var item in extensions) { item.Initalize(system, this); }
//Reassigning original bones incase it was attached in editor
if (originalBones.Length > 0 && skinnedRenderer)
{
skinnedRenderer.bones = originalBones;
skinnedRenderer.rootBone = originalRootBone;
}
system.OnOutfitChanged += OnOutfitUpdate;
system.OnShapeChanged += SetShape;
system.AttachOutfit(this);
RemoveIncompatible();
CheckTags();
CopySystemShapes();
foreach (var item in extensions) { item.Execute(system, this); }
}
#region OnUpdate Methods
private void OnOutfitUpdate(Outfit newOutfit)
{
if (RemoveIfIncompatible(newOutfit)) return;
CheckTags();
}
private void CheckTags()
{
var shapes = new List<string>(tagShapes.Keys);
if (!skinnedRenderer) return;
for (int i = 0; i < shapes.Count; i++)
{
var yes = system.ContainsTag(shapes[i]);
if (yes) { skinnedRenderer.SetBlendShapeWeight(tagShapes[shapes[i]], 100); }
else { skinnedRenderer.SetBlendShapeWeight(tagShapes[shapes[i]], 0); }
}
}
#endregion
#region Shapes Methods
private void CopySystemShapes()
{
if (system)
{
var shapesKeys = shapes.Keys.ToArray();
for (int i = 0; i < shapesKeys.Length; i++)
{
var systemValue = system.GetShape(shapesKeys[i]);
if (systemValue == -10000) continue;
SetShape(shapesKeys[i], systemValue);
}
}
}
private void InitSetUpShapes()
{
if (!skinnedRenderer) return;
var mesh = skinnedRenderer.sharedMesh;
var blendShapeCount = skinnedRenderer.sharedMesh.blendShapeCount;
for (int i = 0; i < blendShapeCount; i++)
{
var blendFullName = mesh.GetBlendShapeName(i);
var blendName = mesh.GetBlendShapeName(i);
//removing nameshape that maya gives
var sort = blendName.Split(".");
if (sort.Length > 1) { blendName = sort[1]; }
sort = blendName.Split("_");
if (sort.Length > 1)
{
if (sort[0] == "Tag") { tagShapes.Add(sort[1], i); }
if (sort[0] == "Shape")
{
shapes.Add(sort[1], i);
}
}
}
}
public void SetShape(string key, float value)
{
if (!skinnedRenderer) return;
var sort = key.Split(".");
if (sort.Length > 1) { key = sort[1]; }
if (!shapes.TryGetValue(key, out int index)) return;
foreach (var smr in skinnedRenderers)
{
smr.SetBlendShapeWeight(index, value);
}
}
#endregion
#region Incompatible Outfit Methods
private void RemoveIncompatible()
{
foreach (var item in IncompatibleSets)
{
system.RemoveOutfit(item, true);
}
}
private bool RemoveIfIncompatible(Outfit outfit)
{
if (outfit == null) return false;
foreach (var item in IncompatibleSets)
{
if (outfit.Type == item)
{
system.RemoveOutfit(this, true);
return true;
}
}
return false;
}
#endregion
#region Color Methods
private void SetColorInital()
{
if (!outfitRenderer) return;
var mat = outfitRenderer.material;
for (int i = 0; i < defaultColors.Length; i++)
{
mat.SetColor("_Color_" + (1 + i), defaultColors[i]);
}
}
public override void SetColor(Color color, int index, bool linkedChanged = false)
{
if (system == null) { system = GetComponentInParent<OutfitSystem>(); }
if (outfitRenderer == null) { outfitRenderer = GetComponentInChildren<Renderer>(); }
if (customShader)
{
SetColor(color);
}
else
{
outfitRenderer.material.SetColor("_Color_" + index, color);
}
foreach (var item in LinkedColorSets)
{
if (!linkedChanged)
{
var linkedOutfit = system.GetOutfit(item.linkedType);
if (linkedOutfit == null) continue;
if (index > item.linkedChannelRange) continue;
linkedOutfit.SetColor(color, index, true);
}
}
}
public override void SetSwatch(int swatchIndex, bool linkedChanged = false)
{
if (!customShader) return;
if (!material) { material = GetComponentInChildren<Renderer>().material; }
if (swatchIndex + 1 > outfitSwatches.Count) return;
var swatchID = outfitSwatches[swatchIndex].swatchID;
var tex = Resources.Load<Texture>(swatchID);
material.mainTexture = tex;
currentSwatch = swatchIndex;
foreach (var item in LinkedColorSets)
{
if (!linkedChanged)
{
var linkedOutfit = system.GetOutfit(item.linkedType);
if (linkedOutfit == null) continue;
linkedOutfit.SetSwatch(swatchIndex, true);
}
}
}
public OutfitData GetOutfitData()
{
var outfitData = new OutfitData();
var path = Type.name + "/" + name;
path = path.Replace("(Clone)", "");
outfitData.outfit = path;
if (customShader)
{
outfitData.color = GetColor(1);
outfitData.swatch = currentSwatch;
}
else
{
outfitData.colors = GetColors();
var decal = GetDecal();
if (decal != null)
{
outfitData.decal = "Decal/" + decal.name;
outfitData.decalColors = GetDecalColors();
outfitData.decalScale = GetDecalSize();
}
else
{
outfitData.decal = "";
}
var pattern = GetPattern();
if (pattern != null)
{
outfitData.pattern = "Pattern/" + pattern.name;
outfitData.patternColors = GetPatternColors();
outfitData.patternScale = GetPatternSize();
}
else
{
outfitData.pattern = "";
}
}
return outfitData;
}
#endregion
#region Soft Attach
#if UNITY_EDITOR
public void SoftAttach()
{
var system = GetComponentInParent<OutfitSystem>();
if (system == null)
{
//return bones if no longer attach to system
SoftDetach();
return;
}
system.SoftAttach(this);
}
public void SoftDetach()
{
editorAttachPoint = null;
if (originalBones.Length > 0)
{
var skinnedRenderer = GetComponentInChildren<SkinnedMeshRenderer>();
if (skinnedRenderer == null) return;
skinnedRenderer.bones = originalBones;
skinnedRenderer.rootBone = originalRootBone;
originalBones = new Transform[0];
originalRootBone = null;
}
}
#endif
#endregion
#region Magicka Cloth2
private void InitCloth()
{
/*
#if MAGICACLOTH2
var cloth = GetComponentInChildren<MagicaCloth2.MagicaCloth>();
if (!cloth) return;
cloth.enabled = false;
cloth.Initialize();
cloth.DisableAutoBuild();
#endif
*/
}
public void ActivateCloth(Dictionary<string, Transform> boneMap)
{
/*
#if MAGICACLOTH2
var cloth = GetComponentInChildren<MagicaCloth2.MagicaCloth>();
if (!cloth) return;
cloth.ReplaceTransform(boneMap);
var col = system.GetClothColliders();
List<MagicaCloth2.ColliderComponent> ClothColliders = col
.Where(m => m != null)
.Select(m => m.GetComponent<MagicaCloth2.ColliderComponent>())
.ToList();
cloth.SerializeData.colliderCollisionConstraint.colliderList = ClothColliders;
cloth.enabled = true;
#endif
*/
}
#endregion
}
[System.Serializable]
public class OutfitSwatch
{
public string swatchID;
public Color IconColorTop = Color.white;
public Color IconColorBottom = Color.black;
}
[System.Serializable]
public class LinkedColorSets
{
public OutfitType linkedType;
[Range(1, 9)] public int linkedChannelRange;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: db36749fc04f0fd4693c063c504270a1

View File

@@ -0,0 +1,202 @@
using System.Collections.Generic;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public abstract class OutfitBase : MonoBehaviour
{
public bool customShader;
protected Material material;
private void Awake()
{
material = GetComponentInChildren<Renderer>().material;
}
public virtual void SetColor(Color color, int index, bool linkedChanged = false)
{
}
public virtual void SetColor(Color color)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
if (material.HasProperty("_Color_1"))
{
material.SetColor("_Color_1", color);
}
else if (material.HasProperty("_Color"))
{
material.SetColor("_Color", color);
}
else if (material.HasProperty("_MainColor"))
{
material.SetColor("_MainColor", color);
}
}
public virtual List<Color> GetColors()
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
var colors = new List<Color>();
if (customShader)
{
colors.Add(material.color);
return colors;
}
for (int i = 1; i <= 9; i++)
{
colors.Add(material.GetColor("_Color_" + i));
}
return colors;
}
public virtual Color GetColor(int channel)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
if (customShader)
{
if (material.HasProperty("_Color_1"))
{
return material.GetColor("_Color_1");
}
else if (material.HasProperty("_Color"))
{
return material.GetColor("_Color");
}
else if (material.HasProperty("_MainColor"))
{
return material.GetColor("_MainColor");
}
else
{
return Color.white;
}
}
return material.GetColor("_Color_" + channel);
}
public virtual void SetSwatch(int swatchIndex, bool linkedChange = false)
{
}
public virtual void SetDecal(Texture texture)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
if(texture == null) material.SetTexture("_DecalMap", null);
else material.SetTexture("_DecalMap", texture);
}
public virtual void SetDecalSize(Vector4 size)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
material.SetVector("_DecalScale", size);
}
public virtual Vector4 GetDecalSize()
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
var v = material.GetVector("_DecalScale");
return new Vector4(v.x, v.y , 0 ,0);
}
public virtual Texture GetDecal()
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
return material.GetTexture("_DecalMap");
}
public virtual void SetDecalColor(Color color, int index)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
material.SetColor("_DecalColor_" + index, color);
}
public virtual Color GetDecalColor(int index)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
return material.GetColor("_DecalColor_" + index);
}
public virtual List<Color> GetDecalColors()
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
var colors = new List<Color>();
for (int i = 1; i < 4; i++)
{
colors.Add(material.GetColor("_DecalColor_" + i));
}
return colors;
}
public virtual void SetPattern(Texture texture)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
material.SetTexture("_PatternMap", texture);
}
public virtual Texture GetPattern()
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
return material.GetTexture("_PatternMap");
}
public virtual void SetPatternColor(Color color, int index)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
material.SetColor("_PatternColor_" + index, color);
}
public virtual Color GetPatternColor(int index)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
return material.GetColor("_PatternColor_" + index);
}
public virtual List<Color> GetPatternColors()
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
var colors = new List<Color>();
for (int i = 1; i < 4; i++)
{
colors.Add(material.GetColor("_PatternColor_" + i));
}
return colors;
}
public virtual void SetPatternSize(Vector2 size)
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
material.SetVector("_PatternScale", size);
}
public virtual Vector4 GetPatternSize()
{
if (!material) { material = GetComponentInChildren<Renderer>().material; }
var v = material.GetVector("_PatternScale");
return new Vector4(v.x, v.y, 0 ,0);
}
public virtual void SetBaseTexture(Texture texture, Texture normalTexture = null)
{
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1e1c13099198aba47bbec60b5fea3afb

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class OutfitFollowBlendShapes : MonoBehaviour, IOutfitExtension
{
OutfitSystem system;
SkinnedMeshRenderer mesh;
SkinnedMeshRenderer followTarget;
[SerializeField] OutfitType follow;
[SerializeField] List<Vector2> shapes = new List<Vector2>();
private void OnDestroy()
{
if (system == null) return;
system.OnOutfitChanged -= OnNewSetUpHead;
}
private void Init()
{
}
private void OnNewSetUpHead(Outfit outfit)
{
if (outfit == null) { return; }
if (outfit.Type != follow) { return; }
if (!outfit.skinnedRenderer) { return; }
followTarget = outfit.skinnedRenderer;
SetUp();
}
private void SetUp()
{
mesh = GetComponentInChildren<SkinnedMeshRenderer>();
var characterShapeTitle = followTarget.sharedMesh.GetBlendShapeName(0);
var sort = characterShapeTitle.Split(".");
if (sort.Length > 1) { characterShapeTitle = sort[0] + "."; }
else { characterShapeTitle = ""; }
shapes.Clear();
for (int i = 0; i < mesh.sharedMesh.blendShapeCount; i++)
{
var shapeName = mesh.sharedMesh.GetBlendShapeName(i);
sort = shapeName.Split(".");
if (sort.Length > 1) { shapeName = sort[1]; }
var shapeIndex = followTarget.sharedMesh.GetBlendShapeIndex(characterShapeTitle + shapeName);
if (shapeIndex != -1)
{
//print(characterShapeTitle + " | " + shapeName + " | " + shapeIndex);
shapes.Add(new Vector2 (i,shapeIndex));
}
}
}
private void Update()
{
if (followTarget == null) return;
for (int i = 0; i < shapes.Count; i++)
{
mesh.SetBlendShapeWeight((int)shapes[i].x, followTarget.GetBlendShapeWeight((int)shapes[i].y));
}
}
public string GetID()
{
return "BlendShapeFollow";
}
public void Initalize(OutfitSystem outfitSystem, Outfit outfit)
{
system = outfitSystem;
if (system == null) return;
system.OnOutfitChanged += OnNewSetUpHead;
mesh = outfit.skinnedRenderer;
var followOutfit = system.GetOutfit(follow);
if (followOutfit == null) { return; }
if (followOutfit.skinnedRenderer == null) { return; }
followTarget = followOutfit.skinnedRenderer;
SetUp();
}
public void Execute(OutfitSystem outfitSystem, Outfit outfit)
{
}
public object GetValue()
{
return null;
}
public Type GetValueType()
{
return null;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 497fa68147501dc4f81acb60c2647e46

View File

@@ -0,0 +1,27 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class OutfitHeightChange : MonoBehaviour
{
[SerializeField] float HeightOffset;
private void OnEnable()
{
var System = GetComponentInParent<OutfitSystem>();
if (System == null) return;
System.SetHeight(HeightOffset);
}
private void OnDisable()
{
var System = GetComponentInParent<OutfitSystem>();
if (System == null) return;
System.SetHeight(0);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 56c7d0af527584d479702c3f4242abb3

View File

@@ -0,0 +1,47 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class OutfitHideByTag : MonoBehaviour
{
OutfitSystem system;
[SerializeField] HideSettings[] settings;
public void OnEnable()
{
system = GetComponentInParent<OutfitSystem>();
if (!system) return;
system.OnOutfitChanged += SetHide;
}
public void OnDisable()
{
system = GetComponentInParent<OutfitSystem>(true);
if (!system) return;
system.OnOutfitChanged -= SetHide;
}
private void SetHide(Outfit arg0)
{
foreach (var item in settings)
{
if (system.ContainsTag(item.tag))
{
item.renderer.gameObject.SetActive(false);
}
else
{
item.renderer.gameObject.SetActive(true);
}
}
}
[System.Serializable]
private struct HideSettings
{
public SkinnedMeshRenderer renderer;
public string tag;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d588c07bc45fc674499da992f84b5d29

View File

@@ -0,0 +1,47 @@
using UnityEngine;
using UnityEngine.UI;
namespace Bozo.AnimeCharacters
{
public class OutfitSelector : MonoBehaviour
{
public Image icon;
private Outfit outfit;
private CharacterCreator characterCreator;
private Button button;
public void Init(Outfit outfit, CharacterCreator characterCreator)
{
//icon = GetComponentInChildren<Image>();
button = GetComponentInChildren<Button>();
button.onClick.AddListener(OnSelect);
this.outfit = outfit;
this.characterCreator = characterCreator;
icon.overrideSprite = this.outfit.OutfitIcon;
}
private void OnSelect()
{
characterCreator.SetOutfit(outfit);
}
public void SetVisable(string type)
{
if (outfit.Type == null)
{
gameObject.SetActive(false);
Debug.LogWarning(outfit.name + " is missing an outfitType and will not show in the character creator");
return;
}
if(outfit.Type.name == type)
{
gameObject.SetActive(true);
}
else
{
gameObject.SetActive(false);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b046ca2a12a9c3846a325943ca101458

View File

@@ -0,0 +1,989 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
namespace Bozo.AnimeCharacters
{
public class OutfitSystem : MonoBehaviour
{
//[Header("Save Data")]
public CharacterObject characterData;
private CharacterObject _characterData;
public string SaveID;
//[Header("Dependencies")]
[SerializeField] SkinnedMeshRenderer CharacterBody;
//Height
public bool muteHeightChange { get; private set; }
public float height { get; private set; }
//Animation
public Animator animator
{
get
{
if (_animator == null)
{
_animator = GetComponentInParent<Animator>();
if (_animator == null) { _animator = GetComponentInChildren<Animator>(); }
}
return _animator;
}
private set
{ _animator = value; }
}
private Animator _animator;
public float stance { get; private set; }
//Dimensions
private Bounds CharacterRenderBounds;
Dictionary<string, Transform> boneMap = new Dictionary<string, Transform>();
//Outfits
public Dictionary<OutfitType, Outfit> Outfits = new Dictionary<OutfitType, Outfit>();
public Dictionary<string, OutfitType> KnownOutfitTypes = new Dictionary<string, OutfitType>();
//Shapes
private Dictionary<string, int> bodyShapes = new Dictionary<string, int>();
private Dictionary<string, int> faceShapes = new Dictionary<string, int>();
private Dictionary<string, int> tagShapes = new Dictionary<string, int>();
public Dictionary<string, BodyShapeModifier> bodyModifiers = new Dictionary<string, BodyShapeModifier>();
private List<string> tags = new List<string>();
//Events
public UnityAction<Outfit> OnOutfitChanged;
public UnityAction<SkinnedMeshRenderer> OnRigChanged;
public UnityAction<string, float> OnShapeChanged;
public bool initalized { get; private set; }
// Merged Properties
public string prefabName;
public Material mergeMaterial;
public bool mergedMode;
public bool mergeBase;
public bool mergeOnAwake;
public bool autoUpdate;
public CharacterData data;
private Dictionary<string, OutfitData> outfitData = new Dictionary<string, OutfitData>();
public Dictionary<string,Texture2D> customMaps = new Dictionary<string, Texture2D>();
public bool isDirty { get; private set; }
public MergedMaterialData[] materialData;
public enum LoadMode { OnStartAndOnValidate, OnStart, Manual}
public LoadMode loadMode;
public bool async;
#if MAGICACLOTH2
//MagicaCloth
private MagicaCloth2.ColliderComponent[] ClothColliders;
#endif
private void OnValidate()
{
if (Application.isPlaying && gameObject.scene.isLoaded && loadMode == LoadMode.OnStartAndOnValidate)
{
Invoke("LoadFromObject", 0f);
}
}
private void Awake()
{
Init();
if (mergeOnAwake) mergedMode = true;
}
private void Start()
{
if (loadMode == LoadMode.OnStart || loadMode == LoadMode.OnStartAndOnValidate)
{
LoadFromObject();
}
}
#region Initalizers
public void Init()
{
if (initalized) return;
if (CharacterBody == null)
{
Debug.LogWarning("Outfit System does not have a Rig assigned please assign one to prevent this warning", gameObject);
Debug.LogWarning("Attempting auto rig assignment...");
var skinnedMeshes = GetComponentsInChildren<SkinnedMeshRenderer>(true);
foreach (var item in skinnedMeshes)
{
if (item.name == "BMAC_Body")
{
CharacterBody = item;
Debug.Log("Rig Found Successfully!");
break;
}
}
Debug.LogError("Search Failed. Please Assign Mannually", gameObject);
return;
}
CharacterRenderBounds = CharacterBody.localBounds;
InitBoneMap();
InitBodyShapes();
InitBodyMods();
InitClothColliders();
initalized = true;
}
private void InitBoneMap()
{
boneMap.Clear();
foreach (Transform bone in CharacterBody.bones)
{
if (boneMap.ContainsKey(bone.name) == false)
{
boneMap.Add(bone.name, bone);
}
}
}
private void InitBodyShapes()
{
var body = GetOutfit("Body");
bodyShapes.Clear();
tagShapes.Clear();
Mesh mesh;
int blendShapeCount = 0;
if (body != null)
{
mesh = body.skinnedRenderer.sharedMesh;
blendShapeCount = body.skinnedRenderer.sharedMesh.blendShapeCount;
}
else
{
mesh = CharacterBody.sharedMesh;
blendShapeCount = CharacterBody.sharedMesh.blendShapeCount;
}
for (int i = 0; i < blendShapeCount; i++)
{
var blendFullName = mesh.GetBlendShapeName(i);
var blendName = mesh.GetBlendShapeName(i);
//removing nameshape that maya gives
var sort = blendName.Split(".");
if (sort.Length > 1) { blendName = sort[1]; }
sort = blendName.Split("_");
if (sort.Length > 1)
{
if (sort[0] == "Shape") { bodyShapes.Add(sort[1], i); }
if (sort[0] == "Tag") { tagShapes.Add(sort[1], i); }
}
}
}
private void InitBodyMods()
{
var bodyMods = new List<BodyShapeModifier>(GetComponentsInChildren<BodyShapeModifier>());
bodyModifiers.Clear();
for (int i = 0; i < bodyMods.Count; i++)
{
bodyModifiers.Add(bodyMods[i].name, bodyMods[i]);
}
}
private void InitFaceShapes()
{
var head = GetOutfit("Head");
faceShapes.Clear();
Mesh mesh;
if (head != null)
{
mesh = head.skinnedRenderer.sharedMesh;
}
else
{
mesh = CharacterBody.sharedMesh;
}
var blendShapeCount = mesh.blendShapeCount;
for (int i = 0; i < blendShapeCount; i++)
{
var blendFullName = mesh.GetBlendShapeName(i);
var blendName = mesh.GetBlendShapeName(i);
//removing nameshape that maya gives
var sort = blendName.Split(".");
if (sort.Length > 1) { blendName = sort[1]; }
sort = blendName.Split("_");
if (sort.Length > 1)
{
if (sort[0] == "Shape") { faceShapes.Add(sort[1], i); }
}
}
}
#endregion
private void InitClothColliders()
{
#if MAGICACLOTH2
ClothColliders = GetComponentsInChildren<MagicaCloth2.ColliderComponent>();
#endif
}
#region Saving and Loading
public void LoadFromObject(CharacterObject saveData)
{
characterData = saveData;
LoadFromObject();
}
[ContextMenu("Load")]
public void LoadFromObject()
{
if (characterData)
{
if (_characterData != characterData)
{
SaveID = characterData.name;
if (mergedMode)
{
data = characterData.data;
isDirty = true;
MergeCharacter();
}
else
{
_characterData = characterData;
LoadCharacter(characterData.data);
}
}
}
}
[ContextMenu("LoadByID")]
public void LoadFromID()
{
LoadFromID(SaveID);
}
public void LoadFromID(string saveName)
{
if (string.IsNullOrEmpty(saveName)) return;
SaveID = saveName;
var data = BMAC_SaveSystem.GetDataFromID(SaveID);
if (data == null) return;
LoadCharacter(data);
}
private async void LoadCharacter(CharacterData data)
{
if (mergedMode)
{
this.data = data;
isDirty = true;
MergeCharacter();
}
else
{
await BMAC_SaveSystem.LoadCharacter(this, data, false, async);
}
}
[ContextMenu("SaveToObject")]
public void SaveToObject()
{
if (!characterData)
{
Debug.LogWarning("Character Data Field is empty. Please provide a BSMC_CharacterObject to " + transform.name);
return;
}
BMAC_SaveSystem.SaveCharacter(this, characterData.data.characterName, characterData.icon);
}
[ContextMenu("SaveByID")]
public void SaveByID()
{
SaveByID(SaveID);
}
public void SaveByID(string characterName)
{
if (string.IsNullOrEmpty(characterName))
{
Debug.LogWarning("No ID provided saving aborted");
return;
}
//Creating EmptyIcon
if (!System.IO.File.Exists(BMAC_SaveSystem.iconFilePath + "/" + characterName + ".png"))
{
Texture2D tex = new Texture2D(2, 2, TextureFormat.RGBA32, false);
byte[] bytes = tex.EncodeToPNG();
System.IO.File.WriteAllBytes(BMAC_SaveSystem.iconFilePath + "/" + characterName + ".png", bytes);
}
BMAC_SaveSystem.SaveCharacter(this, characterName);
}
#endregion
#region Outfit Removeal
public void RemoveOutfit(Outfit outfit, bool destory)
{
if (Outfits.TryGetValue(outfit.Type, out Outfit currentOutfitInSlot))
{
if (destory == true && currentOutfitInSlot != null)
{
Destroy(currentOutfitInSlot.gameObject);
Outfits[outfit.Type] = null;
}
}
RemoveTags(outfit);
OnOutfitChanged?.Invoke(null);
}
public void RemoveOutfit(OutfitType type, bool destory)
{
if (Outfits.TryGetValue(type, out Outfit currentOutfitInSlot))
{
if (destory == true && currentOutfitInSlot != null)
{
Destroy(currentOutfitInSlot.gameObject);
Outfits[type] = null;
}
}
RemoveTags(currentOutfitInSlot);
OnOutfitChanged?.Invoke(null);
}
public void RemoveTags(Outfit removedOutfit)
{
if (removedOutfit == null) return;
tags.RemoveAll(item => removedOutfit.tags.Contains(item));
}
public void RemoveAllOutfits()
{
List<Outfit> list = new List<Outfit>(Outfits.Values);
foreach (var item in list)
{
if (item == null) continue;
Destroy(item.gameObject);
}
Outfits.Clear();
tags.Clear();
OnOutfitChanged?.Invoke(null);
}
#endregion
public Outfit InstantiateOutfit(Outfit outfit)
{
var inst = Instantiate(outfit, transform);
inst.name = inst.name.Replace("(Clone)", "");
return inst;
}
public void AttachOutfit(Outfit outfit)
{
if (!initalized) return;
if (mergedMode)
{
outfitData[outfit.Type.name] = outfit.GetOutfitData();
data.outfitDatas = outfitData.Values.ToList();
isDirty = true;
Destroy(outfit.gameObject);
if (autoUpdate) MergeCharacter();
return;
}
if (!KnownOutfitTypes.ContainsKey(outfit.Type.name))
{
KnownOutfitTypes.Add(outfit.Type.name, outfit.Type);
}
//check if an outfit is already in that slot and replace it
ReplaceOutfit(outfit);
//Merging outfit bones or attaching outfit to specified bone
MergeBones(outfit);
//Adjusting Mesh bounds so the meshes don't unexpectingly disappear.
if (outfit.skinnedRenderer)
{
UpdateCharacterBounds(outfit);
}
//Apply the Current Body Morphs to the Outfit
ApplyShapesToOufit(outfit);
//If Head get its Morphs
if (outfit.Type.name == "Head") { InitFaceShapes(); }
//If Body get its Morphs
if (outfit.Type.name == "Body") { InitBodyShapes(); }
tags.AddRange(outfit.tags);
ApplyTags();
OnOutfitChanged?.Invoke(outfit);
}
private void ApplyShapesToOufit(Outfit outfit)
{
var keys = new List<string>(bodyShapes.Keys);
for (int i = 0; i < keys.Count; i++)
{
outfit.SetShape(keys[i], bodyShapes[keys[i]]);
}
}
public void SetShape(string key, float value)
{
SkinnedMeshRenderer renderer = null;
var index = -1;
var body = GetOutfit("Body");
var head = GetOutfit("Head");
if (bodyShapes.TryGetValue(key, out int bodyValue) && body)
{
index = bodyValue;
if (body != null) { renderer = body.skinnedRenderer; }
}
else if (faceShapes.TryGetValue(key, out int faceValue) && head)
{
index = faceValue;
if (head != null) { renderer = head.skinnedRenderer; }
}
else
{
if (bodyShapes.TryGetValue(key, out int blendValue))
{
index = blendValue;
renderer = CharacterBody;
}
}
if (renderer != null) renderer.SetBlendShapeWeight(index, value);
OnShapeChanged?.Invoke(key, value);
}
private void ApplyTags()
{
// This method is intented for when you merged the body but still want to attach outfits dynamically
if(GetOutfit("Body") != null) { return; }
var shapes = new List<string>(tagShapes.Keys);
if (!CharacterBody) return;
if (CharacterBody.sharedMesh.blendShapeCount == 0) return;
for (int i = 0; i < shapes.Count; i++)
{
var yes = ContainsTag(shapes[i]);
if (yes) { CharacterBody.SetBlendShapeWeight(tagShapes[shapes[i]], 100); }
else { CharacterBody.SetBlendShapeWeight(tagShapes[shapes[i]], 0); }
}
}
public void SetStance(float value)
{
animator.SetFloat("Stance", value);
stance = value;
}
public void SetHeight(float value)
{
//remove Previous Height
transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y - height, transform.localPosition.z);
//Apply New Height
height = value;
if (!muteHeightChange)
{
transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y + value, transform.localPosition.z);
}
}
public void MuteHeightChange(bool value)
{
if (value == muteHeightChange) return;
muteHeightChange = value;
var height = this.height;
if (muteHeightChange)
{
height = -height;
}
transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y + height, transform.localPosition.z);
}
private void ReplaceOutfit(Outfit outfit)
{
if (Outfits.TryGetValue(outfit.Type, out Outfit currentOutfitInSlot))
{
if (Outfits[outfit.Type])
{
if (outfit.transform != Outfits[outfit.Type].transform)
{
Destroy(currentOutfitInSlot.gameObject);
}
else
{
OnOutfitChanged?.Invoke(outfit);
}
}
Outfits[outfit.Type] = outfit;
}
else
{
Outfits.Add(outfit.Type, outfit);
}
}
private void MergeBones(Outfit outfit)
{
foreach (var smr in outfit.skinnedRenderers)
{
var renderer = smr;
if (outfit.AttachPoint == "" && renderer)
{
if (outfit.Initalized == false)
{
var oldBones = renderer.bones.ToArray();
var newBones = new Transform[renderer.bones.Length];
for (int i = 0; i < oldBones.Length; i++)
{
var bone = oldBones[i];
boneMap.TryGetValue(bone.name, out Transform baseBone);
if (bone == baseBone)
{
newBones[i] = baseBone;
continue;
}
else
{
newBones[i] = baseBone;
//Destroy(bone.gameObject);
}
}
renderer.bones = newBones;
renderer.rootBone = CharacterBody.rootBone;
}
}
else
{
Transform bone = null;
try
{
bone = boneMap[outfit.AttachPoint];
}
catch
{
Debug.LogError(name + " is missing " + outfit.AttachPoint + " that " + outfit.name + " requires");
return;
}
outfit.transform.parent = bone.transform;
outfit.transform.position = bone.position;
outfit.transform.rotation = bone.rotation;
outfit.transform.localScale = Vector3.one;
}
}
outfit.ActivateCloth(boneMap);
outfit.Initalized = true;
if (outfit.outfitRenderer && outfit.AttachPoint != "")
{
Transform bone = null;
try
{
bone = boneMap[outfit.AttachPoint];
}
catch
{
Debug.LogError(name + " is missing " + outfit.AttachPoint + " that " + outfit.name + " requires");
return;
}
outfit.transform.parent = bone.transform;
outfit.transform.position = bone.position;
outfit.transform.rotation = bone.rotation;
outfit.transform.localScale = Vector3.one;
}
}
public void UpdateCharacterBounds(Outfit outfit)
{
foreach (var item in Outfits.Values)
{
if (item == null) continue;
foreach (var smr in item.skinnedRenderers)
{
if (smr != null) smr.localBounds = CharacterRenderBounds;
}
}
}
public bool ContainsTag(string tag)
{
return tags.Contains(tag);
}
#region Getters
public Outfit GetOutfit(OutfitType outfitType)
{
if (Outfits.TryGetValue(outfitType, out Outfit item))
{
return item;
}
return null;
}
public Outfit GetOutfit(string outfitType)
{
if (KnownOutfitTypes.TryGetValue(outfitType, out OutfitType type))
{
if (Outfits.TryGetValue(type, out Outfit item))
{
return item;
}
}
return null;
}
public List<Outfit> GetOutfits()
{
return new List<Outfit>(Outfits.Values);
}
public List<string> GetShapes()
{
return bodyShapes.Keys.ToList();
}
public List<string> GetFaceShapes()
{
return faceShapes.Keys.ToList();
}
#if MAGICACLOTH2
public MagicaCloth2.ColliderComponent[] GetClothColliders()
{
return ClothColliders;
}
#endif
public float GetShape(string key)
{
if (bodyShapes.TryGetValue(key, out int value))
{
var body = GetOutfit("Body");
if (body != null)
{
var weightValue = body.skinnedRenderer.GetBlendShapeWeight(value);
return weightValue;
}
else return -10000;
}
else return -10000;
}
public Dictionary<string, BodyShapeModifier> GetMods()
{
return bodyModifiers;
}
public Dictionary<string, Transform> GetBones()
{
return boneMap;
}
public float GetShapeValue(string key)
{
var weight = -1f;
var body = GetOutfit("Body");
if (body == null) return -1;
if (bodyShapes.TryGetValue(key, out int bodyValue))
{
weight = body.skinnedRenderer.GetBlendShapeWeight(bodyValue);
}
else if (faceShapes.TryGetValue(key, out int faceValue))
{
var face = GetOutfit("Head");
if (face == null) return -1;
weight = face.skinnedRenderer.GetBlendShapeWeight(faceValue);
}
return weight;
}
public float GetShapeValue(int key)
{
SkinnedMeshRenderer renderer;
var body = GetOutfit("Body");
if (body == null) renderer = CharacterBody;
else renderer = body.skinnedRenderer;
var weightValue = renderer.GetBlendShapeWeight(key);
return weightValue;
}
public Dictionary<string, float> GetBodyShapeValues()
{
var bodyShapeValues = new Dictionary<string, float>();
var shapes = bodyShapes.Values.ToArray();
var keys = bodyShapes.Keys.ToArray();
SkinnedMeshRenderer renderer;
var body = GetOutfit("Body");
if (body == null) renderer = CharacterBody;
else renderer = body.skinnedRenderer;
for (int i = 0; i < shapes.Length; i++)
{
var weightValue = renderer.GetBlendShapeWeight(shapes[i]);
bodyShapeValues.Add(keys[i], weightValue);
}
return bodyShapeValues;
}
public Dictionary<string, float> GetFaceShapeValues()
{
var faceShapeValues = new Dictionary<string, float>();
var shapes = faceShapes.Values.ToArray();
var keys = faceShapes.Keys.ToArray();
SkinnedMeshRenderer renderer;
var head = GetOutfit("Head");
if (head == null) renderer = CharacterBody;
else renderer = head.skinnedRenderer;
for (int i = 0; i < shapes.Length; i++)
{
var weightValue = renderer.GetBlendShapeWeight(shapes[i]);
faceShapeValues.Add(keys[i], weightValue);
}
return faceShapeValues;
}
#endregion
#if UNITY_EDITOR
public void SoftAttach(Outfit outfit)
{
//For Attaching outfits during in the Editor
if (CharacterBody == null)
{
Debug.LogWarning("Soft Attach attempted but OuftitSystem did not have a CharacterBody please assign in the inspector", gameObject);
return;
}
Dictionary<string, Transform> boneMap = new Dictionary<string, Transform>();
foreach (Transform bone in CharacterBody.bones)
{
if (boneMap.ContainsKey(bone.name) == false)
{
boneMap.Add(bone.name, bone);
}
}
var renderer = outfit.GetComponentInChildren<SkinnedMeshRenderer>();
renderer.localBounds = CharacterBody.localBounds;
//Already Attached
if (outfit.originalBones.Length > 0)
{
return;
}
if (outfit.AttachPoint == "" && renderer)
{
if (outfit.Initalized == false)
{
outfit.originalBones = renderer.bones;
outfit.originalRootBone = renderer.rootBone;
var oldBones = renderer.bones.ToArray();
var newBones = new Transform[renderer.bones.Length];
for (int i = 0; i < oldBones.Length; i++)
{
var bone = oldBones[i];
boneMap.TryGetValue(bone.name, out newBones[i]);
}
renderer.bones = newBones;
renderer.rootBone = CharacterBody.rootBone;
}
}
}
#endif
public SkinnedMeshRenderer GetCharacterBody() { return CharacterBody; }
public void SetCharacterBody(GameObject newBody)
{
var smr = newBody.GetComponentInChildren<SkinnedMeshRenderer>();
if (smr == null) return;
RemoveAllOutfits();
DestroyImmediate(CharacterBody.transform.parent.gameObject);
newBody.transform.parent = transform;
newBody.transform.localPosition = Vector3.zero;
newBody.transform.localRotation = Quaternion.identity;
newBody.transform.localScale = Vector3.one;
CharacterBody = smr;
InitBoneMap();
InitBodyShapes();
InitBodyMods();
InitClothColliders();
OnRigChanged?.Invoke(CharacterBody);
Invoke("RebindBody", 0);
}
public void RebindBody()
{
animator.Rebind();
}
[ContextMenu("Merge")]
public void MergeCharacter()
{
if (Application.isPlaying && gameObject.scene.isLoaded)
{
var optimizer = new BoZo_CharacterOptimizer();
if (mergedMode && isDirty)
{
optimizer.OptimizeCharacter(this, data);
}
else
{
var preMergedData = BMAC_SaveSystem.GetCharacterData(this);
data = preMergedData;
foreach (var item in GetOutfits())
{
if (!item) { continue; }
var outfit = outfitData[item.Type.name] = item.GetOutfitData();
}
optimizer.OptimizeCharacter(this, preMergedData);
animator.SetBool("isMerged", true);
mergedMode = true;
}
}
else
{
Debug.LogWarning("For stability reason Character Merging is only available in Play Mode");
}
}
[ContextMenu("SaveToPrefab")]
public void SaveCharacterToPrefab()
{
#if UNITY_EDITOR
if (Application.isPlaying && gameObject.scene.isLoaded)
{
var optimizer = new BoZo_CharacterOptimizer();
if (mergedMode && isDirty)
{
optimizer.SaveOptimizedCharacter(this, data);
}
else
{
var preMergedData = BMAC_SaveSystem.GetCharacterData(this);
data = preMergedData;
foreach (var item in GetOutfits())
{
outfitData[item.Type.name] = item.GetOutfitData();
}
optimizer.SaveOptimizedCharacter(this, preMergedData);
animator.SetBool("isMerged", true);
mergedMode = true;
}
}
#endif
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c317bffdef488c04db98be9d95891349

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
[CreateAssetMenu(fileName = "NewOutfitType", menuName = "BoZo/BMAC_OutfitType")]
public class OutfitType : ScriptableObject
{
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ab164b4404dbd424ba5b274ece7019e6

View File

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

View File

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

View File

@@ -0,0 +1,46 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class BoZo_MagicaClothCollider : MonoBehaviour
{
#if MAGICACLOTH2
[SerializeField] Direction direction;
[SerializeField] bool reverseDirection;
[SerializeField] float length;
[SerializeField] float startRadius;
[SerializeField] float endRadius;
[SerializeField] Vector3 center;
private void Awake()
{
var col = gameObject.AddComponent<MagicaCloth2.MagicaCapsuleCollider>();
switch (direction)
{
case Direction.X:
col.direction = MagicaCloth2.MagicaCapsuleCollider.Direction.X;
break;
case Direction.Y:
col.direction = MagicaCloth2.MagicaCapsuleCollider.Direction.Y;
break;
case Direction.Z:
col.direction = MagicaCloth2.MagicaCapsuleCollider.Direction.Z;
break;
default:
break;
}
col.reverseDirection = reverseDirection;
col.SetSize(startRadius, endRadius, length);
col.center = center;
col.UpdateParameters();
}
private enum Direction { X, Y, Z }
#endif
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 63e462de7adcce6478830a8f97bd9a95
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/ThirdParty/MagicaCloth/BoZo_MagicaClothCollider.cs
uploadId: 853356

View File

@@ -0,0 +1,165 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class BoZo_MagicaClothSupport : MonoBehaviour, IOutfitExtension<Texture2D>
{
public const string id = "MagicaClothExtension";
bool initalized;
private OutfitSystem system;
public ClothType type;
[Header("Bones")]
public bool boneReferenceByString;
public List<Transform> rootBones;
public List<string> rootBonesString;
public float collisionSize = 0.025f;
[Header("Mesh")]
public Texture2D influenceMap;
[Range(0, 0.2f)] public float reductionSetting = 0.065f;
[Header("Preset")]
public TextAsset clothPreset;
public List<Transform> transforms = new List<Transform>();
#if MAGICACLOTH2
MagicaCloth2.MagicaCloth cloth;
#endif
public Texture2D GetValue() => influenceMap;
object IOutfitExtension.GetValue() => influenceMap;
public System.Type GetValueType() => typeof(Texture2D);
private void OnEnable()
{
system = GetComponentInParent<OutfitSystem>();
if (system) system.OnRigChanged += OnCharacterMerged;
}
private void OnDisable()
{
system = GetComponentInParent<OutfitSystem>();
if (system) system.OnRigChanged -= OnCharacterMerged;
}
public void Initalize(OutfitSystem outfitSystem, Outfit outfit)
{
#if MAGICACLOTH2
if (cloth) return;
cloth = gameObject.AddComponent<MagicaCloth2.MagicaCloth>();
cloth.Initialize();
cloth.DisableAutoBuild();
#endif
}
private void OnCharacterMerged(SkinnedMeshRenderer rig)
{
#if MAGICACLOTH2
if (system == null) return;
if (cloth) { Destroy(cloth); cloth = null; }
initalized = false;
if (system.customMaps.ContainsKey(id)) influenceMap = system.customMaps[id];
Initalize(null, null);
Execute(system, null);
#endif
}
public void Execute(OutfitSystem outfitSystem, Outfit outfit)
{
#if MAGICACLOTH2
if (outfitSystem.mergeBase) return;
if (initalized) return;
switch (type)
{
case ClothType.Mesh:
SetMeshCloth(outfitSystem, outfit);
break;
case ClothType.Bone:
SetBoneCloth(outfitSystem, outfit);
break;
case ClothType.Spring:
SetBoneCloth(outfitSystem, outfit);
break;
default:
break;
}
initalized = true;
#endif
}
#if MAGICACLOTH2
private void SetMeshCloth(OutfitSystem outfitSystem, Outfit outfit)
{
var sdata = cloth.SerializeData;
SkinnedMeshRenderer smr = null;
if (outfit) smr = outfit.skinnedRenderer;
else smr = outfitSystem.GetCharacterBody();
sdata.sourceRenderers.Add(smr);
sdata.reductionSetting.shapeDistance = reductionSetting;
sdata.paintMode = MagicaCloth2.ClothSerializeData.PaintMode.Texture_Fixed_Move;
sdata.paintMaps.Add(influenceMap);
if (clothPreset) cloth.SerializeData.ImportJson(clothPreset.ToString());
sdata.radius = new MagicaCloth2.CurveSerializeData(collisionSize);
var col = outfitSystem.GetClothColliders();
sdata.colliderCollisionConstraint.colliderList = col.ToList();
outfitSystem.RebindBody();
cloth.enabled = true;
cloth.BuildAndRun();
}
private void SetBoneCloth(OutfitSystem outfitSystem, Outfit outfit)
{
var sdata = cloth.SerializeData;
if (type == ClothType.Bone) sdata.clothType = MagicaCloth2.ClothProcess.ClothType.BoneCloth;
if (type == ClothType.Spring) sdata.clothType = MagicaCloth2.ClothProcess.ClothType.BoneSpring;
SkinnedMeshRenderer smr = null;
if (outfit) smr = outfit.skinnedRenderer;
else smr = outfitSystem.GetCharacterBody();
if (rootBonesString.Count != 0)
{
sdata.rootBones = smr.bones.Where(bone => rootBonesString.Contains(bone.name)).ToList();
}
else
{
sdata.rootBones = rootBones;
}
if (clothPreset) cloth.SerializeData.ImportJson(clothPreset.ToString());
sdata.radius = new MagicaCloth2.CurveSerializeData(collisionSize);
var col = outfitSystem.GetClothColliders();
sdata.colliderCollisionConstraint.colliderList = col.ToList();
cloth.enabled = true;
cloth.BuildAndRun();
}
#endif
public string GetID()
{
return id;
}
public enum ClothType { Mesh, Bone, Spring }
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 1d2d34769e54eb14398b24dc32eea2c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/ThirdParty/MagicaCloth/BoZo_MagicaClothSupport.cs
uploadId: 853356

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 99584cca56fc61e408f2d14378fa2059
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/ThirdParty/MagicaCloth/BoZo_Preset_LongHair.json
uploadId: 853356

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 433936ba35faf404f921f4a7966526f1
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/ThirdParty/MagicaCloth/BoZo_Preset_ShortHair.json
uploadId: 853356

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: e136f8a162b7c3f419623d4d87104bb7
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/ThirdParty/MagicaCloth/BoZo_Preset_Skirt.json
uploadId: 853356

View File

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

View File

@@ -0,0 +1,60 @@
using UnityEditor;
using UnityEngine;
namespace Bozo.AnimeCharacters
{
[CustomEditor(typeof(BoZo_MagicaClothSupport))]
[CanEditMultipleObjects]
public class BoZo_MagicaClothSupportEditor : Editor
{
public override void OnInspectorGUI()
{
#if MAGICACLOTH2
BoZo_MagicaClothSupport ob = (BoZo_MagicaClothSupport)target;
Color originalColor = GUI.color;
serializedObject.Update();
EditorGUILayout.PropertyField(serializedObject.FindProperty("type"));
EditorGUILayout.Space(10);
if (ob.type == BoZo_MagicaClothSupport.ClothType.Mesh)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("influenceMap"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("reductionSetting"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("collisionSize"));
}
else if (ob.type == BoZo_MagicaClothSupport.ClothType.Bone || ob.type == BoZo_MagicaClothSupport.ClothType.Spring)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("boneReferenceByString"));
if (ob.boneReferenceByString)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("rootBonesString"));
}
else
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("rootBones"));
}
EditorGUILayout.PropertyField(serializedObject.FindProperty("collisionSize"));
}
EditorGUILayout.Space(10);
EditorGUILayout.PropertyField(serializedObject.FindProperty("clothPreset"));
serializedObject.ApplyModifiedProperties();
//base.OnInspectorGUI();
return;
#endif
EditorGUILayout.LabelField("MagicaCloth2 Not Installed");
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d1433a1d9f4cc134a8500cb9c5b2be9c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 323550
packageName: 'BoZo: Modular Anime Characters - Base Pack'
packageVersion: 1.7.4
assetPath: Assets/BoZo_ModularAnimeCharacters/Scripts/ThirdParty/MagicaCloth/Editor/BoZo_MagicaClothSupportEditor.cs
uploadId: 853356

View File

@@ -0,0 +1,20 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class ToonFaceRelay : MonoBehaviour
{
private ToonFacialAnimator animator;
private void Start()
{
animator = GetComponentInParent<ToonFacialAnimator>();
}
public void SetFace(int preset)
{
if (animator == null) return;
animator.SetFace(preset);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e69a102f430316f44af6ccf14ad2b401

View File

@@ -0,0 +1,136 @@
using UnityEngine;
namespace Bozo.AnimeCharacters
{
public class ToonFacialAnimator : MonoBehaviour
{
public Vector3 commonLeftEyeOffset;
public Vector3 commonRightEyeOffset;
public Vector3 commonMouthOffset;
public float eyeRotation;
public float mouthRotation;
public Vector3 spriteScale;
private SpriteRenderer leftEye;
private SpriteRenderer rightEye;
private SpriteRenderer mouth;
[SerializeField] ToonFacePreset[] facePresets;
[SerializeField] SkinnedMeshRenderer rigOverride;
private void Start()
{
GenerateFace();
}
[ContextMenu("test")]
public void test()
{
SetFace(0);
}
private void GenerateFace()
{
Transform headBone = null;
Transform eyeBoneL = null;
Transform eyeBoneR = null;
if (rigOverride)
{
foreach (var bone in rigOverride.bones)
{
if (bone.name == "head"){ headBone = bone; }
if (bone.name == "eyeRoot_l") { eyeBoneL = bone; }
if (bone.name == "eyeRoot_r") { eyeBoneR = bone; }
}
}
else
{
var system = GetComponentInParent<OutfitSystem>();
if (!system) system = GetComponentInChildren<OutfitSystem>();
headBone = system.GetBones()["head"];
eyeBoneL = system.GetBones()["eyeRoot_l"];
eyeBoneR = system.GetBones()["eyeRoot_r"];
}
leftEye = new GameObject("ToonLeftEye", typeof(SpriteRenderer)).GetComponent<SpriteRenderer>();
rightEye = new GameObject("ToonRightEye", typeof(SpriteRenderer)).GetComponent<SpriteRenderer>();
mouth = new GameObject("ToonMouth", typeof(SpriteRenderer)).GetComponent<SpriteRenderer>();
leftEye.transform.parent = eyeBoneL;
rightEye.transform.parent = eyeBoneR;
mouth.transform.parent = headBone;
leftEye.transform.localPosition = commonLeftEyeOffset;
leftEye.transform.localScale = spriteScale;
leftEye.transform.localRotation = Quaternion.Euler(0, eyeRotation, 0);
rightEye.transform.localPosition = commonRightEyeOffset;
rightEye.transform.localScale = spriteScale;
rightEye.transform.localRotation = Quaternion.Euler(0, -eyeRotation, 0);
mouth.transform.localPosition = commonMouthOffset;
mouth.transform.localScale = spriteScale;
mouth.transform.localRotation = Quaternion.Euler(mouthRotation, 0, 0);
}
public void SetFace(int preset)
{
if(leftEye == null || rightEye == null || mouth == null)
{
GenerateFace();
}
var set = facePresets[preset];
leftEye.sprite = set.leftEyeSprite;
leftEye.flipX = set.leftEyeFlip;
leftEye.transform.localPosition = set.leftEyeOffset + commonLeftEyeOffset;
leftEye.transform.localScale = set.leftEyeScale + spriteScale;
rightEye.sprite = set.rightEyeSprite;
rightEye.flipX = set.rightEyeFlip;
rightEye.transform.localPosition = set.rightEyeOffset + commonRightEyeOffset;
rightEye.transform.localScale = set.rightEyeScale + spriteScale;
mouth.sprite = set.mouthSprite;
mouth.flipX = set.mouthFlip;
mouth.transform.localPosition = set.mouthOffset + commonMouthOffset;
mouth.transform.localScale = set.mouthScale + spriteScale;
}
[System.Serializable]
public class ToonFacePreset
{
public string presetName;
public Sprite leftEyeSprite;
public bool leftEyeFlip = true;
public Vector3 leftEyeOffset;
public Vector3 leftEyeScale = Vector3.zero;
public Sprite rightEyeSprite;
public bool rightEyeFlip = false;
public Vector3 rightEyeOffset;
public Vector3 rightEyeScale = Vector3.zero;
public Sprite mouthSprite;
public bool mouthFlip = true;
public Vector3 mouthOffset;
public Vector3 mouthScale = Vector3.zero;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7c34edd43158e704a831709334750f64