using UnityEngine;
using UnityEditor;
public class SetPivot : EditorWindow {
Vector3 p; //피봇 값 -1..1, 메쉬 바운드들로부터 계산됨
Vector3 last_p; //최근에 사용했던 피벗
GameObject obj; //Hierarchy 창에서 선택된 오브젝트
MeshFilter meshFilter; //선택된 오브젝트 메쉬 필터
Mesh mesh; //선택된 오브젝트 메쉬
Collider col; //선택된 오브젝트 콜라이더
bool pivotUnchanged; //메쉬 복사본을 인스턴트 할 때 결정
[MenuItem ("GameObject/Set Pivot")] //게임 오브젝트 메뉴에서 피벗 설정 메뉴 항목을 배치하고 설정
static void Init () {
SetPivot window = (SetPivot)EditorWindow.GetWindow (typeof (SetPivot));
window.RecognizeSelectedObject(); //클래스 인스턴스에 RecognizeSelectedObject를 호출하여 변수를 초기화
window.Show ();
}
void OnGUI() {
if(obj) {
if(mesh) {
p.x = EditorGUILayout.Slider("X", p.x, -1.0f, 1.0f);
p.y = EditorGUILayout.Slider("Y", p.y, -1.0f, 1.0f);
p.z = EditorGUILayout.Slider("Z", p.z, -1.0f, 1.0f);
if(p != last_p) { //세 개의 슬라이더 중 하나에서 사용자의 입력을 감지
//사용자가 피벗을 변경하는 경우에만 메쉬의 인스턴스를 생성
if(pivotUnchanged) mesh = meshFilter.mesh; pivotUnchanged = false;
UpdatePivot();
last_p = p;
}
if(GUILayout.Button("Center")) { //메시 경계의 중심으로 피벗 설정
//사용자가 피벗을 변경하는 경우에만 메쉬의 인스턴스를 생성
if(pivotUnchanged) mesh = meshFilter.mesh; pivotUnchanged = false;
p = Vector3.zero;
UpdatePivot();
last_p = p;
}
GUILayout.Label("Bounds " + mesh.bounds.ToString());
} else {
GUILayout.Label("Selected object does not have a Mesh specified.");
}
} else {
GUILayout.Label("No object selected in Hierarchy.");
}
}
//특정 방향으로 변환위치를 이동하여 피벗을 이동
void UpdatePivot() {
Vector3 diff = Vector3.Scale(mesh.bounds.extents, last_p - p); //서로 다른 위치 차이 값을 계산
obj.transform.position -= Vector3.Scale(diff, obj.transform.localScale); //localScale을 고려하여 객체의 위치를 이동
//모든 꼭지점을 반복 처리하고 대상물 위치 이동의 반대 방향으로 이동
Vector3[] verts = mesh.vertices;
for(int i=0; i<verts.Length; i++) {
verts[i] += diff;
}
mesh.vertices = verts; //메쉬에 다시 정점 배열을 할당
mesh.RecalculateBounds(); //렌더링을 위해서 메쉬의 경계를 재계산
//단, 변환 위치가 수정될 때 특정 콜라이더을의 'Center' 매개 변수를 조절해야 함
if(col) {
if(col is BoxCollider) {
((BoxCollider) col).center += diff;
} else if(col is CapsuleCollider) {
((CapsuleCollider) col).center += diff;
} else if(col is SphereCollider) {
((SphereCollider) col).center += diff;
}
}
}
void UpdatePivotVector() {
Bounds b = mesh.bounds;
Vector3 offset = -1 * b.center;
p = last_p = new Vector3(offset.x / b.extents.x, offset.y / b.extents.y, offset.z / b.extents.z);
}
//선택 변경 알림이 뜨면 새로운 오브젝트에 대한 변수 및 참조를 다시 계산
void OnSelectionChange() {
RecognizeSelectedObject();
}
//선택한 오브젝트 및 해당 구성 요소에 대한 참조를 수집하고
//객체가 메쉬가 지정된 경우 피벗 벡터를 업데이트
void RecognizeSelectedObject() {
Transform t = Selection.activeTransform;
obj = t ? t.gameObject : null;
if(obj) {
meshFilter = obj.GetComponent(typeof(MeshFilter)) as MeshFilter;
mesh = meshFilter ? meshFilter.sharedMesh : null;
if(mesh)
UpdatePivotVector();
col = obj.GetComponent(typeof(Collider)) as Collider;
pivotUnchanged = true;
} else {
mesh = null;
}
}
}
'UNITY 3D' 카테고리의 다른 글
애니메이션 되감기 (거꾸로 재생) (0) | 2015.08.27 |
---|