提交捏脸插件
This commit is contained in:
109
Assets/CharacterCustomizer/UI/Scripts/Apparel_Menu.cs
Normal file
109
Assets/CharacterCustomizer/UI/Scripts/Apparel_Menu.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using System.Linq;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class Apparel_Menu : MonoBehaviour, ICustomizerUI
|
||||
{
|
||||
public GameObject ButtonPrefab;
|
||||
public GameObject Container;
|
||||
|
||||
private CharacterCustomization customizer;
|
||||
|
||||
public bool useIcons = true;
|
||||
public Sprite defaultIcon;
|
||||
|
||||
public GameObject CategoryPrefab;
|
||||
public GameObject CategoryContainer;
|
||||
|
||||
private List<scrObj_Apparel.MenuCategory> menuCategories;
|
||||
|
||||
public SmoothScroll CategoryScroll;
|
||||
|
||||
public void InitializeUIElement(CharacterCustomization customizerScript, CC_UI_Util parentUI)
|
||||
{
|
||||
customizer = customizerScript;
|
||||
RefreshUIElement();
|
||||
}
|
||||
|
||||
public void createApparelButtons(scrObj_Apparel.MenuCategory menuCategory)
|
||||
{
|
||||
foreach (Transform child in Container.transform)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
for (int i = 0; i < customizer.ApparelTables.Count; i++)
|
||||
{
|
||||
var items = customizer.ApparelTables[i].Items.Where(item => item.MenuCategory == menuCategory);
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
for (int j = 0; j < item.Materials.Count; j++)
|
||||
{
|
||||
createButton(item.Name, i, j, item.Materials[j].Icon);
|
||||
}
|
||||
|
||||
if (item.Materials.Count == 0)
|
||||
{
|
||||
createButton(item.Name, i, 0, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createCategoryButtons()
|
||||
{
|
||||
//Safely destroy existing category buttons
|
||||
var children = new List<GameObject>();
|
||||
foreach (Transform child in CategoryContainer.transform) children.Add(child.gameObject);
|
||||
foreach (var go in children)
|
||||
{
|
||||
go.transform.SetParent(null);
|
||||
Destroy(go);
|
||||
}
|
||||
|
||||
//Try get tab manager
|
||||
var tabManager = CategoryContainer.GetComponentInParent<Tab_Manager>();
|
||||
|
||||
//Get menu categories in order
|
||||
menuCategories = customizer.ApparelTables.SelectMany(table => table.Items).Select(item => item.MenuCategory).Distinct().ToList();
|
||||
|
||||
//Create category button per menu category
|
||||
for (int i = 0; i < menuCategories.Count; i++)
|
||||
{
|
||||
scrObj_Apparel.MenuCategory cat = menuCategories[i];
|
||||
GameObject categoryButton = Instantiate(CategoryPrefab, CategoryContainer.transform).gameObject;
|
||||
categoryButton.GetComponentInChildren<TextMeshProUGUI>().text = menuCategories[i].ToString();
|
||||
var button = categoryButton.GetComponentInChildren<Button>();
|
||||
button.onClick.RemoveAllListeners();
|
||||
button.onClick.AddListener(() => { createApparelButtons(cat); });
|
||||
}
|
||||
|
||||
if (tabManager != null) tabManager.assignTabs();
|
||||
}
|
||||
|
||||
private void createButton(string text, int slot, int material, Sprite sprite)
|
||||
{
|
||||
string name = text;
|
||||
int matIndex = material;
|
||||
int apparelSlot = slot;
|
||||
|
||||
GameObject Button = Instantiate(ButtonPrefab, Container.transform).gameObject;
|
||||
Button.GetComponentInChildren<Button>().onClick.AddListener(() => { customizer.setApparelByName(name, apparelSlot, matIndex); });
|
||||
|
||||
if (useIcons) Button.GetComponentInChildren<Image>().sprite = sprite == null ? defaultIcon : sprite;
|
||||
else Button.GetComponentInChildren<TextMeshProUGUI>().text = text;
|
||||
}
|
||||
|
||||
public void RefreshUIElement()
|
||||
{
|
||||
createCategoryButtons();
|
||||
createApparelButtons(menuCategories[0]);
|
||||
if (CategoryScroll != null) CategoryScroll.resetScroll(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/Apparel_Menu.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/Apparel_Menu.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a5762fe1d52a214c89d6f7150f7e80a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
158
Assets/CharacterCustomizer/UI/Scripts/CC_UI_Manager.cs
Normal file
158
Assets/CharacterCustomizer/UI/Scripts/CC_UI_Manager.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
[DefaultExecutionOrder(200)]
|
||||
public class CC_UI_Manager : MonoBehaviour
|
||||
{
|
||||
public static CC_UI_Manager instance;
|
||||
|
||||
public delegate void OnHover(string partHovered);
|
||||
|
||||
public event OnHover onHover;
|
||||
|
||||
public delegate void OnDrag(string partX, string partY, float deltaX, float deltaY, bool first, bool last);
|
||||
|
||||
public event OnDrag onDrag;
|
||||
|
||||
private bool Dragging;
|
||||
private string hoveredPart = "";
|
||||
private string partX, partY = "";
|
||||
private float multX, multY = 1f;
|
||||
public float mouseDeltaScale = 0.01f;
|
||||
private Vector3 mousePos;
|
||||
|
||||
private Canvas canvas;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
[Tooltip("The parent object of your customizable characters")]
|
||||
public GameObject CharacterParent;
|
||||
|
||||
private int currentCharacter;
|
||||
|
||||
public List<AudioClip> UISounds = new List<AudioClip>();
|
||||
|
||||
public void Start()
|
||||
{
|
||||
SetActiveCharacter(0);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
bool first = !Dragging && Input.GetMouseButton(0);
|
||||
bool last = Dragging && !Input.GetMouseButton(0);
|
||||
|
||||
//Set shape on first drag
|
||||
if (first)
|
||||
{
|
||||
partX = ""; partY = "";
|
||||
multX = hoveredPart.Contains("_r") ? -1 : 1; multY = -1f;
|
||||
|
||||
if (hoveredPart.Contains("spine_05")) { partX = "BodyCustomization_ShoulderWidth"; partY = "BodyCustomization_TorsoHeight"; }
|
||||
else if (hoveredPart.Contains("spine")) { partX = "BodyCustomization_WaistSize"; partY = ""; }
|
||||
else if (hoveredPart.Contains("pelvis")) { partX = "BodyCustomization_HipWidth"; partY = ""; }
|
||||
else if (hoveredPart.Contains("lowerarm")) { partX = "BodyCustomization_LowerArmScale"; partY = ""; }
|
||||
else if (hoveredPart.Contains("upperarm")) { partX = "BodyCustomization_UpperArmScale"; partY = ""; }
|
||||
else if (hoveredPart.Contains("thigh")) { partX = "BodyCustomization_ThighScale"; partY = ""; }
|
||||
else if (hoveredPart.Contains("calf")) { partX = "BodyCustomization_CalfScale"; partY = ""; }
|
||||
else if (hoveredPart.Contains("head")) { partX = "BodyCustomization_HeadSize"; partY = "BodyCustomization_NeckLength"; }
|
||||
else if (hoveredPart.Contains("neck")) { partX = "BodyCustomization_NeckScale"; partY = "BodyCustomization_NeckLength"; }
|
||||
else if (hoveredPart.Contains("collider_nose")) { partX = "mod_nose_size"; partY = "mod_nose_height"; multY = 1; }
|
||||
else if (hoveredPart.Contains("collider_mouth")) { partX = "mod_mouth_size"; partY = "mod_mouth_height"; multY = 1; }
|
||||
else if (hoveredPart.Contains("collider_cheekbones")) { partX = "mod_cheekbone_size"; partY = ""; multX *= -1; }
|
||||
else if (hoveredPart.Contains("collider_cheeks")) { partX = "mod_cheeks_size"; partY = ""; multX *= -1; }
|
||||
else if (hoveredPart.Contains("collider_jaw")) { partX = "mod_jaw_width"; partY = "mod_jaw_height"; multX *= -1; }
|
||||
else if (hoveredPart.Contains("collider_chin")) { partX = ""; partY = "mod_chin_size"; }
|
||||
else if (hoveredPart.Contains("collider_eye")) { partX = "mod_eyes_narrow"; partY = "mod_eyes_height"; multY = 1; }
|
||||
else if (hoveredPart.Contains("collider_brow")) { partX = ""; partY = "mod_brow_height"; }
|
||||
}
|
||||
|
||||
Dragging = Input.GetMouseButton(0);
|
||||
|
||||
if (Dragging && getCanvas() != null)
|
||||
{
|
||||
Vector3 mouseDelta = (Input.mousePosition - mousePos) * mouseDeltaScale / canvas.scaleFactor;
|
||||
onDrag?.Invoke(partX, partY, mouseDelta.x * multX, mouseDelta.y * multY, first, last);
|
||||
}
|
||||
mousePos = Input.mousePosition;
|
||||
}
|
||||
|
||||
private Canvas getCanvas()
|
||||
{
|
||||
if (canvas != null) return canvas;
|
||||
else
|
||||
{
|
||||
canvas = GetComponentInChildren<Canvas>();
|
||||
return canvas;
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (Dragging) return;
|
||||
onHover?.Invoke(hoveredPart);
|
||||
|
||||
Physics.SyncTransforms();
|
||||
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
|
||||
if (Physics.Raycast(ray, out RaycastHit hit) && !EventSystem.current.IsPointerOverGameObject())
|
||||
{
|
||||
hoveredPart = hit.collider.name;
|
||||
}
|
||||
else hoveredPart = "";
|
||||
}
|
||||
|
||||
public void playUIAudio(int Index)
|
||||
{
|
||||
var audioSource = gameObject.GetComponent<AudioSource>();
|
||||
if (audioSource && UISounds.Count > Index) audioSource.clip = UISounds[Index]; audioSource.Play();
|
||||
}
|
||||
|
||||
public void SetActiveCharacter(int i)
|
||||
{
|
||||
if (CharacterParent == null) return;
|
||||
|
||||
currentCharacter = i;
|
||||
|
||||
for (int j = 0; j < CharacterParent.transform.childCount; j++)
|
||||
{
|
||||
var character = CharacterParent.transform.GetChild(j).gameObject;
|
||||
|
||||
//Reset active character and disable it
|
||||
if (character.activeSelf && i != j)
|
||||
{
|
||||
var script = character.GetComponentInChildren<CharacterCustomization>();
|
||||
script.LoadFromPreset(script.CharacterName);
|
||||
character.SetActive(false);
|
||||
}
|
||||
//Enable selected character (its UI is automatically activated)
|
||||
else if (i == j) character.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void characterNext()
|
||||
{
|
||||
SetActiveCharacter(currentCharacter == CharacterParent.transform.childCount - 1 ? 0 : currentCharacter + 1);
|
||||
}
|
||||
|
||||
public void characterPrev()
|
||||
{
|
||||
SetActiveCharacter(currentCharacter == 0 ? CharacterParent.transform.childCount - 1 : currentCharacter - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/CC_UI_Manager.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/CC_UI_Manager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c95c1eff6aa1ce42979924449accff9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
83
Assets/CharacterCustomizer/UI/Scripts/CC_UI_Util.cs
Normal file
83
Assets/CharacterCustomizer/UI/Scripts/CC_UI_Util.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class CC_UI_Util : MonoBehaviour
|
||||
{
|
||||
private CharacterCustomization customizer;
|
||||
|
||||
//Initialize all child UI elements
|
||||
public void Initialize(CharacterCustomization customizerScript)
|
||||
{
|
||||
customizer = customizerScript;
|
||||
|
||||
var interfaces = gameObject.GetComponentsInChildren<ICustomizerUI>(true);
|
||||
|
||||
foreach (var element in interfaces)
|
||||
{
|
||||
element.InitializeUIElement(customizerScript, this);
|
||||
}
|
||||
}
|
||||
|
||||
//Refresh UI elements, for example after loading a different preset
|
||||
public void refreshUI()
|
||||
{
|
||||
var interfaces = gameObject.GetComponentsInChildren<ICustomizerUI>(true);
|
||||
|
||||
foreach (var element in interfaces)
|
||||
{
|
||||
element.RefreshUIElement();
|
||||
}
|
||||
}
|
||||
|
||||
public void characterNext()
|
||||
{
|
||||
CC_UI_Manager.instance.characterNext();
|
||||
}
|
||||
|
||||
public void characterPrev()
|
||||
{
|
||||
CC_UI_Manager.instance.characterPrev();
|
||||
}
|
||||
|
||||
public void saveToPreset(string name)
|
||||
{
|
||||
customizer.SaveToPreset(name);
|
||||
}
|
||||
|
||||
public void saveToJSON(string name)
|
||||
{
|
||||
customizer.SaveToJSON(name);
|
||||
}
|
||||
|
||||
public void loadCharacter()
|
||||
{
|
||||
customizer.TryLoadCharacter();
|
||||
refreshUI();
|
||||
}
|
||||
|
||||
public void setCharacterName(string newName)
|
||||
{
|
||||
customizer.setCharacterName(newName);
|
||||
}
|
||||
|
||||
public void setCharacterPreset(string preset)
|
||||
{
|
||||
}
|
||||
|
||||
public void randomizeCharacter()
|
||||
{
|
||||
customizer.randomizeAll();
|
||||
}
|
||||
|
||||
public void randomizeOutfit()
|
||||
{
|
||||
customizer.setRandomOutfit();
|
||||
}
|
||||
|
||||
public void randomizeCharacterAndOutfit()
|
||||
{
|
||||
customizer.randomizeCharacterAndOutfit();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/CC_UI_Util.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/CC_UI_Util.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 523ae823434253c49af62d0cba16020d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
43
Assets/CharacterCustomizer/UI/Scripts/Cursor_Manager.cs
Normal file
43
Assets/CharacterCustomizer/UI/Scripts/Cursor_Manager.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class Cursor_Manager : MonoBehaviour
|
||||
{
|
||||
public static Cursor_Manager instance;
|
||||
|
||||
public Texture2D cursorTexture;
|
||||
private Vector2 hotSpot = new Vector2(0, 0);
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
if (cursorTexture != null)
|
||||
{
|
||||
hotSpot = new Vector2(cursorTexture.width / 2, cursorTexture.height / 2);
|
||||
setDefaultCursor();
|
||||
}
|
||||
}
|
||||
|
||||
public void setCursor(Texture2D texture)
|
||||
{
|
||||
if (cursorTexture != null)
|
||||
{
|
||||
Cursor.SetCursor(texture, hotSpot, CursorMode.Auto);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDefaultCursor()
|
||||
{
|
||||
setCursor(cursorTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/Cursor_Manager.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/Cursor_Manager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 491a40dbe36366b42ad3497e3f9453e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/CharacterCustomizer/UI/Scripts/ICustomizerUI.cs
Normal file
9
Assets/CharacterCustomizer/UI/Scripts/ICustomizerUI.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace CC
|
||||
{
|
||||
public interface ICustomizerUI
|
||||
{
|
||||
void InitializeUIElement(CharacterCustomization customizerScript, CC_UI_Util parentUI);
|
||||
|
||||
void RefreshUIElement();
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/ICustomizerUI.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/ICustomizerUI.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8ad964defd3d394c920d9d06af44e0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Assets/CharacterCustomizer/UI/Scripts/InputFieldHandler.cs
Normal file
37
Assets/CharacterCustomizer/UI/Scripts/InputFieldHandler.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class InputFieldHandler : MonoBehaviour, ICustomizerUI
|
||||
{
|
||||
private TMPro.TMP_InputField inputField;
|
||||
private CC_UI_Util script;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
inputField = GetComponent<TMPro.TMP_InputField>();
|
||||
}
|
||||
|
||||
public void InitializeUIElement(CharacterCustomization customizerScript, CC_UI_Util parentUI)
|
||||
{
|
||||
script = parentUI;
|
||||
}
|
||||
|
||||
public void RefreshUIElement()
|
||||
{
|
||||
}
|
||||
|
||||
public void InvokeMethod(string methodName)
|
||||
{
|
||||
// Get the method from CC_UI_Util that matches the name
|
||||
var method = typeof(CC_UI_Util).GetMethod(methodName);
|
||||
if (method != null && method.GetParameters().Length == 1 &&
|
||||
method.GetParameters()[0].ParameterType == typeof(string))
|
||||
{
|
||||
method.Invoke(script, new object[] { inputField.text });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75abdfd6bbb22a34ebbd0fd9b8f685bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
120
Assets/CharacterCustomizer/UI/Scripts/Option_Color_Picker.cs
Normal file
120
Assets/CharacterCustomizer/UI/Scripts/Option_Color_Picker.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class Option_Color_Picker : MonoBehaviour, ICustomizerUI
|
||||
{
|
||||
private CharacterCustomization customizer;
|
||||
private CC_UI_Util parentUI;
|
||||
|
||||
public CC_Property Property;
|
||||
public bool useOpacity;
|
||||
public string DisplayOption = "Option";
|
||||
public GameObject hsvSliders;
|
||||
private Image[] imgs;
|
||||
|
||||
public Image pickerIcon;
|
||||
|
||||
private float h; private float s; private float v; private float a = 1f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
UnityEditor.EditorApplication.delayCall += OnValidateCallback;
|
||||
}
|
||||
|
||||
private void OnValidateCallback()
|
||||
{
|
||||
if (this == null || Application.isPlaying)
|
||||
{
|
||||
UnityEditor.EditorApplication.delayCall -= OnValidateCallback;
|
||||
return;
|
||||
}
|
||||
|
||||
GetComponentInChildren<TMPro.TMP_Text>().text = DisplayOption;
|
||||
gameObject.name = "ColorPicker_" + DisplayOption;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public void InitializeUIElement(CharacterCustomization customizerScript, CC_UI_Util ParentUI)
|
||||
{
|
||||
customizer = customizerScript;
|
||||
parentUI = ParentUI;
|
||||
|
||||
RefreshUIElement();
|
||||
}
|
||||
|
||||
public void RefreshUIElement()
|
||||
{
|
||||
//Get saved value
|
||||
if (customizer.findProperty(customizer.StoredCharacterData.ColorProperties, Property, out Property, out int savedIndex))
|
||||
{
|
||||
pickerIcon.color = new Color(Property.colorValue.r, Property.colorValue.g, Property.colorValue.b, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void toggleSliders()
|
||||
{
|
||||
Color.RGBToHSV(Property.colorValue, out h, out s, out v);
|
||||
a = Property.colorValue.a;
|
||||
var sliderObj = Instantiate(hsvSliders, parentUI.transform);
|
||||
|
||||
//Remove on click
|
||||
var eventTrigger = sliderObj.GetComponentInChildren<EventTrigger>();
|
||||
var entry = new EventTrigger.Entry();
|
||||
entry.eventID = EventTriggerType.PointerDown;
|
||||
entry.callback = new EventTrigger.TriggerEvent();
|
||||
entry.callback.AddListener(a => Destroy(sliderObj));
|
||||
eventTrigger.triggers.Add(entry);
|
||||
|
||||
//Put slider box on this transform
|
||||
var sliderContainer = sliderObj.transform.GetChild(1);
|
||||
sliderContainer.position = transform.position;
|
||||
|
||||
var sliders = sliderObj.GetComponentsInChildren<Slider>();
|
||||
imgs = sliderObj.GetComponentsInChildren<Image>();
|
||||
|
||||
sliders[0].SetValueWithoutNotify(h);
|
||||
sliders[1].SetValueWithoutNotify(s);
|
||||
sliders[2].SetValueWithoutNotify(v);
|
||||
sliders[3].SetValueWithoutNotify(a);
|
||||
|
||||
sliders[0].onValueChanged.AddListener(f => { h = f; setColor(); });
|
||||
sliders[1].onValueChanged.AddListener(f => { s = f; setColor(); });
|
||||
sliders[2].onValueChanged.AddListener(f => { v = f; setColor(); });
|
||||
sliders[3].onValueChanged.AddListener(f => { a = f; setColor(); });
|
||||
|
||||
foreach (var img in imgs)
|
||||
{
|
||||
if (!img.raycastTarget) img.color = Color.HSVToRGB(h, 1, 1);
|
||||
}
|
||||
|
||||
if (!useOpacity)
|
||||
{
|
||||
Destroy(sliders[3].transform.parent.gameObject);
|
||||
}
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(sliderContainer.GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
public void setColor()
|
||||
{
|
||||
Property.colorValue = Color.HSVToRGB(h, s, v);
|
||||
Property.colorValue.a = a;
|
||||
|
||||
customizer.setColorProperty(Property, true);
|
||||
|
||||
pickerIcon.color = new Color(Property.colorValue.r, Property.colorValue.g, Property.colorValue.b, 1);
|
||||
|
||||
foreach (var img in imgs)
|
||||
{
|
||||
if (!img.raycastTarget) img.color = Color.HSVToRGB(h, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b50bfc1d8d860042808b29a182aef51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
240
Assets/CharacterCustomizer/UI/Scripts/Option_Picker.cs
Normal file
240
Assets/CharacterCustomizer/UI/Scripts/Option_Picker.cs
Normal file
@@ -0,0 +1,240 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class Option_Picker : MonoBehaviour, ICustomizerUI
|
||||
{
|
||||
private CharacterCustomization customizer;
|
||||
|
||||
public enum Type
|
||||
{ Blendshape, Texture, Hair, Color, Stencil };
|
||||
|
||||
public Type CustomizationType;
|
||||
|
||||
public CC_Property Property;
|
||||
public List<CC_Property> Options = new List<CC_Property>();
|
||||
public int Slot = 0;
|
||||
|
||||
public TextMeshProUGUI PropertyText;
|
||||
public TextMeshProUGUI OptionText;
|
||||
|
||||
public string DisplayOption;
|
||||
|
||||
private int navIndex = 0;
|
||||
private int optionsCount = 0;
|
||||
|
||||
public bool valueFromIndex = true;
|
||||
public bool valueFromString = false;
|
||||
public bool blendshapeUseOptionValue;
|
||||
public List<CC_Stencil> stencilOptions = new List<CC_Stencil>();
|
||||
|
||||
public void InitializeUIElement(CharacterCustomization customizerScript, CC_UI_Util ParentUI)
|
||||
{
|
||||
customizer = customizerScript;
|
||||
RefreshUIElement();
|
||||
foreach (var item in stencilOptions)
|
||||
{
|
||||
item.basePropertyName = Property.propertyName;
|
||||
item.materialIndex = Property.materialIndex;
|
||||
item.meshTag = Property.meshTag;
|
||||
}
|
||||
|
||||
if (!blendshapeUseOptionValue && CustomizationType == Type.Blendshape) return;
|
||||
|
||||
foreach (var item in Options)
|
||||
{
|
||||
item.propertyName = Property.propertyName;
|
||||
item.materialIndex = Property.materialIndex;
|
||||
item.meshTag = Property.meshTag;
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshUIElement()
|
||||
{
|
||||
switch (CustomizationType)
|
||||
{
|
||||
case Type.Blendshape:
|
||||
{
|
||||
optionsCount = Options.Count;
|
||||
updateOptionText();
|
||||
for (int i = 0; i < Options.Count; i++)
|
||||
{
|
||||
CC_Property prop;
|
||||
if (customizer.findProperty(customizer.StoredCharacterData.Blendshapes, Options[i], out prop, out int savedIndex))
|
||||
{
|
||||
if (prop.floatValue != 0)
|
||||
{
|
||||
navIndex = i;
|
||||
updateOptionText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type.Texture:
|
||||
{
|
||||
optionsCount = Options.Count;
|
||||
if (customizer.findProperty(customizer.StoredCharacterData.TextureProperties, Property, out Property, out int savedIndex))
|
||||
{
|
||||
navIndex = Options.FindIndex(t => t.stringValue == Property.stringValue);
|
||||
}
|
||||
else navIndex = 0;
|
||||
updateOptionText();
|
||||
break;
|
||||
}
|
||||
case Type.Stencil:
|
||||
{
|
||||
optionsCount = stencilOptions.Count;
|
||||
if (customizer.findProperty(customizer.StoredCharacterData.TextureProperties, Property, out Property, out int savedIndex))
|
||||
{
|
||||
navIndex = stencilOptions.FindIndex(t => t.texture.name == Property.stringValue);
|
||||
}
|
||||
else navIndex = 0;
|
||||
updateOptionText();
|
||||
break;
|
||||
}
|
||||
case Type.Color:
|
||||
{
|
||||
optionsCount = Options.Count;
|
||||
if (customizer.findProperty(customizer.StoredCharacterData.ColorProperties, Property, out Property, out int savedIndex))
|
||||
{
|
||||
navIndex = Options.FindIndex(t => colorMatch(t.colorValue, Property.colorValue));
|
||||
if (navIndex == -1) navIndex = 0;
|
||||
}
|
||||
else navIndex = 0;
|
||||
updateOptionText();
|
||||
break;
|
||||
}
|
||||
case Type.Hair:
|
||||
{
|
||||
if (customizer.HairTables.Count <= Slot)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
optionsCount = customizer.HairTables[Slot].Hairstyles.Count;
|
||||
navIndex = customizer.HairTables[Slot].Hairstyles.FindIndex(t => t.Name == customizer.StoredCharacterData.HairNames[Slot]);
|
||||
if (navIndex == -1) navIndex = 0;
|
||||
updateOptionText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool colorMatch(Color a, Color b, float tolerance = 0.1f)
|
||||
{
|
||||
return Mathf.Abs(a.r - b.r) < tolerance &&
|
||||
Mathf.Abs(a.g - b.g) < tolerance &&
|
||||
Mathf.Abs(a.b - b.b) < tolerance;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
UnityEditor.EditorApplication.delayCall += OnValidateCallback;
|
||||
}
|
||||
|
||||
private void OnValidateCallback()
|
||||
{
|
||||
if (this == null || Application.isPlaying)
|
||||
{
|
||||
UnityEditor.EditorApplication.delayCall -= OnValidateCallback;
|
||||
return;
|
||||
}
|
||||
|
||||
PropertyText.text = DisplayOption;
|
||||
if (DisplayOption != "") gameObject.name = "Picker_" + DisplayOption;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public void updateOptionText()
|
||||
{
|
||||
if (valueFromIndex) { OptionText.gameObject.SetActive(true); OptionText.SetText((navIndex + 1) + "/" + optionsCount); }
|
||||
if (valueFromString) { OptionText.gameObject.SetActive(true); OptionText.SetText(Options[navIndex].stringValue); }
|
||||
}
|
||||
|
||||
public void setOption(int i)
|
||||
{
|
||||
navIndex = i;
|
||||
|
||||
updateOptionText();
|
||||
|
||||
switch (CustomizationType)
|
||||
{
|
||||
case Type.Blendshape:
|
||||
{
|
||||
if (blendshapeUseOptionValue)
|
||||
{
|
||||
customizer.setBlendshapeByName(Property.propertyName, Options[i].floatValue);
|
||||
break;
|
||||
}
|
||||
foreach (var p in Options)
|
||||
{
|
||||
customizer.setBlendshapeByName(name, 0);
|
||||
}
|
||||
customizer.setBlendshapeByName(Options[i].propertyName, 1);
|
||||
break;
|
||||
}
|
||||
case Type.Hair:
|
||||
{
|
||||
customizer.setHair(i, Slot);
|
||||
break;
|
||||
}
|
||||
case Type.Texture:
|
||||
{
|
||||
var pNames = Options[i].propertyName.Split(",");
|
||||
var pValues = Options[i].stringValue.Split(",");
|
||||
var pTags = Options[i].meshTag.Split(",");
|
||||
for (int j = 0; j < pNames.Length; j++)
|
||||
{
|
||||
string value = j < pValues.Length ? pValues[j] : string.Empty;
|
||||
string tag = j < pTags.Length ? pTags[j] : string.Empty;
|
||||
var prop2 = new CC_Property() { propertyName = pNames[j], stringValue = value, materialIndex = Property.materialIndex, meshTag = tag };
|
||||
customizer.setTextureProperty(prop2, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type.Stencil:
|
||||
var stencil = stencilOptions[i];
|
||||
var textureProp = new CC_Property() { propertyName = stencil.basePropertyName, materialIndex = stencil.materialIndex, meshTag = stencil.meshTag };
|
||||
customizer.setTextureProperty(textureProp, true, stencil.texture);
|
||||
var offsetX = new CC_Property() { propertyName = stencil.basePropertyName + "_Offset_X", floatValue = stencil.offsetX, materialIndex = stencil.materialIndex, meshTag = stencil.meshTag };
|
||||
customizer.setFloatProperty(offsetX, true);
|
||||
var offsetY = new CC_Property() { propertyName = stencil.basePropertyName + "_Offset_Y", floatValue = stencil.offsetY, materialIndex = stencil.materialIndex, meshTag = stencil.meshTag };
|
||||
customizer.setFloatProperty(offsetY, true);
|
||||
var scaleX = new CC_Property() { propertyName = stencil.basePropertyName + "_Scale_X", floatValue = stencil.scaleX, materialIndex = stencil.materialIndex, meshTag = stencil.meshTag };
|
||||
customizer.setFloatProperty(scaleX, true);
|
||||
var scaleY = new CC_Property() { propertyName = stencil.basePropertyName + "_Scale_Y", floatValue = stencil.scaleY, materialIndex = stencil.materialIndex, meshTag = stencil.meshTag };
|
||||
customizer.setFloatProperty(scaleY, true);
|
||||
var rotProp = new CC_Property() { propertyName = stencil.basePropertyName + "_Rotation", floatValue = stencil.rotation, materialIndex = stencil.materialIndex, meshTag = stencil.meshTag };
|
||||
customizer.setFloatProperty(rotProp, true);
|
||||
var tintableProp = new CC_Property() { propertyName = stencil.basePropertyName + "_Tintable", floatValue = stencil.tintable ? 1 : 0, materialIndex = stencil.materialIndex, meshTag = stencil.meshTag };
|
||||
customizer.setFloatProperty(tintableProp, true);
|
||||
|
||||
break;
|
||||
|
||||
case Type.Color:
|
||||
{
|
||||
customizer.setColorProperty(Options[i], true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void navLeft()
|
||||
{
|
||||
setOption(navIndex == 0 ? optionsCount - 1 : navIndex - 1);
|
||||
}
|
||||
|
||||
public void navRight()
|
||||
{
|
||||
setOption(navIndex == optionsCount - 1 ? 0 : navIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/Option_Picker.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/Option_Picker.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 972b1ade9bcc8014da70c277593109e2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class Option_Proportional_Sliders : MonoBehaviour, ICustomizerUI
|
||||
{
|
||||
private CharacterCustomization customizer;
|
||||
private CC_UI_Util parentUI;
|
||||
|
||||
public List<CC_Property> Properties = new List<CC_Property>();
|
||||
|
||||
public bool RemoveText = true;
|
||||
public bool Vertical = true;
|
||||
|
||||
public GameObject SliderObject;
|
||||
public Transform SliderContainer;
|
||||
|
||||
private List<Slider> sliders = new List<Slider>();
|
||||
private List<Option_Slider> sliderScripts = new List<Option_Slider>();
|
||||
|
||||
private float sliderSum;
|
||||
|
||||
public void InitializeUIElement(CharacterCustomization customizerScript, CC_UI_Util ParentUI)
|
||||
{
|
||||
customizer = customizerScript;
|
||||
parentUI = ParentUI;
|
||||
|
||||
foreach (var slider in sliderScripts)
|
||||
{
|
||||
Destroy(slider.gameObject);
|
||||
}
|
||||
|
||||
sliderScripts.Clear();
|
||||
sliders.Clear();
|
||||
|
||||
for (int i = 0; i < Properties.Count; i++)
|
||||
{
|
||||
//Create sliders, assign to reference and add delegate
|
||||
var sliderObj = Instantiate(SliderObject, SliderContainer);
|
||||
Option_Slider sliderScript = sliderObj.AddComponent<Option_Slider>();
|
||||
|
||||
if (RemoveText) sliderObj.GetComponentInChildren<TMP_Text>().gameObject.SetActive(false);
|
||||
|
||||
sliderScripts.Add(sliderScript);
|
||||
sliderScript.Property = Properties[i];
|
||||
sliderScript.CustomizationType = Option_Slider.Type.Blendshape;
|
||||
sliderScript.InitializeUIElement(customizerScript, ParentUI);
|
||||
|
||||
Slider slider = sliderScript.GetComponentInChildren<Slider>();
|
||||
if (Vertical) slider.SetDirection(Slider.Direction.BottomToTop, true);
|
||||
sliders.Add(slider);
|
||||
slider.onValueChanged.AddListener(delegate { checkExcess(slider); });
|
||||
}
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(transform.parent.GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
public void RefreshUIElement()
|
||||
{
|
||||
foreach (var slider in sliderScripts)
|
||||
{
|
||||
slider.RefreshUIElement();
|
||||
}
|
||||
}
|
||||
|
||||
public void checkExcess(Slider mainSlider)
|
||||
{
|
||||
sliderSum = 0;
|
||||
|
||||
foreach (Slider slider in sliders)
|
||||
{
|
||||
sliderSum = slider.value + sliderSum;
|
||||
}
|
||||
|
||||
if (sliderSum > 1)
|
||||
{
|
||||
for (int i = 0; i < sliders.Count; i++)
|
||||
{
|
||||
if (mainSlider != sliders[i])
|
||||
{
|
||||
distributeExcess(sliderSum - mainSlider.value, sliderSum - 1, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void distributeExcess(float sum, float excess, int index)
|
||||
{
|
||||
sliders[index].SetValueWithoutNotify(sliders[index].value - (sliders[index].value / sum * excess));
|
||||
sliderScripts[index].setProperty(sliders[index].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78f05b0af19bf944a9c043a5792287e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
129
Assets/CharacterCustomizer/UI/Scripts/Option_Slider.cs
Normal file
129
Assets/CharacterCustomizer/UI/Scripts/Option_Slider.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class Option_Slider : MonoBehaviour, ICustomizerUI
|
||||
{
|
||||
public enum Type
|
||||
{ Blendshape, Scalar, ModifyType };
|
||||
|
||||
public Type CustomizationType;
|
||||
|
||||
public CC_Property Property;
|
||||
|
||||
public Vector2 Range = new Vector2(0, 1);
|
||||
public float DefaultValue = 0f;
|
||||
public string DisplayOption = "Option";
|
||||
public bool UsesDragCustomization;
|
||||
public float dragMultiplier = 1f;
|
||||
|
||||
private Slider slider;
|
||||
|
||||
private CharacterCustomization customizer;
|
||||
private CC_UI_Util parentUI;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
UnityEditor.EditorApplication.delayCall += OnValidateCallback;
|
||||
}
|
||||
|
||||
private void OnValidateCallback()
|
||||
{
|
||||
if (this == null || Application.isPlaying)
|
||||
{
|
||||
UnityEditor.EditorApplication.delayCall -= OnValidateCallback;
|
||||
return;
|
||||
}
|
||||
|
||||
slider = GetComponentInChildren<Slider>();
|
||||
slider.minValue = Range.x;
|
||||
slider.maxValue = Range.y;
|
||||
slider.SetValueWithoutNotify(DefaultValue);
|
||||
GetComponentInChildren<TMPro.TMP_Text>(true).text = DisplayOption;
|
||||
gameObject.name = "Slider_" + DisplayOption;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public void InitializeUIElement(CharacterCustomization customizerScript, CC_UI_Util ParentUI)
|
||||
{
|
||||
slider = GetComponentInChildren<Slider>();
|
||||
customizer = customizerScript;
|
||||
parentUI = ParentUI;
|
||||
|
||||
if (UsesDragCustomization) CC_UI_Manager.instance.onDrag += onBodyCustomization;
|
||||
|
||||
slider.onValueChanged.AddListener(setProperty);
|
||||
|
||||
RefreshUIElement();
|
||||
}
|
||||
|
||||
private void onBodyCustomization(string partX, string partY, float deltaX, float deltaY, bool first, bool last)
|
||||
{
|
||||
if (partX == Property.propertyName)
|
||||
{
|
||||
slider.value += deltaX * dragMultiplier;
|
||||
}
|
||||
if (partY == Property.propertyName)
|
||||
{
|
||||
slider.value += deltaY * dragMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshUIElement()
|
||||
{
|
||||
//Get saved value
|
||||
switch (CustomizationType)
|
||||
{
|
||||
case Type.Blendshape:
|
||||
case Type.ModifyType:
|
||||
{
|
||||
if (customizer.findProperty(customizer.StoredCharacterData.Blendshapes, Property, out Property, out int savedIndex))
|
||||
{
|
||||
slider.SetValueWithoutNotify(Property.floatValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
slider.SetValueWithoutNotify(DefaultValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type.Scalar:
|
||||
{
|
||||
if (customizer.findProperty(customizer.StoredCharacterData.FloatProperties, Property, out Property, out int savedIndex))
|
||||
{
|
||||
slider.SetValueWithoutNotify(Property.floatValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
slider.SetValueWithoutNotify(DefaultValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setProperty(float value)
|
||||
{
|
||||
Property.floatValue = value;
|
||||
|
||||
switch (CustomizationType)
|
||||
{
|
||||
case Type.Blendshape:
|
||||
case Type.ModifyType:
|
||||
{
|
||||
customizer.setBlendshapeByName(Property.propertyName, value);
|
||||
break;
|
||||
}
|
||||
case Type.Scalar:
|
||||
{
|
||||
customizer.setFloatProperty(Property, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/Option_Slider.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/Option_Slider.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7585e7a004288d84d8e14942498a27d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
56
Assets/CharacterCustomizer/UI/Scripts/Option_Tint_Buttons.cs
Normal file
56
Assets/CharacterCustomizer/UI/Scripts/Option_Tint_Buttons.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class Option_Tint_Buttons : MonoBehaviour, ICustomizerUI
|
||||
{
|
||||
public CC_Property property;
|
||||
public List<Color> tints = new List<Color>();
|
||||
public GameObject buttonPrefab;
|
||||
public UnityEvent customEvent;
|
||||
|
||||
private CharacterCustomization customizer;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
var buttonDefault = GetComponentInChildren<Button>();
|
||||
if (buttonDefault != null) buttonDefault.onClick.AddListener(delegate
|
||||
{
|
||||
setProperty(new Color(0, 0, 0, 0)); customEvent.Invoke();
|
||||
});
|
||||
|
||||
for (int i = 0; i < tints.Count; i++)
|
||||
{
|
||||
int index = i;
|
||||
|
||||
var button = Instantiate(buttonPrefab, transform);
|
||||
button.GetComponentInChildren<Button>().onClick.AddListener(delegate { setProperty(tints[index]); customEvent.Invoke(); });
|
||||
button.GetComponentInChildren<Image>().color = tints[i];
|
||||
|
||||
var backgroundImg = button.AddComponent<Image>();
|
||||
backgroundImg.color = new Color(0.5f, 0.5f, 0.5f);
|
||||
}
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(transform.GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
private void setProperty(Color color)
|
||||
{
|
||||
property.colorValue = color;
|
||||
customizer.setColorProperty(property, true);
|
||||
}
|
||||
|
||||
public void InitializeUIElement(CharacterCustomization customizerScript, CC_UI_Util parentUI)
|
||||
{
|
||||
customizer = customizerScript;
|
||||
}
|
||||
|
||||
public void RefreshUIElement()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 069989e85751cf549b524a7b9beab46b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
20
Assets/CharacterCustomizer/UI/Scripts/SetCursor.cs
Normal file
20
Assets/CharacterCustomizer/UI/Scripts/SetCursor.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class SetCursor : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
|
||||
{
|
||||
public Texture2D cursorTexture;
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
Cursor_Manager.instance.setCursor(cursorTexture);
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
Cursor_Manager.instance.setDefaultCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/SetCursor.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/SetCursor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60c36761d13c54347bf3fdd44a106044
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
106
Assets/CharacterCustomizer/UI/Scripts/SmoothScroll.cs
Normal file
106
Assets/CharacterCustomizer/UI/Scripts/SmoothScroll.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using System.Collections;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class SmoothScroll : ScrollRect
|
||||
{
|
||||
public bool SmoothScrolling { get; set; } = true;
|
||||
public float SmoothScrollTime { get; set; } = 0.2f;
|
||||
|
||||
private Coroutine smoothScrollCoroutine;
|
||||
|
||||
public override void OnScroll(PointerEventData data)
|
||||
{
|
||||
if (!IsActive()) return;
|
||||
|
||||
if (SmoothScrolling)
|
||||
{
|
||||
// Stop any ongoing smooth scroll
|
||||
if (smoothScrollCoroutine != null)
|
||||
StopCoroutine(smoothScrollCoroutine);
|
||||
|
||||
Vector2 positionBefore = normalizedPosition;
|
||||
base.OnScroll(data);
|
||||
Vector2 positionAfter = normalizedPosition;
|
||||
normalizedPosition = positionBefore;
|
||||
|
||||
smoothScrollCoroutine = StartCoroutine(SmoothScrollToPosition(positionAfter));
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnScroll(data);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetScrollTarget(Vector2 targetPosition)
|
||||
{
|
||||
if (SmoothScrolling)
|
||||
{
|
||||
if (smoothScrollCoroutine != null)
|
||||
StopCoroutine(smoothScrollCoroutine);
|
||||
|
||||
Vector2 positionBefore = normalizedPosition;
|
||||
normalizedPosition = targetPosition;
|
||||
Vector2 positionAfter = normalizedPosition;
|
||||
normalizedPosition = positionBefore;
|
||||
|
||||
smoothScrollCoroutine = StartCoroutine(SmoothScrollToPosition(positionAfter));
|
||||
}
|
||||
else
|
||||
{
|
||||
normalizedPosition = targetPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public void resetScroll(bool instant = false)
|
||||
{
|
||||
var smoothScroll = SmoothScrolling;
|
||||
if (instant) SmoothScrolling = false;
|
||||
StopAllCoroutines();
|
||||
SetScrollTarget(new Vector2(0, 1));
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(content.GetComponent<RectTransform>());
|
||||
if (instant) SmoothScrolling = smoothScroll;
|
||||
}
|
||||
|
||||
public void ScrollToContent(RectTransform targetContent)
|
||||
{
|
||||
// Ensure targetContent is a child of the content area
|
||||
if (targetContent == null || !targetContent.IsChildOf(content))
|
||||
{
|
||||
Debug.LogWarning("Target content is not a child of the scroll rect content.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the target normalized position
|
||||
Vector2 targetLocalPos = content.InverseTransformPoint(targetContent.position);
|
||||
Vector2 contentSize = content.rect.size;
|
||||
Vector2 viewportSize = viewport.rect.size;
|
||||
|
||||
Vector2 normalizedPos = new Vector2(
|
||||
Mathf.Clamp01((targetLocalPos.x - viewportSize.x / 2) / (contentSize.x - viewportSize.x)),
|
||||
Mathf.Clamp01((targetLocalPos.y - viewportSize.y / 2) / (contentSize.y - viewportSize.y))
|
||||
);
|
||||
|
||||
SetScrollTarget(normalizedPos);
|
||||
}
|
||||
|
||||
private IEnumerator SmoothScrollToPosition(Vector2 targetPosition)
|
||||
{
|
||||
float elapsedTime = 0f;
|
||||
Vector2 startPosition = normalizedPosition;
|
||||
|
||||
while (elapsedTime < SmoothScrollTime)
|
||||
{
|
||||
elapsedTime += Time.unscaledDeltaTime;
|
||||
normalizedPosition = Vector2.Lerp(startPosition, targetPosition, elapsedTime / SmoothScrollTime);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
normalizedPosition = targetPosition;
|
||||
smoothScrollCoroutine = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/SmoothScroll.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/SmoothScroll.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 135cd364be106894d8b0ce2ad412d2aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
68
Assets/CharacterCustomizer/UI/Scripts/Tab_Manager.cs
Normal file
68
Assets/CharacterCustomizer/UI/Scripts/Tab_Manager.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class Tab_Manager : MonoBehaviour
|
||||
{
|
||||
[Header("Button Active Colors")]
|
||||
public ColorBlock TabColorActive;
|
||||
|
||||
[Header("Button Inactive Colors")]
|
||||
public ColorBlock TabColorInactive;
|
||||
|
||||
public GameObject TabParent;
|
||||
private List<GameObject> tabs = new List<GameObject>();
|
||||
private List<GameObject> tabMenus = new List<GameObject>();
|
||||
|
||||
private SmoothScroll scrollRect;
|
||||
public SmoothScroll targetScroll;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
assignTabs();
|
||||
}
|
||||
|
||||
public void assignTabs()
|
||||
{
|
||||
tabs.Clear();
|
||||
tabMenus.Clear();
|
||||
|
||||
for (int i = 0; i < transform.childCount; i++)
|
||||
{
|
||||
var tab = transform.GetChild(i).gameObject;
|
||||
var index = i;
|
||||
tabs.Add(tab);
|
||||
|
||||
tab.GetComponentInChildren<Button>().onClick.AddListener(() => switchTab(index));
|
||||
}
|
||||
|
||||
if (TabParent != null) foreach (Transform child in TabParent.transform)
|
||||
{
|
||||
tabMenus.Add(child.gameObject);
|
||||
}
|
||||
|
||||
scrollRect = GetComponentInParent<SmoothScroll>();
|
||||
switchTab(0);
|
||||
if (scrollRect != null) scrollRect.resetScroll(true);
|
||||
}
|
||||
|
||||
public void switchTab(int tab)
|
||||
{
|
||||
for (int i = 0; i < tabs.Count; i++)
|
||||
{
|
||||
//Set tab color
|
||||
tabs[i].GetComponentInChildren<Button>().colors = tab == i ? TabColorActive : TabColorInactive;
|
||||
|
||||
//Set tab active state
|
||||
if (tabMenus.Count > i) tabMenus[i].SetActive(tab == i);
|
||||
}
|
||||
|
||||
if (scrollRect != null) scrollRect.ScrollToContent(tabs[tab].GetComponent<RectTransform>());
|
||||
if (TabParent != null) LayoutRebuilder.ForceRebuildLayoutImmediate(TabParent.GetComponent<RectTransform>());
|
||||
if (targetScroll != null) targetScroll.resetScroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/Tab_Manager.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/Tab_Manager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c722064675872df4f89a6c429fd1436a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
21
Assets/CharacterCustomizer/UI/Scripts/UI_Sound.cs
Normal file
21
Assets/CharacterCustomizer/UI/Scripts/UI_Sound.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace CC
|
||||
{
|
||||
public class ClickAudio : MonoBehaviour
|
||||
{
|
||||
public int sound;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
var buttons = GetComponentsInChildren<Button>();
|
||||
foreach (var button in buttons)
|
||||
{
|
||||
button.onClick.AddListener(() => CC_UI_Manager.instance.playUIAudio(sound));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/CharacterCustomizer/UI/Scripts/UI_Sound.cs.meta
Normal file
11
Assets/CharacterCustomizer/UI/Scripts/UI_Sound.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9023a8ca4ce46224a99b57ac0a9b6bbc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user