127 lines
4.1 KiB
C#
127 lines
4.1 KiB
C#
#if UNITY_EDITOR
|
|
using UnityEngine;
|
|
using VRC.Dynamics;
|
|
|
|
namespace VRC.SDK3.Dynamics.PhysBone
|
|
{
|
|
/// <summary>
|
|
/// Internal component that makes it possible to grab and pose PhysBones for testing in an SDK project while it's
|
|
/// in play mode.
|
|
/// </summary>
|
|
// This component is intentionally duplicated across SDKs instead of existing in the base SDK only, to address
|
|
// compatibility issues with community made tooling.
|
|
[AddComponentMenu("")]
|
|
public class PhysBoneGrabHelper : MonoBehaviour
|
|
{
|
|
Camera currentCamera;
|
|
|
|
void Update()
|
|
{
|
|
currentCamera = FindCamera();
|
|
|
|
//Process mouse input
|
|
SetMouseDown(Input.GetMouseButton(0));
|
|
if (mouseIsDown && Input.GetMouseButtonDown(1))
|
|
{
|
|
if(grab != null)
|
|
{
|
|
PhysBoneManager.Inst.ReleaseGrab(grab, true);
|
|
grab = null;
|
|
}
|
|
}
|
|
UpdateGrab();
|
|
}
|
|
|
|
Camera FindCamera()
|
|
{
|
|
//Get target display
|
|
int targetDisplay = Display.activeEditorGameViewTarget;
|
|
|
|
//Find camera with matching target
|
|
Camera result = null;
|
|
var cameras = Camera.allCameras;
|
|
foreach(var camera in cameras) //Get the last active camera
|
|
{
|
|
if (camera.isActiveAndEnabled &&
|
|
camera.cameraType == CameraType.Game &&
|
|
camera.targetDisplay == targetDisplay &&
|
|
camera.targetTexture == null
|
|
)
|
|
result = camera;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool mouseIsDown = false;
|
|
PhysBoneManager.Grab grab;
|
|
Vector3 grabOriginLocal;
|
|
void SetMouseDown(bool state)
|
|
{
|
|
if (state == mouseIsDown)
|
|
return;
|
|
|
|
mouseIsDown = state;
|
|
|
|
if (mouseIsDown && currentCamera != null)
|
|
{
|
|
var localPlayer = VRC.SDKBase.Networking.LocalPlayer;
|
|
var playerId = localPlayer != null && localPlayer.IsValid() ? localPlayer.playerId : -1;
|
|
var ray = GetMouseRay();
|
|
grab = PhysBoneManager.Inst.AttemptGrab(playerId, ray, out Vector3 grabOrigin);
|
|
if (grab != null)
|
|
{
|
|
grabOriginLocal = currentCamera.transform.InverseTransformPoint(grabOrigin);
|
|
#if VERBOSE_LOGGING
|
|
Debug.Log($"Grabbing - Chain:{grab.chainId} Bone:{grab.bone}");
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (grab != null)
|
|
{
|
|
PhysBoneManager.Inst.ReleaseGrab(grab);
|
|
grab = null;
|
|
}
|
|
}
|
|
}
|
|
Ray GetMouseRay()
|
|
{
|
|
return currentCamera.ScreenPointToRay(Input.mousePosition);
|
|
}
|
|
void UpdateGrab()
|
|
{
|
|
if(currentCamera == null)
|
|
return;
|
|
|
|
if (grab != null)
|
|
{
|
|
Vector3 curGrabOrigin = currentCamera.transform.TransformPoint(grabOriginLocal);
|
|
var ray = GetMouseRay();
|
|
Vector3 hit;
|
|
if (PlaneLineIntersection(curGrabOrigin, -currentCamera.transform.forward, ray.origin, ray.origin + ray.direction * 1000f, out hit))
|
|
{
|
|
grab.GlobalPosition = hit + grab.LocalOffset;
|
|
}
|
|
}
|
|
}
|
|
public static bool PlaneLineIntersection(Vector3 planeOrigin, Vector3 planeNormal, Vector3 lineA, Vector3 lineB, out Vector3 hit)
|
|
{
|
|
float delta;
|
|
|
|
//Make sure the line is not parallel
|
|
delta = Vector3.Dot(planeNormal, (lineB - lineA) - planeOrigin);
|
|
if (delta == 0.0f)
|
|
{
|
|
hit = Vector3.zero;
|
|
return false;
|
|
}
|
|
|
|
//Find the delta
|
|
delta = Vector3.Dot(planeNormal, lineA - planeOrigin) / delta;
|
|
hit = lineA + ((lineB - lineA) * -delta);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
#endif |