834 lines
24 KiB
C#
834 lines
24 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Globalization;
|
||
|
using System.Linq;
|
||
|
using HG;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.EventSystems;
|
||
|
using UnityEngine.Rendering.PostProcessing;
|
||
|
using UnityEngine.UI;
|
||
|
|
||
|
namespace RoR2.UI;
|
||
|
|
||
|
[RequireComponent(typeof(RectTransform))]
|
||
|
[RequireComponent(typeof(RawImage))]
|
||
|
public class ModelPanel : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IScrollHandler, IEndDragHandler
|
||
|
{
|
||
|
private class CameraFramingCalculator
|
||
|
{
|
||
|
private GameObject modelInstance;
|
||
|
|
||
|
private Transform root;
|
||
|
|
||
|
private readonly List<Transform> boneList = new List<Transform>();
|
||
|
|
||
|
private HurtBoxGroup hurtBoxGroup;
|
||
|
|
||
|
private HurtBox[] hurtBoxes = Array.Empty<HurtBox>();
|
||
|
|
||
|
public Vector3 outputPivotPoint;
|
||
|
|
||
|
public Vector3 outputCameraPosition;
|
||
|
|
||
|
public float outputMinDistance;
|
||
|
|
||
|
public float outputMaxDistance;
|
||
|
|
||
|
public Quaternion outputCameraRotation;
|
||
|
|
||
|
private static void GenerateBoneList(Transform rootBone, List<Transform> boneList)
|
||
|
{
|
||
|
boneList.AddRange(rootBone.gameObject.GetComponentsInChildren<Transform>());
|
||
|
}
|
||
|
|
||
|
public CameraFramingCalculator(GameObject modelInstance)
|
||
|
{
|
||
|
this.modelInstance = modelInstance;
|
||
|
root = modelInstance.transform;
|
||
|
GenerateBoneList(root, boneList);
|
||
|
hurtBoxGroup = modelInstance.GetComponent<HurtBoxGroup>();
|
||
|
if ((bool)hurtBoxGroup)
|
||
|
{
|
||
|
hurtBoxes = hurtBoxGroup.hurtBoxes;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool FindBestEyePoint(out Vector3 result, out float approximateEyeRadius)
|
||
|
{
|
||
|
approximateEyeRadius = 1f;
|
||
|
IEnumerable<Transform> source = boneList.Where(FirstChoice);
|
||
|
if (!source.Any())
|
||
|
{
|
||
|
source = boneList.Where(SecondChoice);
|
||
|
}
|
||
|
Vector3[] array = source.Select((Transform bone) => bone.position).ToArray();
|
||
|
result = Vector3Utils.AveragePrecise(array);
|
||
|
for (int i = 0; i < array.Length; i++)
|
||
|
{
|
||
|
float magnitude = (array[i] - result).magnitude;
|
||
|
if (magnitude > approximateEyeRadius)
|
||
|
{
|
||
|
approximateEyeRadius = magnitude;
|
||
|
}
|
||
|
}
|
||
|
return array.Length != 0;
|
||
|
static bool FirstChoice(Transform bone)
|
||
|
{
|
||
|
if ((bool)bone.GetComponent<SkinnedMeshRenderer>())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
string name = bone.name;
|
||
|
if (name.Equals("eye", StringComparison.OrdinalIgnoreCase))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if (name.Equals("eyeball.1", StringComparison.OrdinalIgnoreCase))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
static bool SecondChoice(Transform bone)
|
||
|
{
|
||
|
if ((bool)bone.GetComponent<SkinnedMeshRenderer>())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
return bone.name.ToLower().Contains("eye");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool FindBestHeadPoint(string searchName, out Vector3 result, out float approximateRadius)
|
||
|
{
|
||
|
Transform[] array = boneList.Where((Transform bone) => string.Equals(bone.name, searchName, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||
|
if (array.Length == 0)
|
||
|
{
|
||
|
array = boneList.Where((Transform bone) => bone.name.ToLower(CultureInfo.InvariantCulture).Contains(searchName)).ToArray();
|
||
|
}
|
||
|
if (array.Length != 0)
|
||
|
{
|
||
|
foreach (Transform bone2 in array)
|
||
|
{
|
||
|
if (TryCalcBoneBounds(bone2, 0.2f, out var bounds, out approximateRadius))
|
||
|
{
|
||
|
result = bounds.center;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
result = Vector3.zero;
|
||
|
approximateRadius = 0f;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private static float CalcMagnitudeToFrameSphere(float sphereRadius, float fieldOfView)
|
||
|
{
|
||
|
float num = fieldOfView * 0.5f;
|
||
|
float num2 = 90f;
|
||
|
return Mathf.Tan((180f - num2 - num) * (MathF.PI / 180f)) * sphereRadius;
|
||
|
}
|
||
|
|
||
|
private bool FindBestCenterOfMass(out Vector3 result, out float approximateRadius)
|
||
|
{
|
||
|
_ = from bone in boneList
|
||
|
select bone.GetComponent<HurtBox>() into hurtBox
|
||
|
where hurtBox
|
||
|
select hurtBox;
|
||
|
if ((bool)hurtBoxGroup && (bool)hurtBoxGroup.mainHurtBox)
|
||
|
{
|
||
|
result = hurtBoxGroup.mainHurtBox.transform.position;
|
||
|
approximateRadius = Util.SphereVolumeToRadius(hurtBoxGroup.mainHurtBox.volume);
|
||
|
return true;
|
||
|
}
|
||
|
result = Vector3.zero;
|
||
|
approximateRadius = 1f;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private static float GetWeightForBone(ref BoneWeight boneWeight, int boneIndex)
|
||
|
{
|
||
|
if (boneWeight.boneIndex0 == boneIndex)
|
||
|
{
|
||
|
return boneWeight.weight0;
|
||
|
}
|
||
|
if (boneWeight.boneIndex1 == boneIndex)
|
||
|
{
|
||
|
return boneWeight.weight1;
|
||
|
}
|
||
|
if (boneWeight.boneIndex2 == boneIndex)
|
||
|
{
|
||
|
return boneWeight.weight2;
|
||
|
}
|
||
|
if (boneWeight.boneIndex3 == boneIndex)
|
||
|
{
|
||
|
return boneWeight.weight3;
|
||
|
}
|
||
|
return 0f;
|
||
|
}
|
||
|
|
||
|
private static int FindBoneIndex(SkinnedMeshRenderer _skinnedMeshRenderer, Transform _bone)
|
||
|
{
|
||
|
Transform[] bones = _skinnedMeshRenderer.bones;
|
||
|
for (int i = 0; i < bones.Length; i++)
|
||
|
{
|
||
|
if (bones[i] == _bone)
|
||
|
{
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
private bool TryCalcBoneBounds(Transform bone, float weightThreshold, out Bounds bounds, out float approximateRadius)
|
||
|
{
|
||
|
SkinnedMeshRenderer[] componentsInChildren = modelInstance.GetComponentsInChildren<SkinnedMeshRenderer>();
|
||
|
SkinnedMeshRenderer skinnedMeshRenderer = null;
|
||
|
Mesh mesh = null;
|
||
|
int num = -1;
|
||
|
List<int> list = new List<int>();
|
||
|
for (int i = 0; i < componentsInChildren.Length; i++)
|
||
|
{
|
||
|
skinnedMeshRenderer = componentsInChildren[i];
|
||
|
mesh = skinnedMeshRenderer.sharedMesh;
|
||
|
if (!mesh)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
num = FindBoneIndex(skinnedMeshRenderer, bone);
|
||
|
if (num != -1)
|
||
|
{
|
||
|
BoneWeight[] boneWeights = mesh.boneWeights;
|
||
|
for (int j = 0; j < boneWeights.Length; j++)
|
||
|
{
|
||
|
if (GetWeightForBone(ref boneWeights[j], num) > weightThreshold)
|
||
|
{
|
||
|
list.Add(j);
|
||
|
}
|
||
|
}
|
||
|
if (list.Count == 0)
|
||
|
{
|
||
|
num = -1;
|
||
|
}
|
||
|
}
|
||
|
if (num != -1)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (num == -1)
|
||
|
{
|
||
|
bounds = default(Bounds);
|
||
|
approximateRadius = 0f;
|
||
|
return false;
|
||
|
}
|
||
|
Mesh mesh2 = new Mesh();
|
||
|
skinnedMeshRenderer.BakeMesh(mesh2);
|
||
|
Vector3[] vertices = mesh2.vertices;
|
||
|
UnityEngine.Object.Destroy(mesh2);
|
||
|
if (mesh2.vertexCount != mesh.vertexCount)
|
||
|
{
|
||
|
Debug.LogWarningFormat("Baked mesh vertex count differs from the original mesh vertex count! baked={0} original={1}", mesh2.vertexCount, mesh.vertexCount);
|
||
|
vertices = mesh.vertices;
|
||
|
}
|
||
|
Vector3[] array = new Vector3[list.Count];
|
||
|
Transform transform = skinnedMeshRenderer.transform;
|
||
|
Vector3 position = transform.position;
|
||
|
Quaternion rotation = transform.rotation;
|
||
|
for (int k = 0; k < list.Count; k++)
|
||
|
{
|
||
|
int num2 = list[k];
|
||
|
Vector3 vector = vertices[num2];
|
||
|
Vector3 vector2 = position + rotation * vector;
|
||
|
array[k] = vector2;
|
||
|
}
|
||
|
bounds = new Bounds(Vector3Utils.AveragePrecise(array), Vector3.zero);
|
||
|
float num3 = 0f;
|
||
|
for (int l = 0; l < array.Length; l++)
|
||
|
{
|
||
|
bounds.Encapsulate(array[l]);
|
||
|
float num4 = Vector3.Distance(bounds.center, array[l]);
|
||
|
if (num4 > num3)
|
||
|
{
|
||
|
num3 = num4;
|
||
|
}
|
||
|
}
|
||
|
approximateRadius = num3;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void GetCharacterThumbnailPosition(float fov)
|
||
|
{
|
||
|
ModelPanelParameters component = modelInstance.GetComponent<ModelPanelParameters>();
|
||
|
if ((bool)component)
|
||
|
{
|
||
|
if ((bool)component.focusPointTransform)
|
||
|
{
|
||
|
outputPivotPoint = component.focusPointTransform.position;
|
||
|
}
|
||
|
if ((bool)component.cameraPositionTransform)
|
||
|
{
|
||
|
outputCameraPosition = component.cameraPositionTransform.position;
|
||
|
}
|
||
|
outputCameraRotation = Util.QuaternionSafeLookRotation(component.cameraDirection);
|
||
|
outputMinDistance = component.minDistance;
|
||
|
outputMaxDistance = component.maxDistance;
|
||
|
return;
|
||
|
}
|
||
|
Vector3 result = Vector3.zero;
|
||
|
float approximateRadius = 1f;
|
||
|
bool flag = FindBestHeadPoint("head", out result, out approximateRadius);
|
||
|
if (!flag)
|
||
|
{
|
||
|
flag = FindBestHeadPoint("chest", out result, out approximateRadius);
|
||
|
}
|
||
|
bool flag2 = false;
|
||
|
bool flag3 = false;
|
||
|
float num = 1f;
|
||
|
float approximateEyeRadius = 1f;
|
||
|
flag2 = FindBestEyePoint(out var result2, out approximateEyeRadius);
|
||
|
if (!flag)
|
||
|
{
|
||
|
approximateRadius = approximateEyeRadius;
|
||
|
}
|
||
|
if (flag2)
|
||
|
{
|
||
|
result = result2;
|
||
|
}
|
||
|
if (!flag && !flag2)
|
||
|
{
|
||
|
flag3 = FindBestCenterOfMass(out result, out approximateRadius);
|
||
|
}
|
||
|
float num2 = 1f;
|
||
|
if (Util.GuessRenderBoundsMeshOnly(modelInstance, out var bounds))
|
||
|
{
|
||
|
if (flag3)
|
||
|
{
|
||
|
approximateRadius = Util.SphereVolumeToRadius(bounds.size.x * bounds.size.y * bounds.size.z);
|
||
|
}
|
||
|
Mathf.Max((result.y - bounds.min.y) / bounds.size.y - 0.5f - 0.2f, 0f);
|
||
|
_ = bounds.center;
|
||
|
num2 = bounds.size.z / bounds.size.x;
|
||
|
outputMinDistance = Mathf.Min(bounds.size.x, bounds.size.y, bounds.size.z) * 1f;
|
||
|
outputMaxDistance = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z) * 2f;
|
||
|
}
|
||
|
Vector3 vector = -root.forward;
|
||
|
for (int i = 0; i < boneList.Count; i++)
|
||
|
{
|
||
|
if (boneList[i].name.Equals("muzzle", StringComparison.OrdinalIgnoreCase))
|
||
|
{
|
||
|
Vector3 vector2 = root.position - boneList[i].position;
|
||
|
vector2.y = 0f;
|
||
|
float magnitude = vector2.magnitude;
|
||
|
if (magnitude > 0.2f)
|
||
|
{
|
||
|
vector2 /= magnitude;
|
||
|
vector = vector2;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
vector = Quaternion.Euler(0f, 57.29578f * Mathf.Atan(num2 - 1f) * 1f, 0f) * vector;
|
||
|
Vector3 vector3 = -vector * (CalcMagnitudeToFrameSphere(approximateRadius, fov) + num);
|
||
|
Vector3 vector4 = result + vector3;
|
||
|
outputPivotPoint = result;
|
||
|
outputCameraPosition = vector4;
|
||
|
outputCameraRotation = Util.QuaternionSafeLookRotation(result - vector4);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private GameObject _modelPrefab;
|
||
|
|
||
|
public GameObject modelPostProcessVolumePrefab;
|
||
|
|
||
|
public Vector3 modelPostProcessVolumePosition = Vector3.zero;
|
||
|
|
||
|
public RenderSettingsState renderSettings;
|
||
|
|
||
|
public Color camBackgroundColor = Color.clear;
|
||
|
|
||
|
public bool disablePostProcessLayer = true;
|
||
|
|
||
|
public bool useUnscaledTime;
|
||
|
|
||
|
private static int isGroundedParamHash = Animator.StringToHash("isGrounded");
|
||
|
|
||
|
private static int aimPitchCycleParamHash = Animator.StringToHash("aimPitchCycle");
|
||
|
|
||
|
private static int aimYawCycleParamHash = Animator.StringToHash("aimYawCycle");
|
||
|
|
||
|
private static int IdleStateHash = Animator.StringToHash("Idle");
|
||
|
|
||
|
private RectTransform rectTransform;
|
||
|
|
||
|
private RawImage rawImage;
|
||
|
|
||
|
private GameObject modelInstance;
|
||
|
|
||
|
private CameraRigController cameraRigController;
|
||
|
|
||
|
private ModelCamera modelCamera;
|
||
|
|
||
|
public GameObject headlightPrefab;
|
||
|
|
||
|
public GameObject[] lightPrefabs;
|
||
|
|
||
|
private GameObject modelPostProcessVolumeInstance;
|
||
|
|
||
|
private Vector3 postProcessVolumeLocation;
|
||
|
|
||
|
private Light headlight;
|
||
|
|
||
|
public float fov = 60f;
|
||
|
|
||
|
public bool enableGamepadControls;
|
||
|
|
||
|
public float gamepadZoomSensitivity;
|
||
|
|
||
|
public float gamepadRotateSensitivity;
|
||
|
|
||
|
public UILayerKey requiredTopLayer;
|
||
|
|
||
|
private MPEventSystemLocator mpEventSystemLocator;
|
||
|
|
||
|
private float zoom = 0.5f;
|
||
|
|
||
|
private float desiredZoom = 0.5f;
|
||
|
|
||
|
private float zoomVelocity;
|
||
|
|
||
|
private float minDistance = 0.5f;
|
||
|
|
||
|
private float maxDistance = 10f;
|
||
|
|
||
|
private float orbitPitch;
|
||
|
|
||
|
private float orbitYaw = 180f;
|
||
|
|
||
|
private Vector3 orbitalVelocity = Vector3.zero;
|
||
|
|
||
|
private Vector3 orbitalVelocitySmoothDampVelocity = Vector3.zero;
|
||
|
|
||
|
private Vector2 pan;
|
||
|
|
||
|
private Vector2 panVelocity;
|
||
|
|
||
|
private Vector2 panVelocitySmoothDampVelocity;
|
||
|
|
||
|
private Vector3 pivotPoint = Vector3.zero;
|
||
|
|
||
|
private List<Light> lights = new List<Light>();
|
||
|
|
||
|
private Vector2 orbitDragPoint;
|
||
|
|
||
|
private Vector2 panDragPoint;
|
||
|
|
||
|
private int orbitDragCount;
|
||
|
|
||
|
private int panDragCount;
|
||
|
|
||
|
public GameObject modelPrefab
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return _modelPrefab;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
if (!(_modelPrefab == value))
|
||
|
{
|
||
|
DestroyModelInstance();
|
||
|
_modelPrefab = value;
|
||
|
BuildModelInstance();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public RenderTexture renderTexture { get; private set; }
|
||
|
|
||
|
private void DestroyModelInstance()
|
||
|
{
|
||
|
UnityEngine.Object.Destroy(modelInstance);
|
||
|
modelInstance = null;
|
||
|
}
|
||
|
|
||
|
private void BuildModelInstance()
|
||
|
{
|
||
|
if (!_modelPrefab || !base.enabled || (bool)modelInstance)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
modelInstance = UnityEngine.Object.Instantiate(_modelPrefab, modelPostProcessVolumePosition, Quaternion.identity);
|
||
|
ModelPanelParameters component = _modelPrefab.GetComponent<ModelPanelParameters>();
|
||
|
if ((bool)component)
|
||
|
{
|
||
|
modelInstance.transform.rotation = component.modelRotation;
|
||
|
}
|
||
|
Util.GuessRenderBoundsMeshOnly(modelInstance, out var bounds);
|
||
|
pivotPoint = bounds.center;
|
||
|
minDistance = Mathf.Min(bounds.size.x, bounds.size.y, bounds.size.z) * 1f;
|
||
|
maxDistance = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z) * 2f;
|
||
|
Renderer[] componentsInChildren = modelInstance.GetComponentsInChildren<Renderer>();
|
||
|
for (int i = 0; i < componentsInChildren.Length; i++)
|
||
|
{
|
||
|
componentsInChildren[i].gameObject.layer = LayerIndex.noDraw.intVal;
|
||
|
}
|
||
|
AimAnimator[] componentsInChildren2 = modelInstance.GetComponentsInChildren<AimAnimator>();
|
||
|
for (int j = 0; j < componentsInChildren2.Length; j++)
|
||
|
{
|
||
|
componentsInChildren2[j].inputBank = null;
|
||
|
componentsInChildren2[j].directionComponent = null;
|
||
|
componentsInChildren2[j].enabled = false;
|
||
|
}
|
||
|
Animator[] componentsInChildren3 = modelInstance.GetComponentsInChildren<Animator>();
|
||
|
foreach (Animator obj in componentsInChildren3)
|
||
|
{
|
||
|
obj.SetBool(isGroundedParamHash, value: true);
|
||
|
obj.SetFloat(aimPitchCycleParamHash, 0.5f);
|
||
|
obj.SetFloat(aimYawCycleParamHash, 0.5f);
|
||
|
obj.Play(IdleStateHash);
|
||
|
obj.Update(0f);
|
||
|
obj.updateMode = AnimatorUpdateMode.UnscaledTime;
|
||
|
}
|
||
|
IKSimpleChain[] componentsInChildren4 = modelInstance.GetComponentsInChildren<IKSimpleChain>();
|
||
|
for (int l = 0; l < componentsInChildren4.Length; l++)
|
||
|
{
|
||
|
componentsInChildren4[l].enabled = false;
|
||
|
}
|
||
|
DitherModel[] componentsInChildren5 = modelInstance.GetComponentsInChildren<DitherModel>();
|
||
|
for (int m = 0; m < componentsInChildren5.Length; m++)
|
||
|
{
|
||
|
componentsInChildren5[m].enabled = false;
|
||
|
}
|
||
|
PrintController[] componentsInChildren6 = modelInstance.GetComponentsInChildren<PrintController>();
|
||
|
for (int m = 0; m < componentsInChildren6.Length; m++)
|
||
|
{
|
||
|
componentsInChildren6[m].enabled = false;
|
||
|
}
|
||
|
LightIntensityCurve[] componentsInChildren7 = modelInstance.GetComponentsInChildren<LightIntensityCurve>();
|
||
|
foreach (LightIntensityCurve lightIntensityCurve in componentsInChildren7)
|
||
|
{
|
||
|
if (!lightIntensityCurve.loop)
|
||
|
{
|
||
|
lightIntensityCurve.enabled = false;
|
||
|
}
|
||
|
}
|
||
|
AkEvent[] componentsInChildren8 = modelInstance.GetComponentsInChildren<AkEvent>();
|
||
|
for (int m = 0; m < componentsInChildren8.Length; m++)
|
||
|
{
|
||
|
componentsInChildren8[m].enabled = false;
|
||
|
}
|
||
|
TemporaryOverlay[] componentsInChildren9 = modelInstance.GetComponentsInChildren<TemporaryOverlay>();
|
||
|
for (int m = 0; m < componentsInChildren9.Length; m++)
|
||
|
{
|
||
|
UnityEngine.Object.Destroy(componentsInChildren9[m]);
|
||
|
}
|
||
|
ParticleSystem[] componentsInChildren10 = modelInstance.GetComponentsInChildren<ParticleSystem>();
|
||
|
for (int m = 0; m < componentsInChildren10.Length; m++)
|
||
|
{
|
||
|
ParticleSystem.MainModule main = componentsInChildren10[m].main;
|
||
|
main.useUnscaledTime = true;
|
||
|
}
|
||
|
desiredZoom = 0.5f;
|
||
|
zoom = desiredZoom;
|
||
|
zoomVelocity = 0f;
|
||
|
ResetOrbitAndPan();
|
||
|
}
|
||
|
|
||
|
private void ResetOrbitAndPan()
|
||
|
{
|
||
|
orbitPitch = 0f;
|
||
|
orbitYaw = 0f;
|
||
|
orbitalVelocity = Vector3.zero;
|
||
|
orbitalVelocitySmoothDampVelocity = Vector3.zero;
|
||
|
pan = Vector2.zero;
|
||
|
panVelocity = Vector2.zero;
|
||
|
panVelocitySmoothDampVelocity = Vector2.zero;
|
||
|
}
|
||
|
|
||
|
private void Awake()
|
||
|
{
|
||
|
modelPostProcessVolumeInstance = UnityEngine.Object.Instantiate(modelPostProcessVolumePrefab, modelPostProcessVolumePosition, Quaternion.identity);
|
||
|
rectTransform = GetComponent<RectTransform>();
|
||
|
rawImage = GetComponent<RawImage>();
|
||
|
mpEventSystemLocator = GetComponent<MPEventSystemLocator>();
|
||
|
cameraRigController = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load<GameObject>("Prefabs/Main Camera")).GetComponent<CameraRigController>();
|
||
|
cameraRigController.gameObject.name = "ModelCamera";
|
||
|
cameraRigController.uiCam.gameObject.SetActive(value: false);
|
||
|
cameraRigController.createHud = false;
|
||
|
cameraRigController.enableFading = false;
|
||
|
cameraRigController.enableMusic = false;
|
||
|
GameObject gameObject = cameraRigController.sceneCam.gameObject;
|
||
|
modelCamera = gameObject.AddComponent<ModelCamera>();
|
||
|
cameraRigController.transform.position = modelPostProcessVolumeInstance.transform.position - Vector3.forward * 10f;
|
||
|
cameraRigController.transform.forward = Vector3.forward;
|
||
|
CameraResolutionScaler component = gameObject.GetComponent<CameraResolutionScaler>();
|
||
|
if ((bool)component)
|
||
|
{
|
||
|
component.enabled = false;
|
||
|
}
|
||
|
Camera sceneCam = cameraRigController.sceneCam;
|
||
|
sceneCam.backgroundColor = Color.clear;
|
||
|
sceneCam.clearFlags = CameraClearFlags.Color;
|
||
|
if (disablePostProcessLayer)
|
||
|
{
|
||
|
PostProcessLayer component2 = sceneCam.GetComponent<PostProcessLayer>();
|
||
|
if ((bool)component2)
|
||
|
{
|
||
|
component2.enabled = false;
|
||
|
}
|
||
|
}
|
||
|
Vector3 eulerAngles = cameraRigController.transform.eulerAngles;
|
||
|
orbitPitch = eulerAngles.x;
|
||
|
orbitYaw = eulerAngles.y;
|
||
|
modelCamera.attachedCamera.backgroundColor = camBackgroundColor;
|
||
|
modelCamera.attachedCamera.clearFlags = CameraClearFlags.Color;
|
||
|
modelCamera.attachedCamera.cullingMask = LayerIndex.manualRender.mask;
|
||
|
if ((bool)headlightPrefab)
|
||
|
{
|
||
|
headlight = UnityEngine.Object.Instantiate(headlightPrefab, modelCamera.transform).GetComponent<Light>();
|
||
|
if ((bool)headlight)
|
||
|
{
|
||
|
headlight.gameObject.SetActive(value: true);
|
||
|
modelCamera.AddLight(headlight);
|
||
|
}
|
||
|
}
|
||
|
for (int i = 0; i < lightPrefabs.Length; i++)
|
||
|
{
|
||
|
GameObject obj = UnityEngine.Object.Instantiate(lightPrefabs[i]);
|
||
|
Light component3 = obj.GetComponent<Light>();
|
||
|
obj.SetActive(value: true);
|
||
|
lights.Add(component3);
|
||
|
modelCamera.AddLight(component3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Start()
|
||
|
{
|
||
|
BuildRenderTexture();
|
||
|
desiredZoom = 0.5f;
|
||
|
zoom = desiredZoom;
|
||
|
zoomVelocity = 0f;
|
||
|
}
|
||
|
|
||
|
private void OnDestroy()
|
||
|
{
|
||
|
UnityEngine.Object.Destroy(renderTexture);
|
||
|
if ((bool)modelPostProcessVolumeInstance)
|
||
|
{
|
||
|
UnityEngine.Object.Destroy(modelPostProcessVolumeInstance);
|
||
|
}
|
||
|
if ((bool)cameraRigController)
|
||
|
{
|
||
|
UnityEngine.Object.Destroy(cameraRigController.gameObject);
|
||
|
}
|
||
|
foreach (Light light in lights)
|
||
|
{
|
||
|
UnityEngine.Object.Destroy(light.gameObject);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnDisable()
|
||
|
{
|
||
|
DestroyModelInstance();
|
||
|
}
|
||
|
|
||
|
private void OnEnable()
|
||
|
{
|
||
|
BuildModelInstance();
|
||
|
}
|
||
|
|
||
|
public void Update()
|
||
|
{
|
||
|
UpdateForModelViewer(Time.unscaledDeltaTime);
|
||
|
if (enableGamepadControls && (!requiredTopLayer || requiredTopLayer.representsTopLayer) && mpEventSystemLocator.eventSystem.currentInputSource == MPEventSystem.InputSource.Gamepad && (bool)mpEventSystemLocator.eventSystem)
|
||
|
{
|
||
|
float axis = mpEventSystemLocator.eventSystem.player.GetAxis(16);
|
||
|
float axis2 = mpEventSystemLocator.eventSystem.player.GetAxis(17);
|
||
|
bool button = mpEventSystemLocator.eventSystem.player.GetButton(29);
|
||
|
bool button2 = mpEventSystemLocator.eventSystem.player.GetButton(30);
|
||
|
Vector3 zero = Vector3.zero;
|
||
|
zero.y = (0f - axis) * gamepadRotateSensitivity;
|
||
|
zero.x = axis2 * gamepadRotateSensitivity;
|
||
|
orbitalVelocity = zero;
|
||
|
if (button != button2)
|
||
|
{
|
||
|
desiredZoom = Mathf.Clamp01(desiredZoom + (button ? 0.1f : (-0.1f)) * Time.deltaTime * gamepadZoomSensitivity);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void LateUpdate()
|
||
|
{
|
||
|
modelCamera.attachedCamera.aspect = (float)renderTexture.width / (float)renderTexture.height;
|
||
|
cameraRigController.baseFov = fov;
|
||
|
modelCamera.renderSettings = renderSettings;
|
||
|
modelCamera.RenderItem(modelInstance, renderTexture);
|
||
|
}
|
||
|
|
||
|
private void OnRectTransformDimensionsChange()
|
||
|
{
|
||
|
BuildRenderTexture();
|
||
|
}
|
||
|
|
||
|
private void BuildRenderTexture()
|
||
|
{
|
||
|
if (!rectTransform)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
Vector3[] fourCornersArray = new Vector3[4];
|
||
|
rectTransform.GetLocalCorners(fourCornersArray);
|
||
|
Vector2 size = rectTransform.rect.size;
|
||
|
int num = Mathf.FloorToInt(size.x);
|
||
|
int num2 = Mathf.FloorToInt(size.y);
|
||
|
if (!renderTexture || renderTexture.width != num || renderTexture.height != num2)
|
||
|
{
|
||
|
UnityEngine.Object.Destroy(renderTexture);
|
||
|
renderTexture = null;
|
||
|
if (num > 0 && num2 > 0)
|
||
|
{
|
||
|
RenderTextureDescriptor desc = new RenderTextureDescriptor(num, num2, RenderTextureFormat.ARGB32);
|
||
|
desc.sRGB = true;
|
||
|
renderTexture = new RenderTexture(desc);
|
||
|
renderTexture.useMipMap = false;
|
||
|
renderTexture.filterMode = FilterMode.Bilinear;
|
||
|
}
|
||
|
rawImage.texture = renderTexture;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void UpdateForModelViewer(float deltaTime)
|
||
|
{
|
||
|
zoom = Mathf.SmoothDamp(zoom, desiredZoom, ref zoomVelocity, 0.1f, 10f, deltaTime);
|
||
|
orbitPitch %= 360f;
|
||
|
if (orbitPitch < -180f)
|
||
|
{
|
||
|
orbitPitch += 360f;
|
||
|
}
|
||
|
else if (orbitPitch > 180f)
|
||
|
{
|
||
|
orbitPitch -= 360f;
|
||
|
}
|
||
|
orbitPitch = Mathf.Clamp(orbitPitch + orbitalVelocity.x * deltaTime, -89f, 89f);
|
||
|
orbitYaw += orbitalVelocity.y * deltaTime;
|
||
|
orbitalVelocity = Vector3.SmoothDamp(orbitalVelocity, Vector3.zero, ref orbitalVelocitySmoothDampVelocity, 0.25f, 2880f, deltaTime);
|
||
|
if (orbitDragCount > 0)
|
||
|
{
|
||
|
orbitalVelocity = Vector3.zero;
|
||
|
orbitalVelocitySmoothDampVelocity = Vector3.zero;
|
||
|
}
|
||
|
pan += panVelocity * deltaTime;
|
||
|
panVelocity = Vector2.SmoothDamp(panVelocity, Vector2.zero, ref panVelocitySmoothDampVelocity, 0.25f, 100f, deltaTime);
|
||
|
if (panDragCount > 0)
|
||
|
{
|
||
|
panVelocity = Vector2.zero;
|
||
|
panVelocitySmoothDampVelocity = Vector2.zero;
|
||
|
}
|
||
|
Quaternion quaternion = Quaternion.Euler(orbitPitch, orbitYaw, 0f);
|
||
|
cameraRigController.transform.forward = quaternion * Vector3.forward;
|
||
|
Vector3 forward = cameraRigController.transform.forward;
|
||
|
Vector3 position = pivotPoint + forward * (0f - Mathf.LerpUnclamped(minDistance, maxDistance, zoom)) + cameraRigController.transform.up * pan.y + cameraRigController.transform.right * pan.x;
|
||
|
cameraRigController.transform.position = position;
|
||
|
}
|
||
|
|
||
|
public void SetAnglesForCharacterThumbnailForSeconds(float time, bool setZoom = false)
|
||
|
{
|
||
|
SetAnglesForCharacterThumbnail(setZoom);
|
||
|
float t = time;
|
||
|
Action func = null;
|
||
|
func = delegate
|
||
|
{
|
||
|
t -= (useUnscaledTime ? Time.fixedUnscaledDeltaTime : Time.deltaTime);
|
||
|
if ((bool)this)
|
||
|
{
|
||
|
SetAnglesForCharacterThumbnail(setZoom);
|
||
|
}
|
||
|
if (t <= 0f)
|
||
|
{
|
||
|
RoR2Application.onUpdate -= func;
|
||
|
}
|
||
|
};
|
||
|
RoR2Application.onUpdate += func;
|
||
|
}
|
||
|
|
||
|
public void SetAnglesForCharacterThumbnail(bool setZoom = false)
|
||
|
{
|
||
|
if ((bool)modelInstance)
|
||
|
{
|
||
|
CameraFramingCalculator cameraFramingCalculator = new CameraFramingCalculator(modelInstance);
|
||
|
cameraFramingCalculator.GetCharacterThumbnailPosition(fov);
|
||
|
pivotPoint = cameraFramingCalculator.outputPivotPoint;
|
||
|
minDistance = cameraFramingCalculator.outputMinDistance;
|
||
|
maxDistance = cameraFramingCalculator.outputMaxDistance;
|
||
|
ResetOrbitAndPan();
|
||
|
Vector3 eulerAngles = cameraFramingCalculator.outputCameraRotation.eulerAngles;
|
||
|
orbitPitch = eulerAngles.x;
|
||
|
orbitYaw = eulerAngles.y;
|
||
|
if (setZoom)
|
||
|
{
|
||
|
zoom = Util.Remap(Vector3.Distance(cameraFramingCalculator.outputCameraPosition, cameraFramingCalculator.outputPivotPoint), minDistance, maxDistance, 0f, 1f);
|
||
|
desiredZoom = zoom;
|
||
|
}
|
||
|
zoomVelocity = 0f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void OnBeginDrag(PointerEventData eventData)
|
||
|
{
|
||
|
if (eventData.button == PointerEventData.InputButton.Right)
|
||
|
{
|
||
|
orbitDragCount++;
|
||
|
if (orbitDragCount == 1)
|
||
|
{
|
||
|
orbitDragPoint = eventData.pressPosition;
|
||
|
}
|
||
|
}
|
||
|
else if (eventData.button == PointerEventData.InputButton.Left)
|
||
|
{
|
||
|
panDragCount++;
|
||
|
if (panDragCount == 1)
|
||
|
{
|
||
|
panDragPoint = eventData.pressPosition;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void OnEndDrag(PointerEventData eventData)
|
||
|
{
|
||
|
if (eventData.button == PointerEventData.InputButton.Right)
|
||
|
{
|
||
|
orbitDragCount--;
|
||
|
}
|
||
|
else if (eventData.button == PointerEventData.InputButton.Left)
|
||
|
{
|
||
|
panDragCount--;
|
||
|
}
|
||
|
OnDrag(eventData);
|
||
|
}
|
||
|
|
||
|
public void OnDrag(PointerEventData eventData)
|
||
|
{
|
||
|
float unscaledDeltaTime = Time.unscaledDeltaTime;
|
||
|
if (eventData.button == PointerEventData.InputButton.Right)
|
||
|
{
|
||
|
Vector2 vector = eventData.position - orbitDragPoint;
|
||
|
orbitDragPoint = eventData.position;
|
||
|
float num = 0.5f / unscaledDeltaTime;
|
||
|
orbitalVelocity = new Vector3((0f - vector.y) * num * 0.5f, vector.x * num, 0f);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Vector2 vector2 = eventData.position - panDragPoint;
|
||
|
panDragPoint = eventData.position;
|
||
|
float num2 = -0.01f;
|
||
|
panVelocity = vector2 * num2 / unscaledDeltaTime;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void OnScroll(PointerEventData eventData)
|
||
|
{
|
||
|
desiredZoom = Mathf.Clamp01(desiredZoom + eventData.scrollDelta.y * -0.05f);
|
||
|
}
|
||
|
}
|