오브젝트 스냅 기능 #200
@@ -37,7 +37,7 @@ namespace Studio.RuntimeGizmo
|
||||
|
||||
objectMoveGizmo.Gizmo.SetEnabled(false);
|
||||
objectMoveGizmo.Gizmo.MoveGizmo.SetSnapEnabled(false);
|
||||
objectMoveGizmo.Gizmo.MoveGizmo.SetVertexSnapEnabled(false);
|
||||
objectMoveGizmo.Gizmo.MoveGizmo.SetVertexSnapEnabled(true);
|
||||
objectRotationGizmo.Gizmo.SetEnabled(false);
|
||||
objectScaleGizmo.Gizmo.SetEnabled(false);
|
||||
objectUniversalGizmo.Gizmo.SetEnabled(false);
|
||||
@@ -109,6 +109,7 @@ namespace Studio.RuntimeGizmo
|
||||
selectedObjects.Clear();
|
||||
selectedObjects.AddRange(objects);
|
||||
objectMoveGizmo.SetTargetObjects(selectedObjects);
|
||||
objectMoveGizmo.Gizmo.MoveGizmo.SetVertexSnapTargetObjects(selectedObjects);
|
||||
objectRotationGizmo.SetTargetObjects(selectedObjects);
|
||||
objectScaleGizmo.SetTargetObjects(selectedObjects);
|
||||
objectUniversalGizmo.SetTargetObjects(selectedObjects);
|
||||
|
||||
@@ -106,14 +106,13 @@ namespace RTG
|
||||
bool foundPoint = false;
|
||||
foreach (var srcObject in gameObjects)
|
||||
{
|
||||
Mesh mesh = srcObject.GetMesh();
|
||||
if (mesh != null)
|
||||
foreach (var (mesh, transform) in srcObject.GetAllMeshWithTransform())
|
||||
{
|
||||
MeshVertexChunkCollection meshVChunkCollection = MeshVertexChunkCollectionDb.Get[mesh];
|
||||
if (meshVChunkCollection == null)
|
||||
continue;
|
||||
|
||||
Matrix4x4 worldMtx = srcObject.transform.localToWorldMatrix;
|
||||
Matrix4x4 worldMtx = transform.localToWorldMatrix;
|
||||
List<MeshVertexChunk> testChunks = meshVChunkCollection.GetWorldChunksHoveredByPoint(inputDeviceScreenPt, worldMtx, focusCamera);
|
||||
if (testChunks.Count == 0)
|
||||
{
|
||||
@@ -126,7 +125,9 @@ namespace RTG
|
||||
{
|
||||
Vector3 worldVert = chunk.GetWorldVertClosestToScreenPt(inputDeviceScreenPt, worldMtx, focusCamera);
|
||||
Vector2 screenVert = focusCamera.WorldToScreenPoint(worldVert);
|
||||
float distSqr = (inputDeviceScreenPt - screenVert).sqrMagnitude;
|
||||
Vector2 screenVert2D = new Vector2(screenVert.x, screenVert.y);
|
||||
float distSqr = (inputDeviceScreenPt - screenVert2D).sqrMagnitude;
|
||||
|
||||
if (distSqr < minDistSqr)
|
||||
{
|
||||
minDistSqr = distSqr;
|
||||
@@ -135,27 +136,6 @@ namespace RTG
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OBB spriteWorldOBB = ObjectBounds.CalcSpriteWorldOBB(srcObject);
|
||||
if (spriteWorldOBB.IsValid)
|
||||
{
|
||||
List<Vector3> obbPoints = spriteWorldOBB.GetCenterAndCornerPoints();
|
||||
List<Vector2> screenPoints = focusCamera.ConvertWorldToScreenPoints(obbPoints);
|
||||
int closestPtIndex = Vector2Ex.GetPointClosestToPoint(screenPoints, inputDeviceScreenPt);
|
||||
if (closestPtIndex >= 0)
|
||||
{
|
||||
Vector2 closestPt = screenPoints[closestPtIndex];
|
||||
float distSqr = (inputDeviceScreenPt - closestPt).sqrMagnitude;
|
||||
if (distSqr < minDistSqr)
|
||||
{
|
||||
minDistSqr = distSqr;
|
||||
point = obbPoints[closestPtIndex];
|
||||
foundPoint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return foundPoint;
|
||||
|
||||
@@ -215,6 +215,25 @@ namespace RTG
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<(Mesh mesh, Transform transform)> GetAllMeshWithTransform(this GameObject root)
|
||||
{
|
||||
var result = new List<(Mesh, Transform)>();
|
||||
|
||||
foreach (var mf in root.GetComponentsInChildren<MeshFilter>(true))
|
||||
{
|
||||
if (mf.sharedMesh != null)
|
||||
result.Add((mf.sharedMesh, mf.transform));
|
||||
}
|
||||
|
||||
foreach (var smr in root.GetComponentsInChildren<SkinnedMeshRenderer>(true))
|
||||
{
|
||||
if (smr.sharedMesh != null)
|
||||
result.Add((smr.sharedMesh, smr.transform));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Renderer GetMeshRenderer(this GameObject gameObject)
|
||||
{
|
||||
MeshRenderer meshRenderer = gameObject.GetComponent<MeshRenderer>();
|
||||
|
||||
@@ -318,82 +318,6 @@ namespace Studio.AssetTool
|
||||
}
|
||||
CanvasManager.instance.GetCanvas<Canvas_Popup>().panel_dynamicobjectinfo.OnTransformChanged(objectsToAlign.Select(renderObject => renderObject.gameObject).ToList());
|
||||
}
|
||||
public void VertexSnap()
|
||||
{
|
||||
if (selectedRenderObjects.Count != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//가장 가까운 오브젝트에 붙여준다.
|
||||
//Transform.position이 가깝다고 오브젝트 사이 기리가 꼭 가장 가까운 것은 아니기 때문에
|
||||
//오버랩 박스에 충돌되는 모든 오브젝트의 버텍스로 KDTree를 구성해 볼까 하다가 관두었다.
|
||||
float minDist = float.MaxValue;
|
||||
CustomAssetRenderObject fromObject = selectedRenderObjects[0];
|
||||
CustomAssetRenderObject toObject = null;
|
||||
Bounds fromBounds = fromObject.GetBounds();
|
||||
Collider[] colliders = Physics.OverlapBox(fromBounds.center, fromBounds.size * 2.0f);
|
||||
foreach (Collider collider in colliders)
|
||||
{
|
||||
if (collider.gameObject == fromObject.gameObject) continue;
|
||||
CustomAssetRenderObject otherObject = collider.gameObject.GetComponent<CustomAssetRenderObject>();
|
||||
if (otherObject != null)
|
||||
{
|
||||
float dist = Vector3.Magnitude(fromObject.transform.position - otherObject.transform.position);
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
toObject = otherObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toObject != null)
|
||||
{
|
||||
//선택된 오브젝트의 ConvexHull 버텍스 점을 계산해준다.
|
||||
//이는 iteration하는 버텍스 수를 줄이기 위해 해주며,
|
||||
//만약 선택된 오브젝트도 TDTree로 Nearest 포인트 탐지할 경우 toObject의 센터에 가장 가까운 포인트만 탐지되기 때문에 가장 가까운 버텍스 점이 골라지지 않는 경우가 있다.
|
||||
List<Vector3> verts = new List<Vector3>();
|
||||
List<int> tris = new List<int>();
|
||||
List<Vector3> normals = new List<Vector3>();
|
||||
convexHullCalculator.GenerateHull(fromObject.GetRenderObjectVertices(), false, ref verts, ref tris, ref normals);
|
||||
KDTree toTree = toObject.GetVertexPointKDTree();
|
||||
Vector3 nearestPoint = Vector3.zero;
|
||||
Vector3 snapPoint = Vector3.zero;
|
||||
float minDistance = float.MaxValue;
|
||||
for (int i = 0; i < verts.Count; i++)
|
||||
{
|
||||
Vector3 ptNearest = verts[i];
|
||||
Vector3 ptSnap = toTree.FindNearest(ptNearest);
|
||||
float tempDist = Vector3.Magnitude(ptSnap - ptNearest);
|
||||
if (tempDist < minDistance)
|
||||
{
|
||||
minDistance = tempDist;
|
||||
nearestPoint = ptNearest;
|
||||
snapPoint = ptSnap;
|
||||
}
|
||||
}
|
||||
//Vector3 direction = snapPoint - nearestPoint;
|
||||
//fromObject.transform.position += direction;
|
||||
List<Vector3> dir = new List<Vector3>() { snapPoint - nearestPoint };
|
||||
if (dir[0].magnitude < 0.5f)
|
||||
{
|
||||
fromObject.transform.position += dir[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
ActionCommand command = new ActionCommand(
|
||||
() =>
|
||||
{
|
||||
fromObject.transform.position += dir[0];
|
||||
},
|
||||
() =>
|
||||
{
|
||||
fromObject.transform.position -= dir[0];
|
||||
});
|
||||
CommandInvoker.instance.Invoke(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InputHandler myHandler;
|
||||
|
||||
public void StatusEnterEvent()
|
||||
@@ -422,7 +346,6 @@ namespace Studio.AssetTool
|
||||
downKeyActions.Add(KeyCode.E, () => SetGizmoChangedCommand(new ActivateScaleGizmoCommand()));
|
||||
downKeyActions.Add(KeyCode.R, () => SetGizmoChangedCommand(new ResetGizmoCommand()));
|
||||
downKeyActions.Add(KeyCode.Delete, () => CommandInvoker.instance.Invoke(new RemoveSelectObjectCommand()));
|
||||
getKeyActions.Add(KeyCode.V, VertexSnap);
|
||||
|
||||
var shortcutTable = new Dictionary<KeyCode, Dictionary<KeyCode, Action>>();
|
||||
#if UNITY_EDITOR
|
||||
|
||||
Reference in New Issue
Block a user