You've already forked UniversalViewer
Initial files
This commit is contained in:
77
Assets/Scripts/ModelViewerBase/AssetLibrary.cs
Normal file
77
Assets/Scripts/ModelViewerBase/AssetLibrary.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.AddressableAssets.ResourceLocators;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.ResourceManagement.ResourceProviders;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class AssetLibrary : MonoBehaviour
|
||||
{
|
||||
protected static AssetLibrary _mainInstance;
|
||||
public ResourceLocationMap AddressableResourceMap;
|
||||
private List<string> _addressableKeys;
|
||||
public string LocalFilesPath;
|
||||
|
||||
public static T GetInstance<T>() where T : AssetLibrary
|
||||
{
|
||||
return _mainInstance as T;
|
||||
}
|
||||
|
||||
public List<string> GetAddressableKeys()
|
||||
{
|
||||
if (_addressableKeys == null)
|
||||
{
|
||||
_addressableKeys = AddressableResourceMap.Keys.Select(k=>k.ToString()).ToList();
|
||||
}
|
||||
return _addressableKeys.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load catalog.json from games that use addressables
|
||||
/// </summary>
|
||||
/// <param name="catalogPath"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerator LoadAddressableCatalog(string catalogPath)
|
||||
{
|
||||
var opHandle = Addressables.LoadContentCatalogAsync(catalogPath);
|
||||
yield return opHandle;
|
||||
|
||||
if (opHandle.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
Debug.Log(opHandle.Result.GetType());
|
||||
AddressableResourceMap = opHandle.Result as ResourceLocationMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw opHandle.OperationException;
|
||||
}
|
||||
|
||||
//var keys = AddressableResourceMap.Keys.Where(k=>k.ToString().Contains("chara_100_0001")).ToList();
|
||||
//for (int i = 0; i < keys.Count; i++)
|
||||
//{
|
||||
// Debug.Log(keys[i].ToString());
|
||||
// Debug.Log(JObject.FromObject(AddressableResourceMap.Locations[keys[i]][0]).ToString());
|
||||
// Debug.Log(AddressableResourceMap.Locations[keys[i]][0].Data.GetType());
|
||||
// //switch (AddressableResourceMap.Locations[keys[i]][0])
|
||||
// //{
|
||||
// // case CompactLocation cl:
|
||||
// // break;
|
||||
// //}
|
||||
//}
|
||||
}
|
||||
|
||||
public string GetResourcePath(string resourceName)
|
||||
{
|
||||
var locator = AddressableResourceMap.Locations[resourceName][0]; // AddressableResourceMap.Locations[resourceName][0].Dependencies[0].Data as AssetBundleRequestOptions;
|
||||
if (locator.HasDependencies)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var data = locator.Data as AssetBundleRequestOptions;
|
||||
var filePath = data.BundleName + "/" + data.Hash + "/" + "__data";
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/AssetLibrary.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/AssetLibrary.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68d09003b62bea04bbedb8a5b21b9aa6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
5
Assets/Scripts/ModelViewerBase/AssetSpawnData.cs
Normal file
5
Assets/Scripts/ModelViewerBase/AssetSpawnData.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
public class AssetSpawnData
|
||||
{
|
||||
public AssetTypes AssetType;
|
||||
public string FilePath;
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/AssetSpawnData.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/AssetSpawnData.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a31e5f4826d6b7c42bca99c19497a7f4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
6
Assets/Scripts/ModelViewerBase/AssetTypes.cs
Normal file
6
Assets/Scripts/ModelViewerBase/AssetTypes.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
public enum AssetTypes
|
||||
{
|
||||
Unknown,
|
||||
Character,
|
||||
Object
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/AssetTypes.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/AssetTypes.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 547b343c746a81e4dbfc463e6edd4948
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
6
Assets/Scripts/ModelViewerBase/BoneList.cs
Normal file
6
Assets/Scripts/ModelViewerBase/BoneList.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
[System.Serializable]
|
||||
public class BoneList
|
||||
{
|
||||
public string Name;
|
||||
public SerializableBone[] Bones = new SerializableBone[0];
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/BoneList.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/BoneList.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98e7f80672878ce44b33fbf239398d53
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
288
Assets/Scripts/ModelViewerBase/CameraOrbit.cs
Normal file
288
Assets/Scripts/ModelViewerBase/CameraOrbit.cs
Normal file
@@ -0,0 +1,288 @@
|
||||
using CommandUndoRedo;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class CameraOrbit : MonoBehaviour
|
||||
{
|
||||
public bool LightLock = false;
|
||||
public Camera Cam;
|
||||
bool controlOn;
|
||||
float controlTime;
|
||||
|
||||
[Header("Light")]
|
||||
public GameObject Light;
|
||||
public GameObject CameraTargetHelper;
|
||||
public Vector3 TargetCenter;
|
||||
|
||||
EventSystem eventSystem;
|
||||
|
||||
[Header("Free Camera")]
|
||||
bool FreeCamLeft = false;
|
||||
bool FreeCamRight = false;
|
||||
public Vector3 lookRotation;
|
||||
|
||||
private CameraSettings _settings => ModelViewerMain.GetInstance().GetCameraHandler().Settings;
|
||||
|
||||
private CameraTransformCommand _tempCommand;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
public CameraOrbit Init()
|
||||
{
|
||||
Cam = GetComponentInChildren<Camera>();
|
||||
eventSystem = EventSystem.current;
|
||||
return this;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (ModelViewerMain.GetInstance() == null) return;
|
||||
UpdateImmediate();
|
||||
}
|
||||
|
||||
public void UpdateImmediate()
|
||||
{
|
||||
if (HandleManager.InteractionInProgress || _settings.CameraLock) return;
|
||||
|
||||
switch (_settings.CameraMode)
|
||||
{
|
||||
case 0:
|
||||
OrbitAround();
|
||||
OrbitLight();
|
||||
break;
|
||||
case 1:
|
||||
OrbitAround(true);
|
||||
OrbitLight();
|
||||
break;
|
||||
case 2: FreeCamera(); break;
|
||||
}
|
||||
}
|
||||
|
||||
#region Camera
|
||||
/// <summary>
|
||||
/// Orbit camera around world center
|
||||
/// </summary>
|
||||
void OrbitAround(bool aroundCharacter = false)
|
||||
{
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
var settings = _settings;
|
||||
|
||||
using (var context = new KeyframeToggleContext(settings))
|
||||
{
|
||||
if (eventSystem.currentSelectedGameObject == null)
|
||||
{
|
||||
x = Input.GetAxis("Horizontal");
|
||||
y = Input.GetAxis("Vertical");
|
||||
}
|
||||
|
||||
if (aroundCharacter)
|
||||
{
|
||||
var selectedObject = ModelViewerMain.GetInstance().SelectedObject;
|
||||
TargetCenter = selectedObject != null ? selectedObject.GetCenter() : Vector3.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetCenter = Vector3.zero;
|
||||
}
|
||||
|
||||
Cam.fieldOfView = settings.Fov;
|
||||
Vector3 position = transform.position;
|
||||
Vector3 rotation = Cam.transform.localEulerAngles;
|
||||
|
||||
if (Input.GetMouseButtonDown(0) && !eventSystem.IsPointerOverGameObject())
|
||||
{
|
||||
StartKeyframe();
|
||||
controlOn = true;
|
||||
controlTime = 0;
|
||||
}
|
||||
if (Input.GetMouseButton(0) && controlOn)
|
||||
{
|
||||
controlTime += Time.deltaTime;
|
||||
position -= Input.GetAxis("Mouse X") * settings.RotSpeed * transform.right;
|
||||
settings.SliderCamDist.value -= Input.mouseScrollDelta.y * settings.ZoomSpeed;
|
||||
settings.SliderCamHeight.value -= Input.GetAxis("Mouse Y") * settings.RotSpeed;
|
||||
}
|
||||
else if (controlOn)
|
||||
{
|
||||
controlOn = false;
|
||||
if (controlTime > 0.2f)
|
||||
{
|
||||
context.ForceSetKeyframe();
|
||||
EndKeyframe();
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonDown(2) && !eventSystem.IsPointerOverGameObject())
|
||||
{
|
||||
StartKeyframe();
|
||||
CameraTargetHelper.SetActive(true);
|
||||
controlTime = 0;
|
||||
}
|
||||
if (Input.GetMouseButton(2) && CameraTargetHelper.activeSelf)
|
||||
{
|
||||
controlTime += Time.deltaTime;
|
||||
settings.SliderTargetHeight.value -= Input.GetAxis("Mouse Y");
|
||||
CameraTargetHelper.transform.position = settings.SliderTargetHeight.value * Vector3.up;
|
||||
}
|
||||
if (CameraTargetHelper.activeSelf && Input.GetMouseButtonUp(2))
|
||||
{
|
||||
CameraTargetHelper.SetActive(false);
|
||||
if (controlTime > 0.2f)
|
||||
{
|
||||
context.ForceSetKeyframe();
|
||||
EndKeyframe();
|
||||
}
|
||||
}
|
||||
|
||||
float camDist = settings.CamDist;
|
||||
settings.SliderCamHeight.maxValue = camDist + 1 - camDist * 0.2f;
|
||||
settings.SliderCamHeight.minValue = -camDist + 1 + camDist * 0.2f;
|
||||
settings.SliderCamHeight.value += y * settings.RotSpeed;
|
||||
|
||||
Vector3 target = TargetCenter + settings.TargetHeight * Vector3.up; //set target offsets
|
||||
|
||||
position.y = TargetCenter.y + settings.CamHeight; //set camera height
|
||||
transform.position = position; //set final position of camera at target
|
||||
transform.position += (x * transform.right) * settings.RotSpeed;
|
||||
|
||||
//Debug.Log(rotation);
|
||||
transform.LookAt(target); //look at target position
|
||||
Cam.transform.localEulerAngles = settings.CamAngle * Vector3.forward;
|
||||
transform.position = target - transform.forward * camDist; //move away from target
|
||||
lookRotation = transform.localEulerAngles;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free Camera, Unity-Style
|
||||
/// </summary>
|
||||
void FreeCamera()
|
||||
{
|
||||
var settings = _settings; ;
|
||||
//Debug.Log("1 " + lookRotation);
|
||||
//Debug.Log("2 " + transform.localEulerAngles);
|
||||
//Debug.Log("3 " + transform.eulerAngles);
|
||||
Cam.fieldOfView = settings.Fov;
|
||||
float moveSpeed = settings.MovSpeed;
|
||||
float rotateSpeed = settings.RotSpeed;
|
||||
|
||||
if (Input.GetMouseButtonDown(0) && !eventSystem.IsPointerOverGameObject())
|
||||
{
|
||||
StartKeyframe();
|
||||
lookRotation = transform.localEulerAngles;
|
||||
FreeCamLeft = true;
|
||||
controlTime = 0;
|
||||
}
|
||||
if (Input.GetMouseButton(0) && FreeCamLeft)
|
||||
{
|
||||
controlTime += Time.deltaTime;
|
||||
transform.position += Input.GetAxis("Vertical") * transform.forward * Time.deltaTime * moveSpeed;
|
||||
transform.position += Input.GetAxis("Horizontal") * transform.right * Time.deltaTime * moveSpeed;
|
||||
|
||||
lookRotation.x -= Input.GetAxis("Mouse Y") * rotateSpeed;
|
||||
lookRotation.y += Input.GetAxis("Mouse X") * rotateSpeed;
|
||||
|
||||
lookRotation.x = Mathf.Clamp(lookRotation.x, -90, 90);
|
||||
if (lookRotation.y >= 360) lookRotation.y -= 360;
|
||||
if (lookRotation.y <= -360) lookRotation.y += 360;
|
||||
//x (up down) y (left right) changes
|
||||
transform.localRotation = Quaternion.Euler(lookRotation.x, lookRotation.y, lookRotation.z);
|
||||
}
|
||||
else if (FreeCamLeft)
|
||||
{
|
||||
FreeCamLeft = false;
|
||||
if (controlTime > 0.2f)
|
||||
{
|
||||
ModelViewerMain.GetInstance().GetCameraHandler().SetKeyframe();
|
||||
EndKeyframe();
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonDown(1) && !eventSystem.IsPointerOverGameObject())
|
||||
{
|
||||
StartKeyframe();
|
||||
FreeCamRight = true;
|
||||
controlTime = 0;
|
||||
}
|
||||
if (Input.GetMouseButton(1) && FreeCamRight)
|
||||
{
|
||||
controlTime += Time.deltaTime;
|
||||
transform.position += Input.GetAxis("Mouse X") * transform.right * Time.deltaTime * moveSpeed;
|
||||
transform.position += Input.GetAxis("Mouse Y") * transform.up * Time.deltaTime * moveSpeed;
|
||||
}
|
||||
else if (FreeCamRight)
|
||||
{
|
||||
FreeCamRight = false;
|
||||
if (controlTime > 0.2f)
|
||||
{
|
||||
ModelViewerMain.GetInstance().GetCameraHandler().SetKeyframe();
|
||||
EndKeyframe();
|
||||
}
|
||||
}
|
||||
Cam.transform.localEulerAngles = settings.CamAngle * Vector3.forward;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Light
|
||||
/// <summary>
|
||||
/// Rotate Light Source
|
||||
/// </summary>
|
||||
private void OrbitLight()
|
||||
{
|
||||
if (Input.GetMouseButton(1) && !LightLock)
|
||||
{
|
||||
Light.transform.Rotate(Input.GetAxis("Mouse X") * Vector3.up, Space.Self);
|
||||
Light.transform.Rotate(Input.GetAxis("Mouse Y") * Vector3.right, Space.Self);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLightColor(Color color)
|
||||
{
|
||||
Light.GetComponent<Light>().color = color;
|
||||
}
|
||||
|
||||
public void SetLightIntensity(float value)
|
||||
{
|
||||
Light.GetComponent<Light>().intensity = value;
|
||||
}
|
||||
|
||||
public void SetLightShadowIntensity(float value)
|
||||
{
|
||||
Light.GetComponent<Light>().shadowStrength = value;
|
||||
}
|
||||
|
||||
public void SetLightShadows(int value)
|
||||
{
|
||||
Light.GetComponent<Light>().shadows = (LightShadows)value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void StartKeyframe()
|
||||
{
|
||||
var cam = ModelViewerMain.GetInstance().GetCameraHandler();
|
||||
if (cam == ModelViewerMain.GetInstance().WorkCameraOrbit)
|
||||
{
|
||||
_tempCommand = null;
|
||||
return;
|
||||
}
|
||||
_tempCommand = new CameraTransformCommand()
|
||||
{
|
||||
Container = cam,
|
||||
OldValues = cam.SerializeFrame() as KeyframeDataCamera,
|
||||
Frame = TimelineController.Instance.CurrentFrame
|
||||
};
|
||||
}
|
||||
|
||||
private void EndKeyframe()
|
||||
{
|
||||
if (_tempCommand != null )
|
||||
{
|
||||
_tempCommand.NewValues = _tempCommand.Container.SerializeFrame() as KeyframeDataCamera;
|
||||
UndoRedoManager.Insert(_tempCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/CameraOrbit.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/CameraOrbit.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32a48605970827e4999f4dd7807a5eac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
119
Assets/Scripts/ModelViewerBase/CameraSettings.cs
Normal file
119
Assets/Scripts/ModelViewerBase/CameraSettings.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class CameraSettings : MonoBehaviour, IKeyframeSetter
|
||||
{
|
||||
protected bool _setKeyframe = true;
|
||||
|
||||
[Header("Scene")]
|
||||
public SliderPanel
|
||||
SliderFov;
|
||||
public SliderPanel
|
||||
SliderCamDist,
|
||||
SliderCamHeight,
|
||||
SliderTargetHeight,
|
||||
SliderCamAngle;
|
||||
|
||||
[Header("Unsaved")]
|
||||
public SliderPanel
|
||||
SliderMovSpeed;
|
||||
public SliderPanel
|
||||
SliderRotSpeed,
|
||||
SliderZoomSpeed;
|
||||
|
||||
public Toggle ToggleCameraLock;
|
||||
public Toggle ToggleWorkCamera;
|
||||
|
||||
public ExtendedDropdown BackgroundDropdown;
|
||||
public TMPro.TMP_Dropdown DropdownCameraMode;
|
||||
|
||||
public GameObject ColorPickerPanel;
|
||||
|
||||
public int CameraMode => DropdownCameraMode.value;
|
||||
|
||||
public bool CameraLock => ToggleCameraLock.isOn;
|
||||
|
||||
public float Fov => SliderFov.value;
|
||||
public float CamDist => SliderCamDist.value;
|
||||
public float CamHeight => SliderCamHeight.value;
|
||||
public float TargetHeight => SliderTargetHeight.value;
|
||||
public float CamAngle => SliderCamAngle.value;
|
||||
public float MovSpeed => SliderMovSpeed.value;
|
||||
public float RotSpeed => SliderRotSpeed.value;
|
||||
public float ZoomSpeed => SliderZoomSpeed.value;
|
||||
|
||||
public void SwapCamera(bool workCameraMode)
|
||||
{
|
||||
var mainCamera = ModelViewerMain.GetInstance().MainCameraOrbit;
|
||||
var workCamera = ModelViewerMain.GetInstance().WorkCameraOrbit;
|
||||
|
||||
var camera = mainCamera.Camera;
|
||||
|
||||
if (workCameraMode)
|
||||
{
|
||||
mainCamera.LastPosition = mainCamera.SerializeFrame() as KeyframeDataCamera;
|
||||
mainCamera.transform.SetPositionAndRotation(camera.Cam.transform.position, camera.Cam.transform.rotation);
|
||||
mainCamera.LineRenderer.enabled = true;
|
||||
workCamera.LineRenderer.enabled = false;
|
||||
|
||||
if(workCamera.LastPosition.Root.Position == Vector3.zero)
|
||||
{
|
||||
workCamera.PastePose(mainCamera.LastPosition, new PoseLoadOptions(true));
|
||||
}
|
||||
else
|
||||
{
|
||||
workCamera.PastePose(workCamera.LastPosition, new PoseLoadOptions(true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
workCamera.LastPosition = workCamera.SerializeFrame() as KeyframeDataCamera;
|
||||
workCamera.transform.SetPositionAndRotation(camera.Cam.transform.position, camera.Cam.transform.rotation);
|
||||
//WorkCameraOrbit.LineRenderer.enabled = true;
|
||||
mainCamera.LineRenderer.enabled = false;
|
||||
|
||||
mainCamera.PastePose(mainCamera.LastPosition, new PoseLoadOptions(true));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetKeyframe(int frameNum = -1)
|
||||
{
|
||||
if (ToggleWorkCamera.isOn || !_setKeyframe) return;
|
||||
|
||||
ModelViewerMain.GetInstance().MainCameraOrbit.SetKeyframe();
|
||||
}
|
||||
|
||||
public void EnableKeyframeSet()
|
||||
{
|
||||
_setKeyframe = true;
|
||||
}
|
||||
|
||||
public void DisableKeyframeSet()
|
||||
{
|
||||
_setKeyframe = false;
|
||||
}
|
||||
|
||||
public void OnBackgroundDropdownSelected(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
Camera.main.clearFlags = CameraClearFlags.Skybox;
|
||||
//ColorPickerPanel.SetActive(false);
|
||||
break;
|
||||
case 1:
|
||||
Camera.main.clearFlags = CameraClearFlags.SolidColor;
|
||||
//ColorPickerPanel.SetActive(true);
|
||||
break;
|
||||
case 2:
|
||||
Camera.main.clearFlags = CameraClearFlags.Nothing;
|
||||
//ColorPickerPanel.SetActive(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBackgroundColor(Color color)
|
||||
{
|
||||
Camera.main.backgroundColor = color;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/CameraSettings.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/CameraSettings.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38982c2df9f1d8143ab670461e160feb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/ModelViewerBase/Containers.meta
Normal file
8
Assets/Scripts/ModelViewerBase/Containers.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee079ecd1686a3d43ae7b09d94eb43bb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
137
Assets/Scripts/ModelViewerBase/Containers/CameraContainer.cs
Normal file
137
Assets/Scripts/ModelViewerBase/Containers/CameraContainer.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
|
||||
public class CameraContainer: ObjectContainer
|
||||
{
|
||||
public CameraOrbit Camera;
|
||||
public KeyframeDataCamera LastPosition;
|
||||
public LineRenderer LineRenderer;
|
||||
|
||||
public CameraSettings Settings;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
//Set default keyframe in custom ModelViewerMain
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!LineRenderer.enabled) return;
|
||||
|
||||
float fov = Settings.Fov;
|
||||
float aspect = Camera.Cam.aspect;
|
||||
float nearPlane = Camera.Cam.nearClipPlane;
|
||||
float farPlane = Camera.Cam.farClipPlane;
|
||||
|
||||
Vector3[] far = CalculateCameraFrustRect(fov, aspect, farPlane, transform);
|
||||
Vector3[] near = CalculateCameraFrustRect(fov, aspect, nearPlane, transform);
|
||||
|
||||
var edges = new Vector3[]
|
||||
{
|
||||
far[0], far[1], far[2], far[3], far[0], near[0], near[1], near[2], near[3], near[0], near[1], far[1], far[2], near[2], near[3], far[3]
|
||||
};
|
||||
|
||||
LineRenderer.positionCount = edges.Length;
|
||||
LineRenderer.SetPositions(edges);
|
||||
}
|
||||
|
||||
private static Vector3[] CalculateCameraFrustRect(float fieldOfView, float aspect, float dist, Transform transform)
|
||||
{
|
||||
dist = Mathf.Clamp(dist, 0.1f, 20f);
|
||||
|
||||
Vector3[] rect = new Vector3[4];
|
||||
float frustumHeight = 2.0F * dist * Mathf.Tan(fieldOfView * 0.5F * Mathf.Deg2Rad);
|
||||
rect[0] = transform.TransformPoint(new Vector3(-frustumHeight * aspect / 2, frustumHeight / 2, dist));
|
||||
rect[1] = transform.TransformPoint(new Vector3(frustumHeight * aspect / 2, frustumHeight / 2, dist));
|
||||
rect[2] = transform.TransformPoint(new Vector3(frustumHeight * aspect / 2, -frustumHeight / 2, dist));
|
||||
rect[3] = transform.TransformPoint(new Vector3(-frustumHeight * aspect / 2, -frustumHeight / 2, dist));
|
||||
|
||||
return (rect);
|
||||
}
|
||||
|
||||
Vector3 TransformPoint(Vector3 transforPos, Quaternion transformRotation, Vector3 transformScale, Vector3 pos)
|
||||
{
|
||||
Matrix4x4 matrix = Matrix4x4.TRS(transforPos, transformRotation, transformScale);
|
||||
return matrix.MultiplyPoint3x4(pos);
|
||||
}
|
||||
|
||||
Vector3 InverseTransformPoint(Vector3 transforPos, Quaternion transformRotation, Vector3 transformScale, Vector3 pos)
|
||||
{
|
||||
Matrix4x4 matrix = Matrix4x4.TRS(transforPos, transformRotation, transformScale);
|
||||
Matrix4x4 inverse = matrix.inverse;
|
||||
return inverse.MultiplyPoint3x4(pos);
|
||||
}
|
||||
|
||||
public override ObjectContainerSerializable Serialize()
|
||||
{
|
||||
var serialized = new CameraContainerSerializable(this);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
public override KeyframeData SerializeFrame()
|
||||
{
|
||||
return new KeyframeDataCamera(this);
|
||||
}
|
||||
|
||||
public override void Deserialize(ObjectContainerSerializable serialized)
|
||||
{
|
||||
DeserializeFrames(serialized);
|
||||
}
|
||||
|
||||
public override void Lerp(KeyframeData frame1, KeyframeData frame2, float amount)
|
||||
{
|
||||
var tsf = frame1 as KeyframeDataCamera;
|
||||
|
||||
if (frame1 != frame2)
|
||||
{
|
||||
tsf = tsf.Lerp(frame2, amount) as KeyframeDataCamera;
|
||||
}
|
||||
|
||||
var orbitLocator = ModelViewerMain.GetInstance().MainCameraOrbit;
|
||||
|
||||
if (ModelViewerMain.GetInstance().GetCameraHandler() == ModelViewerMain.GetInstance().WorkCameraOrbit)
|
||||
{
|
||||
//if in work camera mode, move the camera locator only
|
||||
orbitLocator.transform.position = tsf.Root.Position;
|
||||
orbitLocator.transform.eulerAngles = tsf.Root.Rotation;
|
||||
orbitLocator.LastPosition = tsf;
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitLocator.PastePose(tsf, new PoseLoadOptions(true));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
{
|
||||
}
|
||||
|
||||
public override void PastePose(KeyframeData frame, PoseLoadOptions pasteParams = null)
|
||||
{
|
||||
var keyframe = frame as KeyframeDataCamera;
|
||||
Camera.transform.localPosition = keyframe.Root.Position;
|
||||
Camera.transform.localEulerAngles = keyframe.Root.Rotation;
|
||||
Camera.lookRotation = keyframe.Root.Rotation;
|
||||
//if (Camera.lookRotation.x > 90) Camera.lookRotation.x -= 360;
|
||||
//if (Camera.lookRotation.x < -90) Camera.lookRotation.x += 360;
|
||||
//lookRotation.x = lookRotation.x - 360;
|
||||
|
||||
using (new KeyframeToggleContext(this))
|
||||
{
|
||||
Settings.DropdownCameraMode.value = keyframe.CameraMode;
|
||||
//Settings.ToggleCameraLock.isOn = keyframe.CameraLock;
|
||||
Settings.SliderFov.value = keyframe.Fov;
|
||||
Settings.SliderCamDist.value = keyframe.CamDist;
|
||||
Settings.SliderCamHeight.value = keyframe.CamHeight;
|
||||
Settings.SliderTargetHeight.value = keyframe.TargetHeigh;
|
||||
Settings.SliderCamAngle.value = keyframe.CamAngle;
|
||||
}
|
||||
|
||||
Camera.UpdateImmediate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72e8d74079817324498115876d689669
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
[Serializable]
|
||||
public class CameraContainerSerializable : ObjectContainerSerializable
|
||||
{
|
||||
public CameraContainerSerializable() { }
|
||||
|
||||
public CameraContainerSerializable(CameraContainer container)
|
||||
{
|
||||
GUID = "cameraOrbit";
|
||||
Frames = container.Frames.Select(f => new FrameContent(f)).ToList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a1693bb5411564489cd61fa721c0fd0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
257
Assets/Scripts/ModelViewerBase/Containers/ObjectContainer.cs
Normal file
257
Assets/Scripts/ModelViewerBase/Containers/ObjectContainer.cs
Normal file
@@ -0,0 +1,257 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ObjectContainer : MonoBehaviour, IKeyframeSetter
|
||||
{
|
||||
[JsonIgnore] public bool DoNotSave;
|
||||
public int ModelId;
|
||||
public string GUID = "";
|
||||
public bool LoadInProgress = false;
|
||||
|
||||
public List<UIHandle> Handles = new List<UIHandle>();
|
||||
public List<Renderer> Renderers = new List<Renderer>();
|
||||
public Dictionary<SkinnedMeshRenderer, List<MorphHelper>> Morphs = new Dictionary<SkinnedMeshRenderer, List<MorphHelper>>();
|
||||
public List<FrameContent> Frames = new List<FrameContent>();
|
||||
public List<GameObject> InstantiatedObjects = new List<GameObject>();
|
||||
protected bool _setKeyframe = true;
|
||||
protected bool _applicationQuitting = false;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
if (GUID == "")
|
||||
GUID = System.Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
public static T Create<T>(string name = "Container") where T : ObjectContainer
|
||||
{
|
||||
var container = new GameObject(name).AddComponent<T>();
|
||||
return container;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
if (ModelViewerMain.GetInstance() == null) return;
|
||||
if (DoNotSave) return;
|
||||
|
||||
if (Frames.Count == 0)
|
||||
{
|
||||
SetKeyframe();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void PasteContainer(ObjectContainerSerializable bones, PoseLoadOptions pasteParams)
|
||||
{
|
||||
GUID = bones.GUID;
|
||||
}
|
||||
|
||||
public virtual Vector3 GetCenter() { return transform.position; }
|
||||
|
||||
public void ToggleVisible(GameObject go, bool value)
|
||||
{
|
||||
go.SetActive(value);
|
||||
}
|
||||
|
||||
public void ToggleRendererVisible(Renderer r, bool value)
|
||||
{
|
||||
r.enabled = value;
|
||||
}
|
||||
|
||||
public virtual ObjectContainerSerializable Serialize()
|
||||
{
|
||||
return new ObjectContainerSerializable(this);
|
||||
}
|
||||
|
||||
public virtual KeyframeData SerializeFrame()
|
||||
{
|
||||
return new KeyframeData(this);
|
||||
}
|
||||
|
||||
public virtual void Deserialize(ObjectContainerSerializable serialized)
|
||||
{
|
||||
throw new NotImplementedException(GetType().FullName);
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
if (_applicationQuitting) return;
|
||||
|
||||
foreach (var rend in Renderers)
|
||||
{
|
||||
for (int i = rend.sharedMaterials.Length - 1; i >= 0; i--)
|
||||
{
|
||||
Destroy(rend.sharedMaterials[i]);
|
||||
}
|
||||
}
|
||||
foreach (var obj in InstantiatedObjects)
|
||||
{
|
||||
Destroy(obj);
|
||||
}
|
||||
ModelViewerMain.UnregisterObject(this);
|
||||
if (gameObject != null)
|
||||
Destroy(gameObject);
|
||||
Resources.UnloadUnusedAssets();
|
||||
System.GC.Collect();
|
||||
}
|
||||
|
||||
#region Timeline
|
||||
public virtual DataType GetDataType()
|
||||
{
|
||||
switch (this)
|
||||
{
|
||||
case SceneContainer _:
|
||||
return DataType.Scene;
|
||||
case CameraContainer _:
|
||||
return DataType.Camera;
|
||||
default:
|
||||
return DataType.Character;
|
||||
}
|
||||
}
|
||||
|
||||
public FrameContent TryGetFrame(int frameNum)
|
||||
{
|
||||
return Frames.FirstOrDefault(f => f.FrameNum == frameNum);
|
||||
}
|
||||
|
||||
public void GetClosestFrames(int frame, out FrameContent previousFrame, out FrameContent nextFrame)
|
||||
{
|
||||
previousFrame = null;
|
||||
nextFrame = null;
|
||||
|
||||
var frames = Frames.OrderBy(f => f.FrameNum).ToArray();
|
||||
|
||||
for (int i = 0; i < Frames.Count; i++)
|
||||
{
|
||||
if (Frames[i].FrameNum < frame)
|
||||
{
|
||||
previousFrame = nextFrame = frames[i];
|
||||
}
|
||||
else if (Frames[i].FrameNum == frame)
|
||||
{
|
||||
previousFrame = nextFrame = frames[i];
|
||||
break;
|
||||
}
|
||||
else if (Frames[i].FrameNum > frame)
|
||||
{
|
||||
if (previousFrame == null) previousFrame = frames[i];
|
||||
nextFrame = frames[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Returns true if frame existed or false if it was created </summary>
|
||||
public bool GetCurrentFrame(int frame, out FrameContent currentFrame)
|
||||
{
|
||||
GetClosestFrames(frame, out var previousFrame, out var nextFrame);
|
||||
|
||||
if (previousFrame.FrameNum == frame)
|
||||
{
|
||||
currentFrame = previousFrame;
|
||||
return true;
|
||||
}
|
||||
else if (nextFrame.FrameNum == frame)
|
||||
{
|
||||
currentFrame = nextFrame;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentFrame = new FrameContent(frame);
|
||||
Frames.Add(currentFrame);
|
||||
Frames = Frames.OrderBy(f => f.FrameNum).ToList();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetKeyframe(int frameNum = -1)
|
||||
{
|
||||
if (DoNotSave || !_setKeyframe) return;
|
||||
Debug.Log("Setting frame for " + name);
|
||||
//if (Frames.Count == 0) SetDefaultFrame();
|
||||
if (frameNum == -1) frameNum = TimelineController.Instance.CurrentFrame;
|
||||
|
||||
GetClosestFrames(frameNum, out var previousFrame, out var nextFrame);
|
||||
|
||||
FrameContent currentFrame = null;
|
||||
if (previousFrame == null || previousFrame.FrameNum != frameNum)
|
||||
{
|
||||
currentFrame = new FrameContent(frameNum);
|
||||
Frames.Add(currentFrame);
|
||||
Frames = Frames.OrderBy(f => f.FrameNum).ToList();
|
||||
}
|
||||
else if (previousFrame.FrameNum == frameNum) currentFrame = previousFrame;
|
||||
else if (nextFrame.FrameNum == frameNum) currentFrame = nextFrame;
|
||||
|
||||
currentFrame.SetObjectData(SerializeFrame());
|
||||
|
||||
TimelineController.UpdateTimeline();
|
||||
}
|
||||
|
||||
public void SetDefaultFrame()
|
||||
{
|
||||
Frames = new List<FrameContent>()
|
||||
{
|
||||
new FrameContent(0).SetObjectData(SerializeFrame())
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public virtual void DeserializeFrames(ObjectContainerSerializable serialized)
|
||||
{
|
||||
Frames = serialized.Frames.Select(f => new FrameContent(f)).ToList();
|
||||
}
|
||||
|
||||
public virtual void Lerp(KeyframeData frame1, KeyframeData frame2, float amount)
|
||||
{
|
||||
if (frame1 == frame2)
|
||||
{
|
||||
PastePose(frame1, new PoseLoadOptions(true));
|
||||
}
|
||||
else
|
||||
{
|
||||
PastePose(frame1.Lerp(frame2, amount), new PoseLoadOptions(true));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void PastePose(KeyframeData frame, PoseLoadOptions pasteParams)
|
||||
{
|
||||
if (pasteParams.Root)
|
||||
{
|
||||
transform.SetTransform(frame.Root);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Deselect()
|
||||
{
|
||||
throw new NotImplementedException(this.GetType().FullName);
|
||||
}
|
||||
|
||||
public virtual void Select()
|
||||
{
|
||||
throw new NotImplementedException(this.GetType().FullName);
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
|
||||
public void EnableKeyframeSet()
|
||||
{
|
||||
_setKeyframe = true;
|
||||
}
|
||||
|
||||
public void DisableKeyframeSet()
|
||||
{
|
||||
_setKeyframe = false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
_applicationQuitting = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bf6dfe0e5776cd49b8f8923c18704da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
[System.Serializable]
|
||||
public class ObjectContainerSerializable
|
||||
{
|
||||
public string Filename;
|
||||
public string GUID;
|
||||
public List<FrameContent> Frames;
|
||||
|
||||
public ObjectContainerSerializable() { }
|
||||
|
||||
public ObjectContainerSerializable(ObjectContainer containerBase)
|
||||
{
|
||||
this.Filename = containerBase.name;
|
||||
this.GUID = containerBase.GUID;
|
||||
this.Frames = containerBase.Frames.Select(frame => new FrameContent(frame)).ToList();
|
||||
}
|
||||
|
||||
public ObjectContainerSerializable(ObjectContainerSerializable source)
|
||||
{
|
||||
this.Filename = source.Filename;
|
||||
this.GUID = source.GUID;
|
||||
this.Frames = source.Frames.Select(frame => new FrameContent(frame)).ToList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85c39ae818417104eb7ae9174bd0f708
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Assets/Scripts/ModelViewerBase/Containers/SceneContainer.cs
Normal file
37
Assets/Scripts/ModelViewerBase/Containers/SceneContainer.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public class SceneContainer : ObjectContainer
|
||||
{
|
||||
public CameraContainer MainCameraOrbit;
|
||||
public CameraContainer WorkCameraOrbit;
|
||||
|
||||
public List<ObjectContainer> AllObjects = new List<ObjectContainer>();
|
||||
|
||||
public List<T> Objects<T>() where T : ObjectContainer
|
||||
{
|
||||
return AllObjects.Cast<T>().ToList();
|
||||
}
|
||||
|
||||
public static SceneContainer Create<T>(ModelViewerMain main) where T : SceneContainer
|
||||
{
|
||||
var container = new GameObject("Scene").AddComponent<T>();
|
||||
container.Init(main);
|
||||
return container;
|
||||
}
|
||||
|
||||
public virtual void Init(ModelViewerMain main)
|
||||
{
|
||||
GUID = "scene";
|
||||
MainCameraOrbit = main.MainCameraOrbit;
|
||||
WorkCameraOrbit = main.WorkCameraOrbit;
|
||||
SetDefaultFrame();
|
||||
AllObjects.Add(MainCameraOrbit);
|
||||
}
|
||||
|
||||
public override ObjectContainerSerializable Serialize()
|
||||
{
|
||||
return new SceneSerializable(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 520e0b69d9f17e2488c1eb19d9a50940
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
[Serializable]
|
||||
public class SceneSerializable : ObjectContainerSerializable
|
||||
{
|
||||
public string Version;
|
||||
public string Date;
|
||||
public TimelineControllerSerializable Timeline;
|
||||
public List<ObjectContainerSerializable> Objects = new List<ObjectContainerSerializable>();
|
||||
|
||||
public SceneSerializable() { }
|
||||
|
||||
public SceneSerializable(SceneContainer scene)
|
||||
{
|
||||
this.Version = Application.version;
|
||||
this.Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture); ;
|
||||
this.Timeline = new TimelineControllerSerializable(TimelineController.Instance);
|
||||
this.Frames = scene.Frames.Select(f => new FrameContent(f)).ToList();
|
||||
foreach (var obj in scene.AllObjects)
|
||||
{
|
||||
if (obj != scene)
|
||||
Objects.Add(obj.Serialize());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7592143342b8b0741831e85e6a2f88b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/ModelViewerBase/Inverse Kinematics.meta
Normal file
8
Assets/Scripts/ModelViewerBase/Inverse Kinematics.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d421e7c2f2db7e4c90eed5665505326
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,156 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class InverseKinematics : MonoBehaviour {
|
||||
private Material lineMaterial;
|
||||
private Dictionary<GameObject, Transform[]> linePoints = new Dictionary<GameObject, Transform[]>();
|
||||
public bool SoftEnabled = true;
|
||||
|
||||
public Transform upperArm;
|
||||
public Transform forearm;
|
||||
public Transform hand;
|
||||
public Transform elbow;
|
||||
public Transform target;
|
||||
[Space(20)]
|
||||
public Vector3 uppperArm_OffsetRotation;
|
||||
public Vector3 forearm_OffsetRotation;
|
||||
public Vector3 hand_OffsetRotation;
|
||||
[Space(20)]
|
||||
public bool handMatchesTargetRotation = true;
|
||||
[Space(20)]
|
||||
public bool linesVisible = true;
|
||||
public bool forceLinesInvisible = true;
|
||||
|
||||
float angle;
|
||||
float upperArm_Length;
|
||||
float forearm_Length;
|
||||
float arm_Length;
|
||||
float targetDistance;
|
||||
float adyacent;
|
||||
|
||||
public void SpawnLines(Color specialColor) {
|
||||
lineMaterial = new Material(Shader.Find("Legacy Shaders/Particles/Alpha Blended Premultiply"));
|
||||
NewLine(upperArm, elbow, 0.005f, Color.yellow);
|
||||
NewLine(elbow, target, 0.005f, Color.yellow);
|
||||
NewLine(upperArm, target, 0.005f, Color.white);
|
||||
NewLine(forearm, elbow, 0.01f, specialColor);
|
||||
}
|
||||
|
||||
void NewLine(Transform point1, Transform point2, float width, Color color)
|
||||
{
|
||||
GameObject go = new GameObject("line");
|
||||
go.layer = 5;
|
||||
go.transform.SetParent(this.transform);
|
||||
var lr = go.AddComponent<LineRenderer>();
|
||||
lr.startWidth = lr.endWidth = width;
|
||||
lr.startColor = lr.endColor = color;
|
||||
lr.sharedMaterial = lineMaterial;
|
||||
|
||||
linePoints.Add(go, new Transform[] { point1, point2 });
|
||||
}
|
||||
|
||||
void UpdateLines()
|
||||
{
|
||||
foreach(var kv in linePoints)
|
||||
{
|
||||
var lr = kv.Key.GetComponent<LineRenderer>();
|
||||
if (!SoftEnabled)
|
||||
{
|
||||
if(lr.enabled != SoftEnabled)
|
||||
{
|
||||
lr.enabled = SoftEnabled;
|
||||
}
|
||||
}
|
||||
else if((lr.enabled != linesVisible) || (lr.enabled && forceLinesInvisible))
|
||||
{
|
||||
if(forceLinesInvisible)
|
||||
{
|
||||
lr.enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lr.enabled = linesVisible;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < kv.Value.Length; i++)
|
||||
{
|
||||
lr.SetPosition(i, kv.Value[i].position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void LateUpdate () {
|
||||
if(upperArm != null && forearm != null && hand != null && elbow != null && target != null)
|
||||
{
|
||||
if (SoftEnabled)
|
||||
{
|
||||
upperArm_Length = Vector3.Distance(upperArm.position, forearm.position);
|
||||
forearm_Length = Vector3.Distance(forearm.position, hand.position);
|
||||
arm_Length = upperArm_Length + forearm_Length;
|
||||
targetDistance = Vector3.Distance(upperArm.position, target.position);
|
||||
targetDistance = Mathf.Min(targetDistance, arm_Length - arm_Length * 0.001f);
|
||||
|
||||
upperArm.LookAt(target, elbow.position - upperArm.position);
|
||||
upperArm.Rotate(uppperArm_OffsetRotation);
|
||||
|
||||
Vector3 cross = Vector3.Cross(elbow.position - upperArm.position, forearm.position - upperArm.position);
|
||||
|
||||
adyacent = ((upperArm_Length * upperArm_Length) - (forearm_Length * forearm_Length) + (targetDistance * targetDistance)) / (2 * targetDistance);
|
||||
|
||||
angle = Mathf.Acos(adyacent / upperArm_Length) * Mathf.Rad2Deg;
|
||||
|
||||
if (float.IsNaN(angle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Vector3 oldPosition = upperArm.localPosition;
|
||||
upperArm.RotateAround(upperArm.position, cross, -angle);
|
||||
upperArm.localPosition = oldPosition;
|
||||
|
||||
forearm.LookAt(target, cross);
|
||||
forearm.Rotate(forearm_OffsetRotation);
|
||||
|
||||
if (handMatchesTargetRotation)
|
||||
{
|
||||
hand.rotation = target.rotation;
|
||||
hand.Rotate(hand_OffsetRotation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//target.position = hand.position;
|
||||
//target.rotation = hand.rotation;
|
||||
//target.Rotate(-hand_OffsetRotation);
|
||||
//elbow.position = forearm.position;
|
||||
}
|
||||
UpdateLines();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Destroy(lineMaterial);
|
||||
foreach(var i in linePoints)
|
||||
{
|
||||
Destroy(i.Key);
|
||||
}
|
||||
Destroy(elbow.gameObject);
|
||||
Destroy(target.gameObject);
|
||||
}
|
||||
|
||||
void OnDrawGizmos(){
|
||||
if (linesVisible) {
|
||||
if(upperArm != null && elbow != null && hand != null && target != null && elbow != null){
|
||||
Gizmos.color = Color.gray;
|
||||
Gizmos.DrawLine (upperArm.position, forearm.position);
|
||||
Gizmos.DrawLine (forearm.position, hand.position);
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawLine (upperArm.position, target.position);
|
||||
Gizmos.color = Color.blue;
|
||||
Gizmos.DrawLine (forearm.position, elbow.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30d20bcf9ec4ed24b97a6e8ab136c34f
|
||||
timeCreated: 1499795966
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
38
Assets/Scripts/ModelViewerBase/ModelBuilder.cs
Normal file
38
Assets/Scripts/ModelViewerBase/ModelBuilder.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
public class ModelBuilder : MonoBehaviour
|
||||
{
|
||||
public static ModelBuilder _mainInstance;
|
||||
|
||||
public static ModelBuilder GetInstance()
|
||||
{
|
||||
return _mainInstance;
|
||||
}
|
||||
|
||||
public static T GetInstance<T>() where T : ModelBuilder
|
||||
{
|
||||
return _mainInstance as T;
|
||||
}
|
||||
|
||||
public virtual IEnumerator SpawnSerialized(ObjectContainerSerializable oc, Action<GameObject> callback = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerator SpawnAsset(string assetPath, Action<ObjectContainer> callback = null)
|
||||
{
|
||||
yield return SpawnAsset(AssetTypes.Unknown, assetPath, callback);
|
||||
}
|
||||
|
||||
public virtual IEnumerator SpawnAsset(Enum assetType, string assetPath, Action<ObjectContainer> callback = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public virtual IEnumerator SpawnAsset(AssetSpawnData data, Action<ObjectContainer> callback = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/ModelBuilder.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/ModelBuilder.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3553f9c3dfc57b14d95850ae26fc05e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
21
Assets/Scripts/ModelViewerBase/ModelViewerBase.asmdef
Normal file
21
Assets/Scripts/ModelViewerBase/ModelViewerBase.asmdef
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "ModelViewerBase",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:24ad1c085c49dc34dbe16c3d92c6f299",
|
||||
"GUID:aee7fa92e14bf364ebccdd24623e1764",
|
||||
"GUID:ee695b84b4c90104b9367eebc6b0d70d",
|
||||
"GUID:9e24947de15b9834991c9d8411ea37cf",
|
||||
"GUID:84651a3751eca9349aac36a66bba901b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f135e4ce2898524aa1e81c5cd7f1242
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
197
Assets/Scripts/ModelViewerBase/ModelViewerDownloader.cs
Normal file
197
Assets/Scripts/ModelViewerBase/ModelViewerDownloader.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
public class ModelViewerDownloader
|
||||
{
|
||||
public static string UrlBase = "";
|
||||
public static string SaveLocation = "/idbfs/ModelViewer/";
|
||||
|
||||
public static ModelViewerDownloader Instance;
|
||||
public bool SyncRequired;
|
||||
|
||||
public ModelViewerDownloader() : this(UrlBase, "/idbfs/ModelViewer/") { }
|
||||
|
||||
public ModelViewerDownloader(string baseUrl, string saveLocation)
|
||||
{
|
||||
UrlBase = baseUrl;
|
||||
SaveLocation = saveLocation;
|
||||
ModelViewerMain.GetInstance().StartCoroutine(Loop());
|
||||
}
|
||||
|
||||
public class DownloadTask
|
||||
{
|
||||
public string Name;
|
||||
public bool Redownload = false;
|
||||
public bool Finished = false;
|
||||
public bool Success = false;
|
||||
public int Priority = 0;
|
||||
public string ResultText;
|
||||
public byte[] ResultBytes;
|
||||
public System.Action OnDownloadSuccess;
|
||||
|
||||
public DownloadTask(string name, int priority, bool redownload)
|
||||
{
|
||||
Name = name;
|
||||
Priority = priority;
|
||||
Redownload = redownload;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<DownloadTask> _downloadRunning = new List<DownloadTask>();
|
||||
private static List<DownloadTask> _downloadQueue = new List<DownloadTask>();
|
||||
|
||||
public IEnumerator Loop()
|
||||
{
|
||||
float lastSync = 5;
|
||||
while (true)
|
||||
{
|
||||
if(_downloadQueue.Count > 0)
|
||||
{
|
||||
_downloadRunning.AddRange(_downloadQueue);
|
||||
_downloadRunning = _downloadRunning.OrderByDescending(d=>d.Priority).ToList();
|
||||
_downloadQueue.Clear();
|
||||
}
|
||||
if(_downloadRunning.Count > 0)
|
||||
{
|
||||
var fileToDownload = _downloadRunning[0];
|
||||
_downloadRunning.RemoveAt(0);
|
||||
yield return DownloadFile(fileToDownload);
|
||||
if(!_downloadRunning.Any() && !_downloadQueue.Any())
|
||||
{
|
||||
SyncRequired = true;
|
||||
lastSync = 0;
|
||||
}
|
||||
}
|
||||
if(SyncRequired)
|
||||
{
|
||||
lastSync += Time.deltaTime;
|
||||
if(lastSync >= 5)
|
||||
{
|
||||
CommitChanges();
|
||||
}
|
||||
}
|
||||
yield return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerator WaitForDownload(string name, int priority = 0, bool redownload = false, System.Action<string[]> lines = null, System.Action<byte[]> bytes = null, System.Action<string> text = null, System.Action onDownloadSuccess = null)
|
||||
{
|
||||
var task = _downloadQueue.Concat(_downloadRunning).FirstOrDefault(t => t.Name == name);
|
||||
|
||||
if(task == null)
|
||||
{
|
||||
task = new DownloadTask(name, priority, redownload);
|
||||
task.OnDownloadSuccess = onDownloadSuccess;
|
||||
_downloadQueue.Add(task);
|
||||
}
|
||||
|
||||
while (!task.Finished)
|
||||
{
|
||||
yield return 0;
|
||||
}
|
||||
|
||||
lines?.Invoke(task.ResultText.Split('\n').Select(s => s.Trim()).ToArray());
|
||||
bytes?.Invoke(task.ResultBytes);
|
||||
text?.Invoke(task.ResultText);
|
||||
}
|
||||
|
||||
private IEnumerator DownloadFile(DownloadTask task)
|
||||
{
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
string fileSavePath = $"{SaveLocation}{task.Name}";
|
||||
#else
|
||||
string fileSavePath = Application.persistentDataPath + " /" + task.Name;
|
||||
#endif
|
||||
|
||||
if (!task.Redownload && LoadFromIdbfs(fileSavePath, out var data))
|
||||
{
|
||||
//Debug.Log("Loaded from " + fileSavePath);
|
||||
task.Success = true;
|
||||
task.ResultText = Encoding.UTF8.GetString(data);
|
||||
task.ResultBytes = data;
|
||||
task.Finished = true;
|
||||
yield break;
|
||||
}
|
||||
|
||||
string url = UrlBase + task.Name + (task.Redownload ? "?time=" + DateTime.Now.Ticks.ToString() : "");
|
||||
//var downloadPanel = KFKViewerUI.Instance.DownloadPanel;
|
||||
|
||||
//Msg.Log(url);
|
||||
|
||||
using (var www = UnityWebRequest.Get(url))
|
||||
{
|
||||
//downloadPanel.gameObject.SetActive(true);
|
||||
|
||||
var operation = www.SendWebRequest();
|
||||
|
||||
do
|
||||
{
|
||||
//downloadPanel.SetStatus(task.Name, www.downloadProgress);
|
||||
yield return null;
|
||||
}
|
||||
while (!operation.isDone);
|
||||
|
||||
if (www.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
Error.Log(Color.red, www.error);
|
||||
task.Success = false;
|
||||
task.ResultText = "";
|
||||
task.ResultBytes = new byte[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveToIdbfs(fileSavePath, www.downloadHandler.data);
|
||||
task.OnDownloadSuccess?.Invoke();
|
||||
task.Success = true;
|
||||
task.ResultText = www.downloadHandler.text;
|
||||
task.ResultBytes = www.downloadHandler.data;
|
||||
}
|
||||
}
|
||||
|
||||
//downloadPanel.SetStatus(task.Name, 0);
|
||||
//downloadPanel.gameObject.SetActive(false);
|
||||
|
||||
task.Finished = true;
|
||||
}
|
||||
|
||||
public static bool LoadFromIdbfs(string name, out byte[] data)
|
||||
{
|
||||
if(File.Exists(name))
|
||||
{
|
||||
data = File.ReadAllBytes(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveToIdbfs(string path, byte[] data)
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
File.WriteAllBytes(path, data);
|
||||
//Debug.Log("Saved " + path);
|
||||
}
|
||||
|
||||
private static void CommitChanges()
|
||||
{
|
||||
Instance.SyncRequired = false;
|
||||
Debug.Log("Database Updated");
|
||||
#if UNITY_WEBGL && !UNITY_EDITOR
|
||||
SyncFiles();
|
||||
#endif
|
||||
}
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void SyncFiles();
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/ModelViewerDownloader.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/ModelViewerDownloader.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 413260822fc499146b2e2bfdc91a5a21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
93
Assets/Scripts/ModelViewerBase/ModelViewerInterface.cs
Normal file
93
Assets/Scripts/ModelViewerBase/ModelViewerInterface.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UIPanels;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
public class ModelViewerInterface : MonoBehaviour
|
||||
{
|
||||
public static ModelViewerInterface _mainInstance;
|
||||
|
||||
public Transform DynamicPanels;
|
||||
public TMPro.TMP_Text[] TooltipLabels;
|
||||
|
||||
public ScrollRect ScenePresetToggle;
|
||||
public ScrollRect PosePresetToggle;
|
||||
|
||||
public List<UIToolbarPanel> TopbarPanels;
|
||||
|
||||
public UIPanels.UIToolbarPanel TogglesContent;
|
||||
public UIPanels.UISaveLoadPanel SaveLoadPanel;
|
||||
public UIPanels.UICameraSettingsPanel CameraSettingsPanel;
|
||||
|
||||
public Canvas MainCanvas;
|
||||
|
||||
public RectTransform Tooltip;
|
||||
public TMPro.TextMeshProUGUI TooltipText;
|
||||
|
||||
public static ModelViewerInterface GetInstance()
|
||||
{
|
||||
return _mainInstance;
|
||||
}
|
||||
|
||||
public static T GetInstance<T>() where T : ModelViewerInterface
|
||||
{
|
||||
return _mainInstance as T;
|
||||
}
|
||||
|
||||
public static void SetTooltip(int index, string tooltip)
|
||||
{
|
||||
var tooltips = GetInstance().TooltipLabels;
|
||||
if(tooltips.Length > index)
|
||||
{
|
||||
tooltips[index].SetText(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void ToggleVisible(GameObject go)
|
||||
{
|
||||
ToggleVisible(go, false);
|
||||
}
|
||||
|
||||
public static void ToggleVisible(GameObject go, bool force = false, bool forceValue = false)
|
||||
{
|
||||
if (force)
|
||||
{
|
||||
go.SetActive(forceValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
go.SetActive(!go.activeSelf);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetDropdownData(TMPro.TMP_Dropdown dd, List<string> values, bool nullValue = false, bool sortValues = false)
|
||||
{
|
||||
dd.ClearOptions();
|
||||
if (nullValue)
|
||||
dd.AddOptions(new List<string>() { Strings.NoValueSelectedString });
|
||||
if (values != null)
|
||||
{
|
||||
if (sortValues)
|
||||
{
|
||||
values = new List<string>(values);
|
||||
values.Sort();
|
||||
}
|
||||
dd.AddOptions(values);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DropdownPrevious(TMPro.TMP_Dropdown dropdown)
|
||||
{
|
||||
Error.Log(Color.red, "Remove this");
|
||||
dropdown.value = dropdown.value - 1 < 0 ? dropdown.options.Count - 1 : dropdown.value - 1;
|
||||
}
|
||||
|
||||
public static void DropdownNext(TMPro.TMP_Dropdown dropdown)
|
||||
{
|
||||
Error.Log(Color.red, "Remove this");
|
||||
dropdown.value = dropdown.value + 1 >= dropdown.options.Count ? 0 : dropdown.value + 1;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/ModelViewerInterface.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/ModelViewerInterface.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b1090dfa84b72140b13b27e73e267f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
178
Assets/Scripts/ModelViewerBase/ModelViewerMain.cs
Normal file
178
Assets/Scripts/ModelViewerBase/ModelViewerMain.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ModelViewerMain : MonoBehaviour
|
||||
{
|
||||
protected static ModelViewerMain _mainInstance;
|
||||
|
||||
[SerializeField]
|
||||
public CameraContainer
|
||||
MainCameraOrbit,
|
||||
WorkCameraOrbit;
|
||||
|
||||
public OperationMode Mode;
|
||||
public SceneContainer CurrentScene;
|
||||
public ObjectContainer SelectedObject;
|
||||
public List<ObjectContainer> SelectedObjects = new List<ObjectContainer>();
|
||||
|
||||
protected float[] _backupTimes = new float[] { 15 * 60, 5 * 60, 60 };
|
||||
protected float[] _backupTimers;
|
||||
|
||||
public enum OperationMode
|
||||
{
|
||||
Single,
|
||||
Multiple
|
||||
}
|
||||
|
||||
public static ModelViewerMain GetInstance()
|
||||
{
|
||||
return _mainInstance;
|
||||
}
|
||||
|
||||
public static T GetInstance<T>() where T : ModelViewerMain
|
||||
{
|
||||
return _mainInstance as T;
|
||||
}
|
||||
|
||||
public CameraOrbit GetCamera()
|
||||
{
|
||||
return CurrentScene.MainCameraOrbit.Camera;
|
||||
}
|
||||
|
||||
public CameraContainer GetCameraHandler()
|
||||
{
|
||||
if (!CurrentScene.MainCameraOrbit.LineRenderer.enabled)
|
||||
return CurrentScene.MainCameraOrbit;
|
||||
else
|
||||
return CurrentScene.WorkCameraOrbit;
|
||||
}
|
||||
|
||||
public static void RegisterObject(ObjectContainer container)
|
||||
{
|
||||
GetInstance().CurrentScene.AllObjects.Add(container);
|
||||
}
|
||||
|
||||
public static void UnregisterObject(ObjectContainer container)
|
||||
{
|
||||
GetInstance().CurrentScene.AllObjects.Remove(container);
|
||||
GetInstance().SelectionRemove(container);
|
||||
}
|
||||
|
||||
public T GetSelectedObject<T>() where T: ObjectContainer
|
||||
{
|
||||
return SelectedObject as T;
|
||||
}
|
||||
|
||||
public T GetCurrentScene<T>() where T : SceneContainer
|
||||
{
|
||||
return CurrentScene as T;
|
||||
}
|
||||
|
||||
public void SelectObject(ObjectContainer container)
|
||||
{
|
||||
if (SelectedObject == container) return;
|
||||
|
||||
Debug.Log(SelectedObject);
|
||||
|
||||
if(Mode == OperationMode.Single)
|
||||
{
|
||||
SelectedObject?.Destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedObject?.Deselect();
|
||||
}
|
||||
|
||||
SelectedObject = container;
|
||||
SelectedObject?.Select();
|
||||
|
||||
TimelineController.UpdateTimeline();
|
||||
}
|
||||
|
||||
public void SelectionAdd(ObjectContainer container)
|
||||
{
|
||||
if (container == null) return;
|
||||
|
||||
if (SelectedObjects.Count == 0)
|
||||
{
|
||||
SelectedObjects.Add(container);
|
||||
SelectObject(container);
|
||||
}
|
||||
else if(container != null && !SelectedObjects.Contains(container))
|
||||
{
|
||||
SelectedObjects.Add(container);
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectionRemove(ObjectContainer container)
|
||||
{
|
||||
if (container == null) return;
|
||||
|
||||
bool wasSelected = container == SelectedObject;
|
||||
|
||||
if (container != null && SelectedObjects.Contains(container))
|
||||
{
|
||||
SelectedObjects.Remove(container);
|
||||
if (wasSelected)
|
||||
{
|
||||
if(SelectedObjects.Count > 0)
|
||||
{
|
||||
SelectObject(SelectedObjects[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectObject(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SelectionClear()
|
||||
{
|
||||
SelectedObjects.Clear();
|
||||
}
|
||||
|
||||
public void EmptyScene<T>() where T : SceneContainer
|
||||
{
|
||||
DestroyImmediate(CurrentScene);
|
||||
CurrentScene = SceneContainer.Create<T>(this);
|
||||
|
||||
ModelViewerMain.GetInstance().SelectionClear();
|
||||
TimelineController.UpdateTimeline();
|
||||
}
|
||||
|
||||
public SceneSerializable SaveScene()
|
||||
{
|
||||
return CurrentScene.Serialize() as SceneSerializable;
|
||||
}
|
||||
|
||||
public virtual IEnumerator LoadScene(SceneSerializable bc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected void AutoSaveUpdate()
|
||||
{
|
||||
bool skip = false;
|
||||
for (int i = 0; i < _backupTimes.Length; i++)
|
||||
{
|
||||
_backupTimers[i] -= Time.deltaTime;
|
||||
if (skip)
|
||||
{
|
||||
_backupTimers[i] = _backupTimes[i];
|
||||
}
|
||||
else if (_backupTimers[i] <= 0)
|
||||
{
|
||||
_backupTimers[i] = _backupTimes[i];
|
||||
|
||||
var scene = SaveScene();
|
||||
scene.Filename = $"AutoBackup_{_backupTimes[i]}";
|
||||
UISceneContainer.CreateNew(scene, true).Save(true);
|
||||
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/ModelViewerMain.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/ModelViewerMain.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b829d711d6087b41a841693e6a48c1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/ModelViewerBase/Pose.meta
Normal file
8
Assets/Scripts/ModelViewerBase/Pose.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f8104f11c2f4d4498ca9a63e6ddebe6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
68
Assets/Scripts/ModelViewerBase/Pose/PoseLoadOptions.cs
Normal file
68
Assets/Scripts/ModelViewerBase/Pose/PoseLoadOptions.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class PoseLoadOptions
|
||||
{
|
||||
//general
|
||||
public bool
|
||||
Root,
|
||||
Morphs;
|
||||
|
||||
//body parts
|
||||
public bool
|
||||
Body,
|
||||
Ears,
|
||||
//EarsAlt,
|
||||
Tail,
|
||||
//TailAlt,
|
||||
Other;
|
||||
|
||||
//all
|
||||
public bool
|
||||
Position,
|
||||
Rotation,
|
||||
Scale;
|
||||
|
||||
public PoseLoadOptions(bool value)
|
||||
{
|
||||
Root = value;
|
||||
Morphs = value;
|
||||
Body = value;
|
||||
Ears = value;
|
||||
//EarsAlt = value;
|
||||
Tail = value;
|
||||
//TailAlt = value;
|
||||
Other = value;
|
||||
Position = value;
|
||||
Rotation = value;
|
||||
Scale = value;
|
||||
}
|
||||
|
||||
public static PoseLoadOptions None()
|
||||
{
|
||||
return new PoseLoadOptions(false);
|
||||
}
|
||||
|
||||
public static PoseLoadOptions All()
|
||||
{
|
||||
return new PoseLoadOptions(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PoseLoadOptionsExtra
|
||||
{
|
||||
public static void ApplyTo(this SerializableTransform tsf, Transform t, PoseLoadOptions options)
|
||||
{
|
||||
if (tsf.Space == Space.World)
|
||||
{
|
||||
if (options.Position) t.position = tsf.Position;
|
||||
if (options.Rotation) t.eulerAngles = tsf.Rotation;
|
||||
if (options.Scale) t.localScale = tsf.Scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options.Position) t.localPosition = tsf.Position;
|
||||
if (options.Rotation) t.localEulerAngles = tsf.Rotation;
|
||||
if (options.Scale) t.localScale = tsf.Scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/Pose/PoseLoadOptions.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/Pose/PoseLoadOptions.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f825489d1d491e478e07e6e6334ca16
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
public class SerializablePoseParams
|
||||
{
|
||||
public bool Body,
|
||||
Root,
|
||||
Ears,
|
||||
EarsAlt,
|
||||
Tail,
|
||||
TailAlt,
|
||||
PhysicsBones,
|
||||
Morphs;
|
||||
|
||||
public SerializablePoseParams() { }
|
||||
|
||||
public SerializablePoseParams(bool value)
|
||||
{
|
||||
Body = Root = Ears = EarsAlt = Tail = TailAlt = PhysicsBones = Morphs = true;
|
||||
}
|
||||
|
||||
public SerializablePoseParams SetRoot(bool value)
|
||||
{
|
||||
Root = value;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: adae87bbf883dae4baa06f2c4303f5cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/ModelViewerBase/Pose/Timeline.meta
Normal file
8
Assets/Scripts/ModelViewerBase/Pose/Timeline.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a69fe7c010475646b6b04eb27a854b1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
public interface IKeyframeSetter
|
||||
{
|
||||
public void SetKeyframe(int frameNum);
|
||||
public void EnableKeyframeSet();
|
||||
public void DisableKeyframeSet();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8fa2a5bc09d8ef04c8e7844a4c11ade4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Assets/Scripts/ModelViewerBase/Pose/Timeline/KeyframeData.cs
Normal file
26
Assets/Scripts/ModelViewerBase/Pose/Timeline/KeyframeData.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
[System.Serializable]
|
||||
public class KeyframeData
|
||||
{
|
||||
public SerializableTransform Root;
|
||||
|
||||
public KeyframeData() { }
|
||||
|
||||
public KeyframeData(ObjectContainer container)
|
||||
{
|
||||
this.Root = new SerializableTransform(container.transform);
|
||||
}
|
||||
|
||||
public virtual KeyframeData Clone()
|
||||
{
|
||||
var keyframe = new KeyframeData();
|
||||
keyframe.Root = new SerializableTransform(this.Root);
|
||||
return keyframe;
|
||||
}
|
||||
|
||||
public virtual KeyframeData Lerp(KeyframeData target, float amount)
|
||||
{
|
||||
var copy = this.Clone();
|
||||
copy.Root = copy.Root.LerpWith(target.Root, amount);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78f95c9a0a831be438b081224ae745eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class KeyframeDataCamera : KeyframeData
|
||||
{
|
||||
public SerializableTransform CamTransform;
|
||||
|
||||
public int CameraMode;
|
||||
public bool CameraLock;
|
||||
public float Fov = 45;
|
||||
public float CamDist = 5;
|
||||
public float CamHeight = 1;
|
||||
public float TargetHeigh = 1;
|
||||
public float CamAngle = 0;
|
||||
public float MovSpeed = 5;
|
||||
public float RotSpeed = 1;
|
||||
public float ZoomSpeed = 0.2f;
|
||||
|
||||
public KeyframeDataCamera() { }
|
||||
|
||||
public KeyframeDataCamera(CameraContainer camera)
|
||||
{
|
||||
Root = new SerializableTransform(camera.Camera.transform);
|
||||
CamTransform = new SerializableTransform(camera.Camera.Cam.transform);
|
||||
|
||||
var settings = camera.Settings;
|
||||
CameraMode = settings.CameraMode;
|
||||
CameraLock = settings.CameraLock;
|
||||
Fov = settings.Fov;
|
||||
CamDist = settings.CamDist;
|
||||
CamHeight = settings.CamHeight;
|
||||
TargetHeigh = settings.TargetHeight;
|
||||
CamAngle = settings.CamAngle;
|
||||
MovSpeed = settings.MovSpeed;
|
||||
RotSpeed = settings.RotSpeed;
|
||||
ZoomSpeed = settings.ZoomSpeed;
|
||||
}
|
||||
|
||||
public override KeyframeData Clone()
|
||||
{
|
||||
var keyframe = new KeyframeDataCamera();
|
||||
keyframe.Root = new SerializableTransform(this.Root);
|
||||
keyframe.CamTransform = new SerializableTransform(this.CamTransform);
|
||||
keyframe.CameraMode = this.CameraMode;
|
||||
keyframe.CameraLock = this.CameraLock;
|
||||
keyframe.Fov = this.Fov;
|
||||
keyframe.CamDist = this.CamDist;
|
||||
keyframe.CamHeight = this.CamHeight;
|
||||
keyframe.TargetHeigh = this.TargetHeigh;
|
||||
keyframe.CamAngle = this.CamAngle;
|
||||
keyframe.MovSpeed = this.MovSpeed;
|
||||
keyframe.RotSpeed = this.RotSpeed;
|
||||
keyframe.ZoomSpeed = this.ZoomSpeed;
|
||||
return keyframe;
|
||||
}
|
||||
|
||||
public override KeyframeData Lerp(KeyframeData target1, float amount)
|
||||
{
|
||||
var target = target1 as KeyframeDataCamera;
|
||||
var copy = this.Clone() as KeyframeDataCamera;
|
||||
copy.Root = copy.Root.LerpWith(target.Root, amount);
|
||||
copy.CamTransform = copy.CamTransform.LerpWith(target.CamTransform, amount);
|
||||
copy.Fov = Mathf.Lerp(copy.Fov, target.Fov, amount);
|
||||
copy.CamDist = Mathf.Lerp(copy.CamDist, target.CamDist, amount);
|
||||
copy.CamHeight = Mathf.Lerp(copy.CamHeight, target.CamHeight, amount);
|
||||
copy.TargetHeigh = Mathf.Lerp(copy.TargetHeigh, target.TargetHeigh, amount);
|
||||
copy.CamAngle = Mathf.Lerp(copy.CamAngle, target.CamAngle, amount);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6436dcc628970074cb9f996d0953e8fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
public class KeyframeToggleContext : IDisposable
|
||||
{
|
||||
private IKeyframeSetter _keyframmable;
|
||||
private bool _enableKeyframes;
|
||||
|
||||
public KeyframeToggleContext(IKeyframeSetter keyframmable, bool enableKeyframes = false)
|
||||
{
|
||||
_keyframmable = keyframmable;
|
||||
_enableKeyframes = enableKeyframes;
|
||||
Toggle(true);
|
||||
}
|
||||
|
||||
public void ForceSetKeyframe(int frameNum = -1)
|
||||
{
|
||||
Toggle(false);
|
||||
_keyframmable.SetKeyframe(frameNum);
|
||||
Toggle(true);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Toggle(false);
|
||||
}
|
||||
|
||||
private void Toggle(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
if (_enableKeyframes) _keyframmable.EnableKeyframeSet();
|
||||
else _keyframmable.DisableKeyframeSet();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_enableKeyframes) _keyframmable.DisableKeyframeSet();
|
||||
else _keyframmable.EnableKeyframeSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 943743df82cb7ce41a28df2e9cda34dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/ModelViewerBase/RuntimeGizmo.meta
Normal file
8
Assets/Scripts/ModelViewerBase/RuntimeGizmo.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87656b5a24d76394a814678c521b7193
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
using CommandUndoRedo;
|
||||
|
||||
public class CameraTransformCommand : ICommand
|
||||
{
|
||||
public CameraContainer Container;
|
||||
|
||||
public KeyframeDataCamera NewValues;
|
||||
public KeyframeDataCamera OldValues;
|
||||
|
||||
public int Frame;
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
TimelineController.SetCurrentFrame(Frame);
|
||||
Container.PastePose(NewValues);
|
||||
Container.SetKeyframe();
|
||||
}
|
||||
|
||||
public void UnExecute()
|
||||
{
|
||||
TimelineController.SetCurrentFrame(Frame);
|
||||
Container.PastePose(OldValues);
|
||||
Container.SetKeyframe();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad6653f31ee3e334da62554c392eee38
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class HandleUndoData : UndoData
|
||||
{
|
||||
public UIHandle Handle;
|
||||
public Transform NewPosition;
|
||||
public SerializableTransform OldPosition;
|
||||
|
||||
public HandleUndoData() { }
|
||||
|
||||
public HandleUndoData(UIHandle handle)
|
||||
{
|
||||
Handle = handle;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 157ab30982d081842bb68ee2cb4f8d7b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
32
Assets/Scripts/ModelViewerBase/SharedResources.cs
Normal file
32
Assets/Scripts/ModelViewerBase/SharedResources.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
|
||||
public partial class SharedResources : MonoBehaviour
|
||||
{
|
||||
public static SharedResources Instance;
|
||||
|
||||
public AnimatorOverrideController GenericAnimatorController ;
|
||||
public UITimelineObjectEntry TimelineObjectEntry ;
|
||||
public UISceneContainer UISceneContainer ;
|
||||
public UIDraggableProxy UIDraggableProxy ;
|
||||
public UIPoseContainer UIPoseContainer ;
|
||||
public UIPopupPastePanel PopupPastePanel ;
|
||||
public UISelectionEntry SelectionEntry ;
|
||||
public TimelineFrameContainer TimelineFrame ;
|
||||
public UIPopupMessage PopupMessage ;
|
||||
public PopupController HandlePopup ;
|
||||
public SliderPanel SliderPanel ;
|
||||
public SliderPanel TogglePanel ;
|
||||
public MorphPanel MorphPanel ;
|
||||
public GameObject ModelIcon ;
|
||||
public GameObject Handle ;
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
if(Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(this);
|
||||
return;
|
||||
}
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/SharedResources.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/SharedResources.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8af8c42fefb782c4ea8b0f63839931cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/ModelViewerBase/UI.meta
Normal file
8
Assets/Scripts/ModelViewerBase/UI.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94bd658007ce9f9498607709721de17f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
83
Assets/Scripts/ModelViewerBase/UI/ExtendedDropdown.cs
Normal file
83
Assets/Scripts/ModelViewerBase/UI/ExtendedDropdown.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class ExtendedDropdown : MonoBehaviour
|
||||
{
|
||||
public bool LoopAround;
|
||||
[SerializeField] private TMPro.TMP_Dropdown _dropdown;
|
||||
public UnityEvent<int> OnValueChangedEvent;
|
||||
public List<TMPro.TMP_Dropdown.OptionData> options => _dropdown.options;
|
||||
public KeyCode PreviousKey = KeyCode.None;
|
||||
public KeyCode NextKey = KeyCode.None;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if(Input.GetKeyDown(PreviousKey))
|
||||
{
|
||||
DropdownPrevious();
|
||||
}
|
||||
if (Input.GetKeyDown(NextKey))
|
||||
{
|
||||
DropdownNext();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnValueChanged(int index)
|
||||
{
|
||||
OnValueChangedEvent.Invoke(index);
|
||||
}
|
||||
|
||||
public void SetValueWithoutNotify(string value)
|
||||
{
|
||||
var option = options.FindIndex(v => v.text == value);
|
||||
SetValueWithoutNotify(option);
|
||||
}
|
||||
|
||||
public void SetValueWithoutNotify(int value)
|
||||
{
|
||||
_dropdown.SetValueWithoutNotify(value);
|
||||
}
|
||||
|
||||
public void DropdownPrevious()
|
||||
{
|
||||
if (LoopAround)
|
||||
{
|
||||
_dropdown.value = _dropdown.value - 1 < 0 ? _dropdown.options.Count - 1 : _dropdown.value - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dropdown.value = Mathf.Clamp(_dropdown.value - 1, 0, _dropdown.options.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void DropdownNext()
|
||||
{
|
||||
if (LoopAround)
|
||||
{
|
||||
_dropdown.value = _dropdown.value + 1 >= _dropdown.options.Count ? 0 : _dropdown.value + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dropdown.value = Mathf.Clamp(_dropdown.value + 1, 0, _dropdown.options.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetOptions(List<string> values, bool nullValue = false, bool sortValues = false)
|
||||
{
|
||||
var dd = _dropdown;
|
||||
dd.ClearOptions();
|
||||
if (nullValue)
|
||||
dd.AddOptions(new List<string>() { Strings.NoValueSelectedString });
|
||||
if (values != null)
|
||||
{
|
||||
if (sortValues)
|
||||
{
|
||||
values = new List<string>(values);
|
||||
values.Sort();
|
||||
}
|
||||
dd.AddOptions(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/ExtendedDropdown.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/ExtendedDropdown.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 588358108868b3e4a9c5d0771c66dbd3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
35
Assets/Scripts/ModelViewerBase/UI/FrameContent.cs
Normal file
35
Assets/Scripts/ModelViewerBase/UI/FrameContent.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
[System.Serializable]
|
||||
public class FrameContent
|
||||
{
|
||||
public int FrameNum;
|
||||
public KeyframeData ObjectData;
|
||||
#if UNITY_EDITOR
|
||||
//public KeyframeDataCharacter AsCharacter;
|
||||
//public KeyframeDataCamera AsCamera;
|
||||
//public KeyframeDataScene AsScene;
|
||||
#endif
|
||||
|
||||
public FrameContent() { }
|
||||
|
||||
public FrameContent(int frameNum)
|
||||
{
|
||||
FrameNum = frameNum;
|
||||
}
|
||||
|
||||
public FrameContent(FrameContent frame)
|
||||
{
|
||||
FrameNum = frame.FrameNum;
|
||||
ObjectData = frame.ObjectData.Clone();
|
||||
}
|
||||
|
||||
public FrameContent SetObjectData(KeyframeData data)
|
||||
{
|
||||
ObjectData = data;
|
||||
#if UNITY_EDITOR
|
||||
//AsCharacter = ObjectData as KeyframeDataCharacter;
|
||||
//AsCamera = ObjectData as KeyframeDataCamera;
|
||||
//AsScene = ObjectData as KeyframeDataScene;
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/FrameContent.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/FrameContent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3514ca7309b4404fa82480b7356b964
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
30
Assets/Scripts/ModelViewerBase/UI/HandleSettingsPanel.cs
Normal file
30
Assets/Scripts/ModelViewerBase/UI/HandleSettingsPanel.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using UnityEngine.UI;
|
||||
using static SerializableBone;
|
||||
|
||||
namespace KF3.UI.Panels
|
||||
{
|
||||
public class HandleSettingsPanel : UIPanels.UIToolbarPanel
|
||||
{
|
||||
public ScrollRect HandleVisibilityToggles;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
var handleManager = HandleManager.Instance;
|
||||
foreach (BoneTags en in Enum.GetValues(typeof(BoneTags)))
|
||||
{
|
||||
var handle = SliderPanel.CreateToggle(en.ToString(), handleManager.EnabledHandles.Contains(en), HandleVisibilityToggles.content, (value)=>
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
handleManager.EnabledHandles.Add(en);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleManager.EnabledHandles.Remove(en);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39645b413d3a924438246b4f9ffaadc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/ModelViewerBase/UI/Handles.meta
Normal file
8
Assets/Scripts/ModelViewerBase/UI/Handles.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b6140bc0ba26f246b92786a4448449d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
105
Assets/Scripts/ModelViewerBase/UI/Handles/HandleManager.cs
Normal file
105
Assets/Scripts/ModelViewerBase/UI/Handles/HandleManager.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using static SerializableBone;
|
||||
|
||||
public class HandleManager : MonoBehaviour
|
||||
{
|
||||
public static HandleManager Instance;
|
||||
public GameObject HandlesPanel;
|
||||
public GameObject Pfb_HandleDisplay;
|
||||
public UIPopupPanel Pfb_Popup;
|
||||
public Button Pfb_PopupButton;
|
||||
|
||||
public Material LineRendererMaterial;
|
||||
|
||||
public List<BoneTags> EnabledHandles = new List<BoneTags>() { BoneTags.Humanoid };
|
||||
public bool EnabledLines = true;
|
||||
|
||||
public static bool InteractionInProgress;
|
||||
|
||||
private List<UIHandle> AllHandles = new List<UIHandle>();
|
||||
|
||||
public static System.Action<HandleUndoData> RegisterRuntimeGizmoUndoAction;
|
||||
public static System.Action<List<HandleUndoData>> RegisterRuntimeGizmoUndoActions;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var camera = Camera.main;
|
||||
//var poseModeOn = UmaViewerUI.Instance.PoseManager.PoseModeOn;
|
||||
|
||||
foreach (var handle in AllHandles)
|
||||
{
|
||||
//handle.ForceDisplayOff(!poseModeOn);
|
||||
handle.UpdateManual(camera, EnabledLines);
|
||||
|
||||
if (handle.Popup.gameObject.activeInHierarchy)
|
||||
{
|
||||
handle.Popup.UpdateManual(camera);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterHandle(UIHandle handle)
|
||||
{
|
||||
var hm = HandleManager.Instance;
|
||||
|
||||
if (hm.AllHandles.Contains(handle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hm.AllHandles.Add(handle);
|
||||
}
|
||||
|
||||
public static void UnregisterHandle(UIHandle handle)
|
||||
{
|
||||
var hm = HandleManager.Instance;
|
||||
|
||||
if (!hm.AllHandles.Contains(handle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hm.AllHandles.Remove(handle);
|
||||
}
|
||||
|
||||
public static void CloseAllPopups()
|
||||
{
|
||||
var hm = HandleManager.Instance;
|
||||
|
||||
foreach(var handle in hm.AllHandles)
|
||||
{
|
||||
if (handle.Popup.gameObject.activeInHierarchy)
|
||||
{
|
||||
handle.TogglePopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Used on UI buttons </summary>
|
||||
public void ToggleBonesVisible(string tag)
|
||||
{
|
||||
var enumTag = (BoneTags)System.Enum.Parse(typeof(BoneTags), tag);
|
||||
if (EnabledHandles.Contains(enumTag))
|
||||
{
|
||||
EnabledHandles.Remove(enumTag);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnabledHandles.Add(enumTag);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Used on UI buttons </summary>
|
||||
public void ToggleLinesVisible(bool value)
|
||||
{
|
||||
EnabledLines = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 491e0b38519c9e94facd88535f6f3458
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
277
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandle.cs
Normal file
277
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandle.cs
Normal file
@@ -0,0 +1,277 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class UIHandle : MonoBehaviour
|
||||
{
|
||||
/// <summary> Object that "owns" the handle </summary>
|
||||
public ObjectContainer Owner;
|
||||
|
||||
/// <summary> Object that the handle refers to. Cast in inheriting class </summary>
|
||||
public Transform Target;
|
||||
|
||||
/// <summary> Display object on the UI </summary>
|
||||
public GameObject Handle;
|
||||
|
||||
/// <summary> Collider for selecting the handle on UI </summary>
|
||||
public SphereCollider Collider;
|
||||
|
||||
/// <summary> Object that appears when right-clicking the handle </summary>
|
||||
public UIPopupPanel Popup;
|
||||
|
||||
public LineRenderer LineRenderer;
|
||||
|
||||
protected SerializableTransform _defaultTransform;
|
||||
protected float _baseScale = 1;
|
||||
protected bool _forceDisplayOff = false;
|
||||
protected ModelViewerMain Main => ModelViewerMain.GetInstance();
|
||||
|
||||
public static T CreateAsChild<T>(Transform parent) where T : UIHandle
|
||||
{
|
||||
var handle = new GameObject(parent.name + "_Handle").AddComponent<T>();
|
||||
handle.transform.parent = parent.transform;
|
||||
handle.transform.localPosition = Vector3.zero;
|
||||
handle.transform.localScale = Vector3.one;
|
||||
handle.transform.rotation = parent.rotation;
|
||||
handle.Target = parent.transform;
|
||||
return handle;
|
||||
}
|
||||
|
||||
public virtual UIHandle Init(ObjectContainer owner, Transform target)
|
||||
{
|
||||
Target = target;
|
||||
return Init(owner);
|
||||
}
|
||||
|
||||
public virtual UIHandle Init(ObjectContainer owner)
|
||||
{
|
||||
HandleManager.RegisterHandle(this);
|
||||
|
||||
gameObject.layer = LayerMask.NameToLayer("UIHandle");
|
||||
Target = Target == null? owner.transform : Target;
|
||||
Owner = owner;
|
||||
Owner.Handles.Add(this);
|
||||
|
||||
Handle = Instantiate(HandleManager.Instance.Pfb_HandleDisplay, HandleManager.Instance.HandlesPanel.transform);
|
||||
Handle.transform.SetAsFirstSibling();
|
||||
|
||||
Popup = Instantiate(HandleManager.Instance.Pfb_Popup, HandleManager.Instance.HandlesPanel.transform).Init(this);
|
||||
Popup.gameObject.SetActive(false);
|
||||
|
||||
_defaultTransform = new SerializableTransform(Target, Space.Self);
|
||||
|
||||
var collider = gameObject.AddComponent<SphereCollider>();
|
||||
collider.center = Vector3.zero;
|
||||
|
||||
Collider = collider;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
Gizmos.DrawWireSphere(transform.position + Collider.center, transform.lossyScale.x * Collider.radius);
|
||||
}
|
||||
|
||||
public virtual void UpdateManual(Camera camera, bool linesEnabled)
|
||||
{
|
||||
if (Handle != null && camera != null && transform != null)
|
||||
{
|
||||
Handle.transform.localScale = Vector3.one * Mathf.Clamp(_baseScale / Vector3.Distance(camera.transform.position, transform.position), 0.1f, 1);
|
||||
|
||||
if (Collider.transform.localScale.x != 0 && transform.lossyScale.x != 0)
|
||||
{
|
||||
Collider.radius = 35 /* magic number */ * (1 / transform.lossyScale.x) * GetRadiusOnScreen(camera, Collider.transform.position, Handle.transform.localScale.x);
|
||||
Collider.radius = Mathf.Clamp(Collider.radius, 0.001f, 2);
|
||||
}
|
||||
|
||||
Handle.transform.position = camera.WorldToScreenPoint(Collider.transform.TransformPoint(Collider.center));
|
||||
|
||||
if (ShouldBeHidden())
|
||||
{
|
||||
if (Handle.activeSelf == true)
|
||||
{
|
||||
ToggleActive(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isOnScreen =
|
||||
!(Handle.transform.position.x < 0 || Handle.transform.position.y < 0 || Handle.transform.position.z < 0
|
||||
|| Handle.transform.position.x > Screen.width || Handle.transform.position.y > Screen.height);
|
||||
|
||||
if (Handle.activeSelf != isOnScreen)
|
||||
{
|
||||
ToggleActive(!Handle.activeSelf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Handle.activeSelf && LineRenderer != null)
|
||||
{
|
||||
if (LineRenderer.enabled != linesEnabled)
|
||||
{
|
||||
LineRenderer.enabled = linesEnabled;
|
||||
}
|
||||
if (linesEnabled)
|
||||
{
|
||||
LineRenderer.SetPositions(new Vector3[] { (Target).position, (Target).parent.position });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool ShouldBeHidden()
|
||||
{
|
||||
return _forceDisplayOff;
|
||||
}
|
||||
|
||||
/// <summary> For future, `offset` param will allow popups to be spaced out when selecting more than 1 handle at a time. </summary>
|
||||
public void TogglePopup(int offset = 0)
|
||||
{
|
||||
Popup.Offset = offset * Popup.GetComponent<RectTransform>().sizeDelta.x;
|
||||
ModelViewerInterface.ToggleVisible(Popup.gameObject);
|
||||
}
|
||||
|
||||
public UIHandle SetDefaults(Vector3 localPos, Vector3 localRot, Vector3 localScale)
|
||||
{
|
||||
_defaultTransform.Position = localPos;
|
||||
_defaultTransform.Rotation = localRot;
|
||||
_defaultTransform.Scale = localScale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UIHandle SetColor(Color color)
|
||||
{
|
||||
color.a = Handle.GetComponent<Image>().color.a;
|
||||
Handle.GetComponent<Image>().color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UIHandle SetScale(float scale)
|
||||
{
|
||||
this._baseScale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UIHandle SetName(string name)
|
||||
{
|
||||
Handle.gameObject.name = name;
|
||||
Popup.NameLabel.text = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UIHandle SetOffset(Vector3 offset)
|
||||
{
|
||||
Collider.center = offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UIHandle SetContainer(ObjectContainer container)
|
||||
{
|
||||
Owner = container;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float GetRadiusOnScreen(Camera cam, Vector3 position, float screenSize)
|
||||
{
|
||||
Vector3 a = cam.WorldToScreenPoint(position);
|
||||
Vector3 b = new Vector3(a.x, a.y + screenSize, a.z);
|
||||
|
||||
Vector3 aa = cam.ScreenToWorldPoint(a);
|
||||
Vector3 bb = cam.ScreenToWorldPoint(b);
|
||||
|
||||
return (aa - bb).magnitude;
|
||||
}
|
||||
|
||||
public UIHandle WithLineRenderer()
|
||||
{
|
||||
LineRenderer = Handle.gameObject.AddComponent<LineRenderer>();
|
||||
LineRenderer.positionCount = 2;
|
||||
LineRenderer.startWidth = LineRenderer.endWidth = 0.005f;
|
||||
LineRenderer.material = HandleManager.Instance.LineRendererMaterial;
|
||||
LineRenderer.startColor = LineRenderer.endColor = Handle.GetComponent<Image>().color;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (Popup)
|
||||
{
|
||||
Destroy(Popup.gameObject);
|
||||
}
|
||||
if (Handle)
|
||||
{
|
||||
Destroy(Handle);
|
||||
}
|
||||
HandleManager.UnregisterHandle(this);
|
||||
}
|
||||
|
||||
private void TransformReset(PoseLoadOptions options = null)
|
||||
{
|
||||
if(options == null)
|
||||
{
|
||||
options = PoseLoadOptions.All();
|
||||
}
|
||||
|
||||
_defaultTransform.ApplyTo(Target, options);
|
||||
}
|
||||
|
||||
public void TransformResetAll()
|
||||
{
|
||||
var HandleUndoData = new HandleUndoData(this);
|
||||
|
||||
HandleUndoData.OldPosition = new SerializableTransform(Target, Space.World);
|
||||
TransformReset();
|
||||
HandleUndoData.NewPosition = Target;
|
||||
|
||||
HandleManager.RegisterRuntimeGizmoUndoAction.Invoke(HandleUndoData);
|
||||
Owner.SetKeyframe();
|
||||
}
|
||||
|
||||
public void TransformResetPosition()
|
||||
{
|
||||
var HandleUndoData = new HandleUndoData(this);
|
||||
|
||||
HandleUndoData.OldPosition = new SerializableTransform(Target, Space.World);
|
||||
TransformReset(new PoseLoadOptions(false) { Position = true });
|
||||
HandleUndoData.NewPosition = Target;
|
||||
|
||||
HandleManager.RegisterRuntimeGizmoUndoAction.Invoke(HandleUndoData);
|
||||
Owner.SetKeyframe();
|
||||
}
|
||||
|
||||
public void TransformResetRotation()
|
||||
{
|
||||
var HandleUndoData = new HandleUndoData(this);
|
||||
|
||||
HandleUndoData.OldPosition = new SerializableTransform(Target, Space.World);
|
||||
TransformReset(new PoseLoadOptions(false) { Rotation = true });
|
||||
HandleUndoData.NewPosition = Target;
|
||||
|
||||
HandleManager.RegisterRuntimeGizmoUndoAction.Invoke(HandleUndoData);
|
||||
Owner.SetKeyframe();
|
||||
}
|
||||
|
||||
public void TransformResetScale()
|
||||
{
|
||||
var HandleUndoData = new HandleUndoData(this);
|
||||
|
||||
HandleUndoData.OldPosition = new SerializableTransform(Target, Space.World);
|
||||
TransformReset(new PoseLoadOptions(false) { Scale = true });
|
||||
HandleUndoData.NewPosition = Target;
|
||||
|
||||
HandleManager.RegisterRuntimeGizmoUndoAction.Invoke(HandleUndoData);
|
||||
Owner.SetKeyframe();
|
||||
}
|
||||
|
||||
public void ToggleActive(bool value)
|
||||
{
|
||||
Handle.SetActive(value);
|
||||
Collider.enabled = value;
|
||||
Popup.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void ForceDisplayOff(bool value)
|
||||
{
|
||||
_forceDisplayOff = value;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandle.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandle.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f855de4e8b12374a8c7ef07e3ce5142
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
51
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleBone.cs
Normal file
51
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleBone.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static SerializableBone;
|
||||
|
||||
public class UIHandleBone : UIHandle
|
||||
{
|
||||
public Transform Bone => Target;
|
||||
|
||||
public List<BoneTags> Tags;
|
||||
|
||||
public static UIHandleBone CreateAsChild(ObjectContainer owner, Transform parent, List<BoneTags> boneTags)
|
||||
{
|
||||
var handle = CreateAsChild<UIHandleBone>(parent);
|
||||
handle.Init(owner, boneTags);
|
||||
return handle;
|
||||
}
|
||||
|
||||
public override UIHandle Init(ObjectContainer owner)
|
||||
{
|
||||
throw new System.Exception("Use ObjectContainer, List<BoneTags> constructor!");
|
||||
}
|
||||
|
||||
public UIHandleBone Init(ObjectContainer owner, List<BoneTags> boneTags)
|
||||
{
|
||||
if (boneTags == null || !boneTags.Any())
|
||||
{
|
||||
boneTags = new List<BoneTags>() { BoneTags.Untagged };
|
||||
}
|
||||
|
||||
Tags = boneTags.ToList();
|
||||
base.Init(owner);
|
||||
|
||||
SetScale(0.5f);
|
||||
if (Tags.Contains(BoneTags.Left)) SetColor(Color.green);
|
||||
else if (Tags.Contains(BoneTags.Right)) SetColor(Color.blue);
|
||||
else SetColor(Color.white);
|
||||
|
||||
Popup.AddButton("Reset All", TransformResetAll);
|
||||
Popup.AddButton("Reset Position", TransformResetPosition);
|
||||
Popup.AddButton("Reset Rotation", TransformResetRotation);
|
||||
Popup.AddButton("Reset Scale", TransformResetScale);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected override bool ShouldBeHidden()
|
||||
{
|
||||
return _forceDisplayOff || !HandleManager.Instance.EnabledHandles.Intersect(Tags).Any();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ebd7e66c67c47f4fa215b1e3ba00091
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
50
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleIK.cs
Normal file
50
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleIK.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public class UIHandleIK : UIHandle
|
||||
{
|
||||
public List<UIHandle> HiddenHandles = new List<UIHandle>();
|
||||
|
||||
public static Transform CreateTransform(string handleName, Transform parent, Vector3 position)
|
||||
{
|
||||
var go = new GameObject(handleName);
|
||||
go.transform.SetParent(parent);
|
||||
go.transform.position = position;
|
||||
return go.transform;
|
||||
}
|
||||
|
||||
public static Transform CreateTransform(string handleName, Transform parent, Vector3 position, Vector3 eulerAngles)
|
||||
{
|
||||
var go = CreateTransform(handleName, parent, position);
|
||||
go.eulerAngles = eulerAngles;
|
||||
return go;
|
||||
}
|
||||
|
||||
public static UIHandleIK CreateAsChild(ObjectContainer owner, Transform parent, Color color, string name, float scale)
|
||||
{
|
||||
var handle = CreateAsChild<UIHandleIK>(parent);
|
||||
handle.Init(owner).SetName(name).SetColor(color).SetScale(scale);
|
||||
return handle;
|
||||
}
|
||||
|
||||
public override UIHandle Init(ObjectContainer owner)
|
||||
{
|
||||
base.Init(owner);
|
||||
Popup.AddButton("Reset Position", () => TransformResetPosition());
|
||||
Popup.AddButton("Reset Rotation", () => TransformResetRotation());
|
||||
Popup.AddButton("Toggle Helper Lines", () =>
|
||||
{
|
||||
foreach (var c in owner.GetComponents<InverseKinematics>())
|
||||
{
|
||||
c.forceLinesInvisible = !c.forceLinesInvisible;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
protected override bool ShouldBeHidden()
|
||||
{
|
||||
return _forceDisplayOff || !HandleManager.Instance.EnabledHandles.Contains(SerializableBone.BoneTags.IK);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleIK.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleIK.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03de88101ab64404e9d237323c9663b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
25
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleMain.cs
Normal file
25
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleMain.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class UIHandleMain : UIHandle
|
||||
{
|
||||
public static UIHandleMain CreateAsChild(ObjectContainer owner)
|
||||
{
|
||||
var handle = CreateAsChild<UIHandleMain>(owner.transform);
|
||||
handle.Init(owner).SetColor(Color.yellow).SetScale(1.5f);
|
||||
return handle;
|
||||
}
|
||||
|
||||
public override UIHandle Init(ObjectContainer owner)
|
||||
{
|
||||
base.Init(owner);
|
||||
|
||||
Popup.AddButton("Reset All", TransformResetAll);
|
||||
Popup.AddButton("Reset Position", TransformResetPosition);
|
||||
Popup.AddButton("Reset Rotation", TransformResetRotation);
|
||||
Popup.AddButton("Reset Scale", TransformResetScale);
|
||||
Popup.AddButton("Delete", () => Destroy(Owner));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: add71905575d4ec44b658c58aa433e1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using static SerializableBone;
|
||||
|
||||
public class UIHandlePhysicsBone : UIHandleBone
|
||||
{
|
||||
new public static UIHandlePhysicsBone CreateAsChild(ObjectContainer owner, Transform parent, List<BoneTags> boneTags)
|
||||
{
|
||||
var handle = CreateAsChild<UIHandlePhysicsBone>(parent);
|
||||
handle.Init(owner, boneTags).SetScale(0.5f);
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43d8d17f43ab7d94ca0a609656dfee90
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
23
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleProp.cs
Normal file
23
Assets/Scripts/ModelViewerBase/UI/Handles/UIHandleProp.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class UIHandleProp : UIHandle
|
||||
{
|
||||
public static UIHandleProp CreateAsChild(ObjectContainer owner, Transform parent)
|
||||
{
|
||||
var handle = CreateAsChild<UIHandleProp>(parent);
|
||||
handle.Init(owner).SetScale(0.65f);
|
||||
return handle;
|
||||
}
|
||||
|
||||
public override UIHandle Init(ObjectContainer owner)
|
||||
{
|
||||
base.Init(owner);
|
||||
|
||||
Popup.AddButton("Reset All", TransformResetAll);
|
||||
Popup.AddButton("Reset Position", TransformResetPosition);
|
||||
Popup.AddButton("Reset Rotation", TransformResetRotation);
|
||||
Popup.AddButton("Reset Scale", TransformResetScale);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0fa65a26810d854ebc243e69ff044f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
57
Assets/Scripts/ModelViewerBase/UI/Handles/UIPopupPanel.cs
Normal file
57
Assets/Scripts/ModelViewerBase/UI/Handles/UIPopupPanel.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class UIPopupPanel : MonoBehaviour
|
||||
{
|
||||
public UIHandle Owner;
|
||||
public float Offset;
|
||||
public Transform Content;
|
||||
public TMPro.TMP_Text NameLabel;
|
||||
public Dictionary<GameObject, System.Func<bool>> ConditionalButtons = new Dictionary<GameObject, System.Func<bool>>();
|
||||
|
||||
private int _side;
|
||||
|
||||
public UIPopupPanel Init(UIHandle owner)
|
||||
{
|
||||
Owner = owner;
|
||||
transform.SetAsFirstSibling();
|
||||
NameLabel.text = owner.Target.name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void UpdateManual(Camera camera)
|
||||
{
|
||||
if (camera.WorldToScreenPoint(Owner.transform.position).x < camera.pixelWidth / 2 - _side)
|
||||
{
|
||||
_side = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_side = 1;
|
||||
}
|
||||
|
||||
float pos = _side * camera.pixelWidth / 20 + Offset;
|
||||
transform.position = camera.WorldToScreenPoint(Owner.transform.position) + pos * Vector3.right;
|
||||
|
||||
foreach (var kv in ConditionalButtons)
|
||||
{
|
||||
kv.Key.gameObject.SetActive(kv.Value.Invoke());
|
||||
}
|
||||
}
|
||||
|
||||
public void AddButton(string name, System.Action callback)
|
||||
{
|
||||
Button b = Instantiate(HandleManager.Instance.Pfb_PopupButton, Content).GetComponent<Button>();
|
||||
b.onClick.AddListener(()=>callback.Invoke());
|
||||
b.GetComponentInChildren<TMPro.TMP_Text>().text = name;
|
||||
}
|
||||
|
||||
public void AddConditionalButton(string name, System.Func<bool> condition, System.Action callback)
|
||||
{
|
||||
Button b = Instantiate(HandleManager.Instance.Pfb_PopupButton, Content).GetComponent<Button>();
|
||||
b.onClick.AddListener(() => callback.Invoke());
|
||||
b.GetComponentInChildren<TMPro.TMP_Text>().text = name;
|
||||
ConditionalButtons.Add(b.gameObject, condition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59083bc243f250f4a8918f69361d09e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
52
Assets/Scripts/ModelViewerBase/UI/MorphHelper.cs
Normal file
52
Assets/Scripts/ModelViewerBase/UI/MorphHelper.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[Serializable]
|
||||
public class MorphHelper
|
||||
{
|
||||
public string Name;
|
||||
[DefaultValue("")]
|
||||
public string ParentName;
|
||||
public float Strength;
|
||||
public bool Value;
|
||||
[NonSerialized]
|
||||
public SkinnedMeshRenderer Renderer;
|
||||
[NonSerialized]
|
||||
public Slider Slider;
|
||||
|
||||
public MorphHelper() { }
|
||||
|
||||
public MorphHelper(SkinnedMeshRenderer parent, string name, Slider slider = null)
|
||||
{
|
||||
this.ParentName = parent.name;
|
||||
this.Name = name;
|
||||
this.Renderer = parent;
|
||||
this.Slider = slider;
|
||||
}
|
||||
|
||||
/// <summary> Used for serialization! </summary>
|
||||
public MorphHelper(string parent, string name, float strength, bool value, Slider slider = null)
|
||||
{
|
||||
this.ParentName = parent;
|
||||
this.Name = name;
|
||||
this.Strength = strength;
|
||||
this.Value = value;
|
||||
this.Slider = slider;
|
||||
}
|
||||
|
||||
public void SetSlider(Slider slider)
|
||||
{
|
||||
this.Slider = slider;
|
||||
}
|
||||
|
||||
public void UpdateMorph(float value)
|
||||
{
|
||||
var id = Renderer.sharedMesh.GetBlendShapeIndex(Name);
|
||||
Renderer.SetBlendShapeWeight(id, value);
|
||||
Strength = value;
|
||||
if (Slider)
|
||||
Slider.SetValueWithoutNotify(value);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/MorphHelper.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/MorphHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c8f58133046c8b44bee5d32b4bc2cee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
32
Assets/Scripts/ModelViewerBase/UI/MorphPanel.cs
Normal file
32
Assets/Scripts/ModelViewerBase/UI/MorphPanel.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class MorphPanel : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private MorphPanelCategory _morphPanelCategoryPfb;
|
||||
[SerializeField] private Transform _categoryPanels;
|
||||
public Dictionary<string, MorphPanelCategory> Categories = new Dictionary<string, MorphPanelCategory>();
|
||||
|
||||
public static MorphPanel Create(List<string> categories)
|
||||
{
|
||||
var panel = Instantiate(SharedResources.Instance.MorphPanel, ModelViewerInterface.GetInstance().DynamicPanels.transform);
|
||||
panel.Init(categories);
|
||||
return panel;
|
||||
}
|
||||
|
||||
public void Init(List<string> categories)
|
||||
{
|
||||
Categories.Clear();
|
||||
foreach (var category in categories)
|
||||
{
|
||||
var categoryPanel = Instantiate(_morphPanelCategoryPfb, _categoryPanels);
|
||||
categoryPanel.Label.text = category;
|
||||
Categories[category] = categoryPanel;
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateMorph(string category, ObjectContainer container, SkinnedMeshRenderer meshRenderer, int index, string displayName)
|
||||
{
|
||||
SliderPanel.CreateMorph(container, meshRenderer, index, displayName, this.Categories[category].Content);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/MorphPanel.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/MorphPanel.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a16bc42a3ca264e4b8ad40eb7aa2c6e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Scripts/ModelViewerBase/UI/MorphPanelCategory.cs
Normal file
9
Assets/Scripts/ModelViewerBase/UI/MorphPanelCategory.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class MorphPanelCategory : MonoBehaviour
|
||||
{
|
||||
public TMPro.TMP_Text Label;
|
||||
public Transform Content => _scrollRect.content;
|
||||
[SerializeField] ScrollRect _scrollRect;
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/MorphPanelCategory.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/MorphPanelCategory.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 983bac4a8a262aa4eada7f5da7144d26
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
60
Assets/Scripts/ModelViewerBase/UI/PopupController.cs
Normal file
60
Assets/Scripts/ModelViewerBase/UI/PopupController.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class PopupController : MonoBehaviour
|
||||
{
|
||||
public Transform PopupPanel;
|
||||
public float offset;
|
||||
public int side;
|
||||
public UIHandle Owner;
|
||||
GameObject ButtonPrefab;
|
||||
public Dictionary<GameObject, System.Func<bool>> ConditionalButtons = new Dictionary<GameObject, System.Func<bool>>();
|
||||
|
||||
public void AddButton(string name, System.Action callback)
|
||||
{
|
||||
Button b = Instantiate(ButtonPrefab, PopupPanel).GetComponent<Button>();
|
||||
b.onClick.AddListener(()=>callback.Invoke());
|
||||
b.GetComponentInChildren<Text>().text = name;
|
||||
}
|
||||
|
||||
public void AddConditionalButton(string name, System.Func<bool> condition, System.Action callback)
|
||||
{
|
||||
Button b = Instantiate(ButtonPrefab, PopupPanel).GetComponent<Button>();
|
||||
b.onClick.AddListener(() => callback.Invoke());
|
||||
b.GetComponentInChildren<Text>().text = name;
|
||||
ConditionalButtons.Add(b.gameObject, condition);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
float pos;
|
||||
if(Camera.main.WorldToScreenPoint(Owner.transform.position).x < Camera.main.pixelWidth / 2 - side)
|
||||
{
|
||||
side = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
side = 1;
|
||||
}
|
||||
pos = side * Camera.main.pixelWidth / 20 + offset;
|
||||
transform.position = Camera.main.WorldToScreenPoint(Owner.transform.position) + pos * Vector3.right;
|
||||
|
||||
foreach(var kv in ConditionalButtons)
|
||||
{
|
||||
kv.Key.gameObject.SetActive(kv.Value.Invoke());
|
||||
}
|
||||
}
|
||||
|
||||
public PopupController Init(UIHandle owner)
|
||||
{
|
||||
Owner = owner;
|
||||
transform.SetAsFirstSibling();
|
||||
GetComponentInChildren<Text>().text = owner.name;
|
||||
PopupPanel = transform.Find("PopupPanel");
|
||||
ButtonPrefab = Resources.Load(Strings.PopupButtonPrefab) as GameObject;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/PopupController.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/PopupController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c34b8ed085cbb684f9f9646f6c1175d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
38
Assets/Scripts/ModelViewerBase/UI/SliderCallbackExtension.cs
Normal file
38
Assets/Scripts/ModelViewerBase/UI/SliderCallbackExtension.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class SliderCallbackExtension : MonoBehaviour, IPointerClickHandler, IPointerUpHandler
|
||||
{
|
||||
private Slider _slider;
|
||||
public UnityEvent RightClickAction = new UnityEvent();
|
||||
public UnityEvent<float> PointerUpAction = new UnityEvent<float>();
|
||||
public UnityEvent<float> ValueChangedAction = new UnityEvent<float>();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_slider = GetComponent<Slider>();
|
||||
}
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button == PointerEventData.InputButton.Right)
|
||||
{
|
||||
RightClickAction?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button == PointerEventData.InputButton.Left)
|
||||
{
|
||||
PointerUpAction?.Invoke(_slider.value);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnValueChanged(float value)
|
||||
{
|
||||
ValueChangedAction.Invoke(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 553b93692909e854c8f78f6457a4f46e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
21
Assets/Scripts/ModelViewerBase/UI/SliderDisplay.cs
Normal file
21
Assets/Scripts/ModelViewerBase/UI/SliderDisplay.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class SliderDisplay : MonoBehaviour
|
||||
{
|
||||
public TMPro.TMP_Text Text;
|
||||
|
||||
public void UpdateDisplay(float value)
|
||||
{
|
||||
if (Text == null) //Legacy, some UI needs to be updated
|
||||
{
|
||||
this.GetComponent<Text>().text = value.ToString("F2");
|
||||
}
|
||||
else
|
||||
{
|
||||
Text.text = value.ToString("F2");
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/SliderDisplay.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/SliderDisplay.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da09db22068c39445a2454d09ac5b09c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
103
Assets/Scripts/ModelViewerBase/UI/SliderPanel.cs
Normal file
103
Assets/Scripts/ModelViewerBase/UI/SliderPanel.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class SliderPanel : MonoBehaviour
|
||||
{
|
||||
public static SliderPanel Prefab;
|
||||
|
||||
public Slider Slider;
|
||||
//public UICallbacks ToggleCallbacks;
|
||||
public TMPro.TMP_Text Text;
|
||||
public Toggle Toggle;
|
||||
public float DefaultValue;
|
||||
public float value {
|
||||
get { return Slider.value; }
|
||||
set { Slider.value = value; }
|
||||
}
|
||||
public float maxValue
|
||||
{
|
||||
get { return Slider.maxValue; }
|
||||
set { Slider.maxValue = value; }
|
||||
}
|
||||
public float minValue
|
||||
{
|
||||
get { return Slider.minValue; }
|
||||
set { Slider.minValue = value; }
|
||||
}
|
||||
[Header("private")]
|
||||
[SerializeField] private SliderDisplay _display;
|
||||
[SerializeField] private SliderCallbackExtension _sliderCallbacks;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_display.UpdateDisplay(Slider.value);
|
||||
}
|
||||
|
||||
public static SliderPanel CreateMorph(ObjectContainer container, SkinnedMeshRenderer meshRenderer, int index, string displayName, Transform parent)
|
||||
{
|
||||
SliderPanel panel = Instantiate(SharedResources.Instance.SliderPanel, parent);
|
||||
|
||||
var helper = new MorphHelper(meshRenderer, meshRenderer.sharedMesh.GetBlendShapeName(index), panel.Slider);
|
||||
if (container.Morphs.ContainsKey(meshRenderer))
|
||||
container.Morphs[meshRenderer].Add(helper);
|
||||
else
|
||||
container.Morphs.Add(meshRenderer, new List<MorphHelper>() { helper });
|
||||
|
||||
panel.Text.text = displayName;
|
||||
panel.Slider.value = meshRenderer.GetBlendShapeWeight(index);
|
||||
panel.SetOnValueChanged((value) => {helper.UpdateMorph(value);});
|
||||
panel.SetOnRelease((value) => { container.SetKeyframe(); });
|
||||
panel.SetOnRightClick(null);
|
||||
return panel;
|
||||
}
|
||||
|
||||
public static SliderPanel CreateToggle(string label, bool isOn, Transform parent, UnityAction<bool> callback)
|
||||
{
|
||||
SliderPanel panel = Instantiate(SharedResources.Instance.TogglePanel, parent);
|
||||
panel.Slider.gameObject.SetActive(false);
|
||||
panel.Toggle.gameObject.SetActive(true);
|
||||
panel.Toggle.SetIsOnWithoutNotify(isOn);
|
||||
panel.Text.text = label;
|
||||
panel.Toggle.onValueChanged.AddListener(callback);
|
||||
return panel;
|
||||
}
|
||||
|
||||
public SliderPanel SetOnValueChanged(UnityAction<float> action)
|
||||
{
|
||||
_sliderCallbacks.ValueChangedAction.RemoveAllListeners();
|
||||
if (action != null)
|
||||
{
|
||||
_sliderCallbacks.ValueChangedAction.AddListener(action);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SliderPanel SetOnRelease(UnityAction<float> action)
|
||||
{
|
||||
_sliderCallbacks.PointerUpAction.RemoveAllListeners();
|
||||
if (action != null)
|
||||
{
|
||||
_sliderCallbacks.PointerUpAction.AddListener(action);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SliderPanel SetOnRightClick(UnityAction action)
|
||||
{
|
||||
_sliderCallbacks.RightClickAction.RemoveAllListeners();
|
||||
_sliderCallbacks.RightClickAction.AddListener(ResetSlider);
|
||||
if(action != null)
|
||||
{
|
||||
_sliderCallbacks.RightClickAction.AddListener(action);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void ResetSlider()
|
||||
{
|
||||
Slider.value = DefaultValue;
|
||||
_sliderCallbacks.PointerUpAction.Invoke(DefaultValue);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/SliderPanel.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/SliderPanel.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6c796de2dad3dd42a843945e951de9b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
320
Assets/Scripts/ModelViewerBase/UI/TimelineController.cs
Normal file
320
Assets/Scripts/ModelViewerBase/UI/TimelineController.cs
Normal file
@@ -0,0 +1,320 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
public class TimelineController : MonoBehaviour
|
||||
{
|
||||
[System.Serializable]
|
||||
public class CopyBufferData
|
||||
{
|
||||
public ObjectContainer TrackedObject;
|
||||
public FrameContent Content;
|
||||
}
|
||||
|
||||
public static TimelineController Instance;
|
||||
|
||||
public TMPro.TMP_InputField FrameCountInput;
|
||||
public TMPro.TMP_Text SelectedObjectLabel;
|
||||
public TMPro.TMP_InputField
|
||||
InputFrameRate,
|
||||
InputFrameDelay;
|
||||
|
||||
public int FrameCount;
|
||||
public int CurrentFrame;
|
||||
public ScrollRect Timeline;
|
||||
public ScrollRect ObjectsList;
|
||||
public Slider TimelineSlider;
|
||||
public CopyBufferData CopyBuffer = null;
|
||||
|
||||
public List<TimelineFrameContainer> Frames;
|
||||
|
||||
public bool Play;
|
||||
public float FrameDelayMS = 33;
|
||||
public float FrameRate = 30;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
IEnumerator Start()
|
||||
{
|
||||
while(ModelViewerMain.GetInstance() == null)
|
||||
{
|
||||
yield return 0;
|
||||
}
|
||||
|
||||
SetFrameRate("30");
|
||||
FrameCount = (int)float.Parse(FrameCountInput.text, CultureInfo.InvariantCulture);
|
||||
FillTimeline(FrameCount);
|
||||
UpdateTimeline();
|
||||
|
||||
StartCoroutine(UpdateLoop());
|
||||
}
|
||||
|
||||
IEnumerator UpdateLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (Play)
|
||||
{
|
||||
ChangeCurrentFrame(1, false);
|
||||
}
|
||||
yield return new WaitForSeconds(FrameDelayMS/1000);
|
||||
}
|
||||
}
|
||||
|
||||
public void TogglePlay()
|
||||
{
|
||||
Play = !Play;
|
||||
}
|
||||
|
||||
public void ChangeCurrentFrame(int frameChange)
|
||||
{
|
||||
TimelineController.ChangeCurrentFrame(frameChange, true);
|
||||
}
|
||||
|
||||
public static void ChangeCurrentFrame(int frameChange, bool stopPlayback)
|
||||
{
|
||||
int frame = Instance.CurrentFrame + frameChange;
|
||||
if (frame < 0)
|
||||
frame = Instance.FrameCount - 1;
|
||||
if (frame >= Instance.FrameCount)
|
||||
frame = 0;
|
||||
|
||||
if (stopPlayback)
|
||||
Instance.Play = false;
|
||||
|
||||
SetCurrentFrame(frame);
|
||||
}
|
||||
|
||||
public static void SetCurrentFrame(int frameIndex)
|
||||
{
|
||||
var main = ModelViewerMain.GetInstance();
|
||||
Instance.CurrentFrame = frameIndex;
|
||||
//Debug.Log(frameIndex);
|
||||
|
||||
foreach (var container in main.CurrentScene.AllObjects)
|
||||
{
|
||||
container.GetClosestFrames(frameIndex, out var previousFrame, out var nextFrame);
|
||||
var blendAmount = previousFrame == nextFrame? 0 : 1 - (float)(nextFrame.FrameNum - frameIndex) / (nextFrame.FrameNum - previousFrame.FrameNum);
|
||||
|
||||
container.Lerp(previousFrame.ObjectData, nextFrame.ObjectData, blendAmount);
|
||||
}
|
||||
UpdateTimeline();
|
||||
}
|
||||
|
||||
public static void SetCurrentFrame(ObjectContainer container)
|
||||
{
|
||||
int frameIndex = Instance.CurrentFrame;
|
||||
|
||||
container.GetClosestFrames(frameIndex, out var previousFrame, out var nextFrame);
|
||||
var blendAmount = previousFrame == nextFrame ? 0 : 1 - (float)(nextFrame.FrameNum - frameIndex) / (nextFrame.FrameNum - previousFrame.FrameNum);
|
||||
|
||||
container.Lerp(previousFrame.ObjectData, nextFrame.ObjectData, blendAmount);
|
||||
}
|
||||
|
||||
public void FillTimeline(int frames)
|
||||
{
|
||||
if (frames > Frames.Count)
|
||||
{
|
||||
int diff = frames - Frames.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
{
|
||||
var frame = Instantiate(SharedResources.Instance.TimelineFrame, Timeline.content).SetNum(Frames.Count);
|
||||
frame.name = Frames.Count.ToString();
|
||||
Frames.Add(frame);
|
||||
}
|
||||
}
|
||||
foreach (var frame in Frames)
|
||||
{
|
||||
frame.gameObject.SetActive(frame.FrameIndex < frames);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSliderScroll()
|
||||
{
|
||||
var sliderPos = TimelineSlider.handleRect.position;
|
||||
var newFrame = Frames.Where(f => f.gameObject.activeInHierarchy).OrderBy(frame => Vector3.Distance(sliderPos, frame.GetComponent<RectTransform>().position)).First();
|
||||
if (CurrentFrame != newFrame.FrameIndex)
|
||||
{
|
||||
SetCurrentFrame(newFrame.FrameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFrameCount(string text)
|
||||
{
|
||||
FrameCount = int.Parse(text);
|
||||
FillTimeline(FrameCount);
|
||||
UpdateTimeline();
|
||||
}
|
||||
|
||||
public void SetFrameDelay(string text)
|
||||
{
|
||||
FrameDelayMS = (int)float.Parse(text, CultureInfo.InvariantCulture);
|
||||
|
||||
if (FrameDelayMS == 0)
|
||||
{
|
||||
FrameDelayMS = 1;
|
||||
}
|
||||
|
||||
FrameRate = 1 / (FrameDelayMS / 1000);
|
||||
InputFrameRate.SetTextWithoutNotify(Mathf.Round(FrameRate).ToString());
|
||||
InputFrameDelay.SetTextWithoutNotify(Mathf.Round(FrameDelayMS).ToString());
|
||||
}
|
||||
|
||||
public void SetFrameRate(string text)
|
||||
{
|
||||
FrameRate = (int)float.Parse(text, CultureInfo.InvariantCulture);
|
||||
|
||||
if(FrameRate == 0)
|
||||
{
|
||||
FrameRate = 1;
|
||||
}
|
||||
|
||||
FrameDelayMS = (1 / FrameRate) * 1000;
|
||||
InputFrameRate.SetTextWithoutNotify(Mathf.Round(FrameRate).ToString());
|
||||
InputFrameDelay.SetTextWithoutNotify(Mathf.Round(FrameDelayMS).ToString());
|
||||
}
|
||||
|
||||
public static void SwapFrames(int frameNum1, int frameNum2)
|
||||
{
|
||||
if (frameNum1 < 0 || frameNum1 >= Instance.FrameCount) return;
|
||||
if (frameNum2 < 0 || frameNum2 >= Instance.FrameCount) return;
|
||||
|
||||
var selectedObject = GetCurrentObject();
|
||||
var frames = selectedObject.Frames;
|
||||
|
||||
var frame1 = selectedObject.TryGetFrame(frameNum1);
|
||||
var frame2 = selectedObject.TryGetFrame(frameNum2);
|
||||
|
||||
if (frame1 != null)
|
||||
{
|
||||
frame1.FrameNum = frameNum2;
|
||||
}
|
||||
|
||||
if (frame2 != null)
|
||||
{
|
||||
frame2.FrameNum = frameNum1;
|
||||
}
|
||||
|
||||
selectedObject.Frames = selectedObject.Frames.OrderBy(f => f.FrameNum).ToList();
|
||||
|
||||
SetCurrentFrame(Instance.CurrentFrame);
|
||||
}
|
||||
|
||||
public static void UpdateTimeline()
|
||||
{
|
||||
var container = GetCurrentObject();
|
||||
|
||||
Instance.SelectedObjectLabel.text = container.name;
|
||||
|
||||
var frames = Instance.Frames.ToList();
|
||||
|
||||
for (int i = 0; i < container.Frames.Count; i++)
|
||||
{
|
||||
var frameNum = container.Frames[i].FrameNum;
|
||||
if (frameNum >= frames.Count) return;
|
||||
|
||||
var frame = frames[frameNum];
|
||||
frame.UpdateContent(container, container.Frames[i]);
|
||||
frames[frameNum] = null;
|
||||
}
|
||||
|
||||
foreach(var frame in frames)
|
||||
{
|
||||
if (frame == null) continue;
|
||||
|
||||
frame.UpdateContent(container, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjectContainer GetCurrentObject()
|
||||
{
|
||||
ObjectContainer container = ModelViewerMain.GetInstance().SelectedObject;
|
||||
|
||||
if (container == null)
|
||||
{
|
||||
container = ModelViewerMain.GetInstance().MainCameraOrbit;
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
public void OnButtonSet()
|
||||
{
|
||||
GetCurrentObject().SetKeyframe(CurrentFrame);
|
||||
}
|
||||
|
||||
public void OnButtonDelete()
|
||||
{
|
||||
Frames[CurrentFrame].DeleteFrame();
|
||||
}
|
||||
|
||||
public void OnButtonCopy()
|
||||
{
|
||||
Frames[CurrentFrame].CopyFrame();
|
||||
}
|
||||
|
||||
|
||||
public void OnButtonPaste()
|
||||
{
|
||||
var data = CopyBuffer;
|
||||
if (data == null) return;
|
||||
|
||||
if (GetCurrentObject() == data.TrackedObject)
|
||||
{
|
||||
if (Input.GetKey(KeyCode.LeftShift)) PasteStep0(data);
|
||||
else PasteStep1(data, new PoseLoadOptions(true));
|
||||
return;
|
||||
}
|
||||
|
||||
UIPopupMessage.Create("You're pasting from a different object. Continue?",
|
||||
() =>
|
||||
{
|
||||
if (Input.GetKey(KeyCode.LeftShift)) PasteStep0(data);
|
||||
else PasteStep1(data, new PoseLoadOptions(true));
|
||||
},
|
||||
() => { }
|
||||
);
|
||||
}
|
||||
|
||||
private void PasteStep0(CopyBufferData data)
|
||||
{
|
||||
UIPopupPastePanel.Create(
|
||||
(pasteOptions) => { PasteStep1(data, pasteOptions); Debug.Log(pasteOptions.Root); },
|
||||
() => { });
|
||||
}
|
||||
|
||||
private void PasteStep1(CopyBufferData data, PoseLoadOptions options)
|
||||
{
|
||||
int frameNum = CurrentFrame;
|
||||
var trackedObject = data.TrackedObject;
|
||||
if (trackedObject == null)
|
||||
{
|
||||
Error.Log(Color.red, "Object has been deleted?");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!trackedObject.GetCurrentFrame(frameNum, out var currentFrame))
|
||||
{
|
||||
trackedObject.PastePose(data.Content.ObjectData, options);
|
||||
currentFrame.SetObjectData(trackedObject.SerializeFrame());
|
||||
SetCurrentFrame(trackedObject);
|
||||
return;
|
||||
}
|
||||
|
||||
UIPopupMessage.Create($"Replace existing data for {trackedObject.name}?",
|
||||
() => {
|
||||
trackedObject.PastePose(data.Content.ObjectData, options);
|
||||
currentFrame.SetObjectData(trackedObject.SerializeFrame());
|
||||
SetCurrentFrame(trackedObject);
|
||||
},
|
||||
() =>{}
|
||||
);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ModelViewerBase/UI/TimelineController.cs.meta
Normal file
11
Assets/Scripts/ModelViewerBase/UI/TimelineController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc7b115ccf00bef478bc99409c5e2443
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
[System.Serializable]
|
||||
public class TimelineControllerSerializable
|
||||
{
|
||||
public int FrameCount;
|
||||
public float FrameDelay;
|
||||
public int CurrentFrame;
|
||||
|
||||
public TimelineControllerSerializable() { }
|
||||
|
||||
public TimelineControllerSerializable(TimelineController tc)
|
||||
{
|
||||
FrameCount = tc.FrameCount;
|
||||
FrameDelay = tc.FrameDelayMS;
|
||||
CurrentFrame = tc.CurrentFrame;
|
||||
}
|
||||
|
||||
public void Deserialize(TimelineController tc)
|
||||
{
|
||||
tc.FrameCount = FrameCount;
|
||||
tc.SetFrameDelay(FrameDelay.ToString());
|
||||
tc.CurrentFrame = CurrentFrame;
|
||||
tc.FillTimeline(TimelineController.Instance.FrameCount);
|
||||
TimelineController.UpdateTimeline();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user