Initial files

This commit is contained in:
2024-04-21 16:38:26 +02:00
parent c69c668ae6
commit cf04700131
554 changed files with 131197 additions and 0 deletions

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68d09003b62bea04bbedb8a5b21b9aa6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,5 @@
public class AssetSpawnData
{
public AssetTypes AssetType;
public string FilePath;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a31e5f4826d6b7c42bca99c19497a7f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
public enum AssetTypes
{
Unknown,
Character,
Object
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 547b343c746a81e4dbfc463e6edd4948
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
[System.Serializable]
public class BoneList
{
public string Name;
public SerializableBone[] Bones = new SerializableBone[0];
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 98e7f80672878ce44b33fbf239398d53
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 32a48605970827e4999f4dd7807a5eac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38982c2df9f1d8143ab670461e160feb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View 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();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 72e8d74079817324498115876d689669
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a1693bb5411564489cd61fa721c0fd0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2bf6dfe0e5776cd49b8f8923c18704da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85c39ae818417104eb7ae9174bd0f708
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 520e0b69d9f17e2488c1eb19d9a50940
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7592143342b8b0741831e85e6a2f88b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 30d20bcf9ec4ed24b97a6e8ab136c34f
timeCreated: 1499795966
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3553f9c3dfc57b14d95850ae26fc05e7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1f135e4ce2898524aa1e81c5cd7f1242
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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();
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 413260822fc499146b2e2bfdc91a5a21
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b1090dfa84b72140b13b27e73e267f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b829d711d6087b41a841693e6a48c1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f825489d1d491e478e07e6e6334ca16
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: adae87bbf883dae4baa06f2c4303f5cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,6 @@
public interface IKeyframeSetter
{
public void SetKeyframe(int frameNum);
public void EnableKeyframeSet();
public void DisableKeyframeSet();
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8fa2a5bc09d8ef04c8e7844a4c11ade4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 78f95c9a0a831be438b081224ae745eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6436dcc628970074cb9f996d0953e8fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 943743df82cb7ce41a28df2e9cda34dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -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();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ad6653f31ee3e334da62554c392eee38
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 157ab30982d081842bb68ee2cb4f8d7b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8af8c42fefb782c4ea8b0f63839931cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View 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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 588358108868b3e4a9c5d0771c66dbd3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3514ca7309b4404fa82480b7356b964
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
});
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39645b413d3a924438246b4f9ffaadc5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 491e0b38519c9e94facd88535f6f3458
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f855de4e8b12374a8c7ef07e3ce5142
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ebd7e66c67c47f4fa215b1e3ba00091
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03de88101ab64404e9d237323c9663b6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: add71905575d4ec44b658c58aa433e1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 43d8d17f43ab7d94ca0a609656dfee90
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e0fa65a26810d854ebc243e69ff044f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59083bc243f250f4a8918f69361d09e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1c8f58133046c8b44bee5d32b4bc2cee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a16bc42a3ca264e4b8ad40eb7aa2c6e9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 983bac4a8a262aa4eada7f5da7144d26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c34b8ed085cbb684f9f9646f6c1175d2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 553b93692909e854c8f78f6457a4f46e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: da09db22068c39445a2454d09ac5b09c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c6c796de2dad3dd42a843945e951de9b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
},
() =>{}
);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc7b115ccf00bef478bc99409c5e2443
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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