void Initialize(CHotSpot oHotSpot, bool bMiddleClickOp) { _oHotSpot = oHotSpot; _bMiddleClickOp = bMiddleClickOp; _eEditMode = CGame.INSTANCE._oCursor._EditMode; // Our gizmo mode is the mode of the cursor edit mode at startup. gameObject.name = "Gizmo-" + _eEditMode.ToString(); //=== Set the initializing gizmo the position and rotation of the hotspot. We have to move/rotate both at every frame === transform.parent = null; // Note that we are NOT a child of our owning hotspot... transform.position = _oHotSpot.transform.position; if (_eEditMode != EEditMode.Move) // Only start at the object's current location if we're rotate or scale. we always move with axis-aliged gizmo transform.rotation = _oHotSpot.transform.rotation; transform.localScale = new Vector3(CCursor.C_GizmoScale, CCursor.C_GizmoScale, CCursor.C_GizmoScale); // Gizmo is always drawn at the default scale regardless of hotspot scaling. if (_eEditMode == EEditMode.Rotate) // Magnify the rotation cursor a given ratio as it frequently needs a bigger size for easy user manipulation transform.localScale *= CCursor.C_GizmoScale_RotationMultiplier; //=== Handling of special 'hidden helper object' mode = Hide gizmo and immediately begin move opeation along y,z axis === if (CGame.INSTANCE._bGameModeBasicInteractions) { Renderer[] aRend = transform.GetComponentsInChildren<Renderer>(); //###IMPROVE? Instead of hiding all gizmo elements, would it be too tough to just not instantiate its prefab?? foreach (Renderer oRend in aRend) oRend.enabled = false; _eModeGizmo = EModeGizmo.S2_UserDraggingGizmoPart; // Direct fast-track to immediately drag gizmo... GizmoTransform_Begin(true); // ... by forcing a move operation on YZ plane } else { _eModeGizmo = EModeGizmo.S1_WaitingLeftClickGizmoPart; } }
public void OnUpdateGizmo() { // Sent by the global cursor from 'Update()' to enable gizmo interactivity by trapping mouse events on various gizmo colliders //=== Potentially invert the gizmo along x,y,z so that it is always pointing toward the camera (Rotation gizmo is 3D symmetrical and never needs inversion === if (_eEditMode != EEditMode.Rotate) { Vector3 vecGizmoToCam = Camera.main.transform.position - transform.position; float nAngleForward = Vector3.Angle(vecGizmoToCam, transform.forward); float nAngleRight = Vector3.Angle(vecGizmoToCam, transform.right); float nAngleUp = Vector3.Angle(vecGizmoToCam, transform.up); transform.localScale = new Vector3(nAngleRight < 90 ? CCursor.C_GizmoScale : -CCursor.C_GizmoScale, nAngleUp < 90 ? CCursor.C_GizmoScale : -CCursor.C_GizmoScale, nAngleForward < 90 ? CCursor.C_GizmoScale : -CCursor.C_GizmoScale); } //=== Process the gizmo finite state machine as progressed by left mouse click === switch (_eModeGizmo) { case EModeGizmo.S1_WaitingLeftClickGizmoPart: // User has completed the left mouse up & down that resulted in hotspot being activated and gizmo shown. We now wait until left mouse button on a gizmo part to begin gizmo moving/rotating/scaling the object _oRayHit_LayerGizmo = CGame.INSTANCE._oCursor.GetHitOnLayerAtMousePos(CCursor.C_LayerMask_Gizmo); // Obtain the user's hit on the gizmo collider layers CGizmo oGizmo = FindGizmoFromCollider(_oRayHit_LayerGizmo.collider); //... See if the user clicked on a part of our gizmo... if (oGizmo != null) { if (_oHighlightedGizmoCollider != _oRayHit_LayerGizmo.collider) { if (_oHighlightedGizmoCollider) { Color oColorGizmoCollider = _oHighlightedGizmoCollider.GetComponent<Renderer>().sharedMaterial.color; oColorGizmoCollider.a = oColorGizmoCollider.a / C_GizmoColliderHighlight; _oHighlightedGizmoCollider.GetComponent<Renderer>().sharedMaterial.color = oColorGizmoCollider; } _oHighlightedGizmoCollider = _oRayHit_LayerGizmo.collider; if (_oHighlightedGizmoCollider) { Color oColorGizmoCollider = _oHighlightedGizmoCollider.GetComponent<Renderer>().sharedMaterial.color; oColorGizmoCollider.a = oColorGizmoCollider.a * C_GizmoColliderHighlight; _oHighlightedGizmoCollider.GetComponent<Renderer>().sharedMaterial.color = oColorGizmoCollider; } } } if (Input.GetMouseButtonDown(0)) { // Trap left mouse down... if (oGizmo != null) { //... There should only be one gizmo globally but throw if we find another one! if (oGizmo != this) CUtility.ThrowException("ERROR: Found a gizmo collider that wasn't 'this' Gizmo"); // If this occurs there is a serious error in the flow that creates CGizmo objects and another one of is created & never removed on screen... dual creation during the same event?? GizmoTransform_Begin(); _eModeGizmo = EModeGizmo.S2_UserDraggingGizmoPart; } } break; case EModeGizmo.S2_UserDraggingGizmoPart: // The user is now left-clicking one of the three x,y,z colliders for the move or rotate gizmo for the currently editing Bone. While the user keeps LMB down we move/rotate the selected Bone... if (Input.GetMouseButton(0) || Input.GetMouseButton(2)) { // User is still holding LMB down on a collider of the current gizmo: Continue moving/rotating current Bone on previously select x,y,z axis GizmoTransform_Update(); } else { // User is no longer holding LMB: We are done transforming this x,y,z and we return to looking for the next gizmo x,y,z collider for further action GizmoTransform_End(); _eModeGizmo = EModeGizmo.S1_WaitingLeftClickGizmoPart; } break; } }