Tanoda
pb_SceneCamera.cs
Go to the documentation of this file.
1
8// #define CONTROLLER
9// #define USE_DELTA_TIME
10
11using System;
12using UnityEngine;
13using System.Collections;
15
16namespace GILES
17{
22 [RequireComponent(typeof(Camera))]
23 public class pb_SceneCamera : MonoBehaviour
24 {
25 private static pb_SceneCamera instance;
26
27 private pb_SceneEditor editor { get { return pb_InputManager.GetCurrentEditor(); } }
28
29 public delegate void OnCameraMoveEvent(pb_SceneCamera cam);
31
32 public delegate void OnCameraFinishMoveEvent(pb_SceneCamera cam);
34
35 public bool ModelViewerCamOnly = false;
36 public bool ModelEditorCamOnly = false;
37
39 {
40 if(instance == null)
41 {
42 Debug.LogWarning("No pb_SceneCamera found, but someone is trying to subscribe to events!");
43 return;
44 }
45
46 if(instance.OnCameraMove == null)
47 instance.OnCameraMove = del;
48 else
49 instance.OnCameraMove += del;
50 }
51
52 public ViewTool cameraState { get; private set; }
53
54 public Texture2D PanCursor;
55 public Texture2D OrbitCursor;
56 public Texture2D DollyCursor;
57 public Texture2D LookCursor;
58 private Texture2D currentCursor;
59
60 const int CURSOR_ICON_SIZE = 64;
61
62 const string INPUT_MOUSE_SCROLLWHEEL = "Mouse ScrollWheel";
63 const string INPUT_MOUSE_X = "Mouse X";
64 const string INPUT_MOUSE_Y = "Mouse Y";
65
66 const int LEFT_MOUSE = 0;
67 const int RIGHT_MOUSE = 1;
68 const int MIDDLE_MOUSE = 2;
69
70 const float MIN_CAM_DISTANCE = 0.02f;
71 const float MAX_CAM_DISTANCE = 100f;
72
73 #if USE_DELTA_TIME
74 public float moveSpeed = 15f;
75 public float lookSpeed = 200f;
76 public float orbitSpeed = 200f;
77 public float scrollModifier = 100f;
78 public float zoomSpeed = .05f;
79 #else
80 public float moveSpeed = 15f;
81 public float lookSpeed = 5f;
82 public float orbitSpeed = 7f;
83 public float scrollModifier = 100f;
84 public float zoomSpeed = .1f;
85 #endif
86
87 private bool eatMouse = false;
88
89 private Camera cam;
90
91 private Vector3 pivot = Vector3.zero;
92 public Vector3 GetPivot() { return pivot; }
93 private float distanceToCamera = 10f;
94
95 private Vector3 prev_mousePosition = Vector3.zero;
96
97 private Rect mouseCursorRect = new Rect(0,0,CURSOR_ICON_SIZE,CURSOR_ICON_SIZE);
98 private Rect screenCenterRect = new Rect(0,0,CURSOR_ICON_SIZE,CURSOR_ICON_SIZE);
99
100 private bool currentActionValid = true;
101
102 Vector3 CamTarget()
103 {
104 return transform.position + transform.forward * distanceToCamera;
105 }
106
107 void Awake()
108 {
109 instance = this;
110 }
111
112 void Start()
113 {
114 pb_InputManager.AddMouseInUseDelegate( IsUsingMouse );
115 pb_InputManager.AddKeyInUseDelegate( IsUsingKey );
116 pb_InputManager.instance.currentEditor.skipOnGUI = ModelEditorCamOnly;
117
118 cam = GetComponent<Camera>();
119 distanceToCamera = Vector3.Distance(pivot, Camera.main.transform.position);
120 }
121
122 public GameObject plane;
123
124 void OnGUI()
125 {
126 float screenHeight = Screen.height;
127
128 mouseCursorRect.x = Input.mousePosition.x - 16;
129 mouseCursorRect.y = (screenHeight - Input.mousePosition.y) - 16;
130
131 screenCenterRect.x = Screen.width/2-32;
132 screenCenterRect.y = screenHeight/2-32;
133
134 Cursor.visible = cameraState == ViewTool.None;
135
136 if(cameraState != ViewTool.None)
137 {
138 switch(cameraState)
139 {
140 case ViewTool.Orbit:
141 GUI.Label(mouseCursorRect, OrbitCursor);
142 cam.orthographic = false;
143 break;
144 case ViewTool.Pan:
145 GUI.Label(mouseCursorRect, PanCursor);
146 break;
147 case ViewTool.Dolly:
148 GUI.Label(mouseCursorRect, DollyCursor);
149 cam.orthographic = false;
150 break;
151 case ViewTool.Look:
152 GUI.Label(mouseCursorRect, LookCursor);
153 cam.orthographic = false;
154 break;
155 }
156 }
157 }
158
162 public bool IsUsingMouse(Vector2 mousePosition)
163 {
164 return cameraState != ViewTool.None || eatMouse || Input.GetKey(KeyCode.LeftAlt);
165 }
166
167 public bool IsUsingKey()
168 {
169 return Input.GetKey(KeyCode.LeftAlt);
170 }
171
172 bool CheckMouseOverGUI()
173 {
174 return EventSystem.current == null || !EventSystem.current.IsPointerOverGameObject();
175 }
176
177 public void GoOrtoX()
178 {
179 cam.orthographic = true;
180 cam.transform.eulerAngles = Vector3.zero;
181
182 try
183 {
185 }
186 catch (Exception)
187 {
188 Focus(Vector3.zero, 2);
189 cam.orthographicSize = 2.0f;
190 }
191 }
192
193 public void GoOrtoY()
194 {
195 cam.orthographic = true;
196 cam.transform.eulerAngles = Vector3.right * 90;
197 cam.transform.eulerAngles += Vector3.up * 270;
198
199 try
200 {
202 }
203 catch (Exception)
204 {
205 Focus(Vector3.zero, 2);
206 cam.orthographicSize = 2.0f;
207 }
208 }
209
210 public void GoOrtoZ()
211 {
212 cam.orthographic = true;
213 cam.transform.eulerAngles = Vector3.up * 270;
214
215 try
216 {
218 }
219 catch (Exception)
220 {
221 Focus(Vector3.zero, 2);
222 cam.orthographicSize = 2.0f;
223 }
224 }
225
226 void LateUpdate()
227 {
228
229 if(Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1) || Input.GetMouseButtonUp(2))
230 {
231 if(cameraState != ViewTool.None && OnCameraFinishMove != null)
232 OnCameraFinishMove(this);
233
234 currentActionValid = true;
235 eatMouse = false;
236 }
237 else
238 if(Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2))
239 {
240 currentActionValid = CheckMouseOverGUI();
241 }
242 else
243 {
244 if(transform.hasChanged && OnCameraMove != null)
245 {
246 OnCameraMove(this);
247 transform.hasChanged = false;
248 }
249 }
250
251 cameraState = ViewTool.None;
252
256 if(zooming)
257 {
258 transform.position = Vector3.Lerp(previousPosition, targetPosition, (zoomProgress += Time.deltaTime)/zoomSpeed);
259 if( Vector3.Distance(transform.position, targetPosition) < .1f) zooming = false;
260 }
261
262 if( (Input.GetAxis(INPUT_MOUSE_SCROLLWHEEL) != 0f || (Input.GetMouseButton(RIGHT_MOUSE) && Input.GetKey(KeyCode.LeftAlt))) && CheckMouseOverGUI())
263 {
264 var view = cam.ScreenToViewportPoint(Input.mousePosition);
265 var isOutside = view.x < 0 || view.x > 1 || view.y < 0 || view.y > 1;
266 if (isOutside)
267 {
268 return;
269 }
270 float delta = Input.GetAxis(INPUT_MOUSE_SCROLLWHEEL);
271
272 if( Mathf.Approximately(delta, 0f) )
273 {
274 cameraState = ViewTool.Dolly;
275 delta = pb_HandleUtility.CalcSignedMouseDelta(Input.mousePosition, prev_mousePosition);
276 }
277
278 if (cam.orthographic)
279 {
280 cam.orthographicSize -= delta;
281 cam.orthographicSize = Mathf.Clamp(cam.orthographicSize, MIN_CAM_DISTANCE, MAX_CAM_DISTANCE);
282 }
283 else
284 {
285 distanceToCamera -= delta * (distanceToCamera / MAX_CAM_DISTANCE) * scrollModifier;
286 distanceToCamera = Mathf.Clamp(distanceToCamera, MIN_CAM_DISTANCE, MAX_CAM_DISTANCE);
287 transform.position = transform.localRotation * (Vector3.forward * -distanceToCamera) + pivot;
288 }
289 }
290
291 bool viewTool = editor == null || editor.EnableCameraControls();
292
296 if( !currentActionValid || (viewTool
297 #if !CONTROLLER
298 && !Input.GetMouseButton(LEFT_MOUSE)
299 && !Input.GetMouseButton(RIGHT_MOUSE)
300 && !Input.GetMouseButton(MIDDLE_MOUSE)
301 && !Input.GetKey(KeyCode.LeftAlt)
302 #endif
303 ) )
304 {
305 Rect screen = new Rect(0,0,Screen.width,Screen.height);
306
307 if(screen.Contains(Input.mousePosition))
308 prev_mousePosition = Input.mousePosition;
309
310 return;
311 }
312
316 if( Input.GetMouseButton(RIGHT_MOUSE) && !Input.GetKey(KeyCode.LeftAlt) )//|| Input.GetKey(KeyCode.LeftShift) )
317 {
318 cameraState = ViewTool.Look;
319
320 eatMouse = true;
321
322 // Rotation
323 float rot_x = Input.GetAxis(INPUT_MOUSE_X);
324 float rot_y = Input.GetAxis(INPUT_MOUSE_Y);
325
326 Vector3 eulerRotation = transform.localRotation.eulerAngles;
327
328 #if USE_DELTA_TIME
329 eulerRotation.x -= rot_y * lookSpeed * Time.deltaTime; // Invert Y axis
330 eulerRotation.y += rot_x * lookSpeed * Time.deltaTime;
331 #else
332 eulerRotation.x -= rot_y * lookSpeed;
333 eulerRotation.y += rot_x * lookSpeed;
334 #endif
335 eulerRotation.z = 0f;
336 transform.localRotation = Quaternion.Euler(eulerRotation);
337
338 // PositionHandle-- Always use delta time when flying
339 float speed = moveSpeed * Time.deltaTime;
340
341 transform.position += transform.forward * speed * Input.GetAxis("Vertical");
342 transform.position += transform.right * speed * Input.GetAxis("Horizontal");
343 try {
344 transform.position += transform.up * speed * Input.GetAxis("CameraUp");
345 } catch {
346 Debug.LogWarning("CameraUp input is not configured. Open \"Edit/Project Settings/Input\" and add an input named \"CameraUp\", mapping q and e to Negative and Positive buttons.");
347 }
348
349 pivot = transform.position + transform.forward * distanceToCamera;
350 }
351 else
355 if((ModelViewerCamOnly || Input.GetKey(KeyCode.LeftAlt)) && Input.GetMouseButton(LEFT_MOUSE))
356 {
357 cameraState = ViewTool.Orbit;
358
359 eatMouse = true;
360
361 float rot_x = Input.GetAxis(INPUT_MOUSE_X);
362 float rot_y = -Input.GetAxis(INPUT_MOUSE_Y);
363
364 Vector3 eulerRotation = transform.localRotation.eulerAngles;
365
366 if( (Mathf.Approximately(eulerRotation.x, 90f) && rot_y > 0f) ||
367 (Mathf.Approximately(eulerRotation.x, 270f) && rot_y < 0f) )
368 rot_y = 0f;
369
370 #if USE_DELTA_TIME
371 eulerRotation.x += rot_y * orbitSpeed * Time.deltaTime;
372 eulerRotation.y += rot_x * orbitSpeed * Time.deltaTime;
373 #else
374 eulerRotation.x += rot_y * orbitSpeed;
375 eulerRotation.y += rot_x * orbitSpeed;
376 #endif
377
378 eulerRotation.z = 0f;
379
380 transform.localRotation = Quaternion.Euler( eulerRotation );
381 transform.position = CalculateCameraPosition(pivot);
382 }
383 else
387 if(Input.GetMouseButton(MIDDLE_MOUSE) || (Input.GetMouseButton(LEFT_MOUSE) && viewTool ) )
388 {
389 cameraState = ViewTool.Pan;
390
391 Vector2 delta = Input.mousePosition - prev_mousePosition;
392
393 delta.x = ScreenToWorldDistance(delta.x, distanceToCamera);
394 delta.y = ScreenToWorldDistance(delta.y, distanceToCamera);
395
396 transform.position -= transform.right * delta.x;
397 transform.position -= transform.up * delta.y;
398
399 pivot = transform.position + transform.forward * distanceToCamera;
400 }
401
402 prev_mousePosition = Input.mousePosition;
403 }
404
405 Vector3 CalculateCameraPosition(Vector3 target)
406 {
407 return transform.localRotation * (Vector3.forward * -distanceToCamera) + target;
408 }
409
410 bool zooming = false;
411 float zoomProgress = 0f;
412 Vector3 previousPosition = Vector3.zero, targetPosition = Vector3.zero;
413
417 public static void Focus(Vector3 target)
418 {
419 instance.ZoomInternal(target, 10f);
420 }
421
422 public static void Focus(Vector3 target, float distance)
423 {
424 instance.ZoomInternal(target, distance);
425 }
426
427 public static void Focus(GameObject target)
428 {
429 instance.ZoomInternal(target);
430 }
431
432 private void ZoomInternal( Vector3 target, float distance )
433 {
434 pivot = target;
435 distanceToCamera = distance;
436 previousPosition = transform.position;
437 targetPosition = CalculateCameraPosition( pivot );
438 zoomProgress = 0f;
439 zooming = true;
440 }
441
445 private void ZoomInternal( GameObject target )
446 {
447 Vector3 center = target.transform.position;
448 Renderer renderer = target.GetComponent<Renderer>();
449 Bounds bounds = renderer != null ? renderer.bounds : new Bounds(center, Vector3.one * 10f);
450
451 distanceToCamera = pb_ObjectUtility.CalcMinDistanceToBounds(cam, bounds);
452 distanceToCamera += distanceToCamera;
453 center = bounds.center;
454
455 ZoomInternal( center, distanceToCamera );
456 }
457
458 private float ScreenToWorldDistance(float screenDistance, float distanceFromCamera)
459 {
460 Vector3 start = cam.ScreenToWorldPoint(Vector3.forward * distanceFromCamera);
461 Vector3 end = cam.ScreenToWorldPoint( new Vector3(screenDistance, 0f, distanceFromCamera));
462 return CopySign(Vector3.Distance(start, end), screenDistance);
463 }
464
468 private float CopySign(float x, float y)
469 {
470 if(x < 0f && y < 0f || x > 0f && y > 0f || x == 0f || y == 0f)
471 return x;
472 else
473 return -x;
474 }
475 }
476}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
static pb_SceneEditor GetCurrentEditor()
static void AddOnCameraMoveDelegate(OnCameraMoveEvent del)
float orbitSpeed
How fast the camera rotation adjusts.
OnCameraFinishMoveEvent OnCameraFinishMove
static void Focus(Vector3 target, float distance)
float scrollModifier
How fast the mouse scroll wheel affects distance from pivot.
delegate void OnCameraFinishMoveEvent(pb_SceneCamera cam)
bool IsUsingMouse(Vector2 mousePosition)
float moveSpeed
How fast the camera position moves.
OnCameraMoveEvent OnCameraMove
delegate void OnCameraMoveEvent(pb_SceneCamera cam)
float lookSpeed
How fast the camera rotation adjusts.
static void Focus(GameObject target)
static void Focus(Vector3 target)
virtual bool EnableCameraControls()
static GameObject activeGameObject
Definition: pb_Selection.cs:82
ViewTool
Definition: pb_Enum.cs:36