public ScaleInputMapping(RyneCamera camera, EditAxis axis, float speed = 1.0f) : base(camera) { Speed = speed; AddInput(new MouseAxisInput { Axis = new Float2(1, 0), Action = new InputScalingAction(new Float3(1, 0, 0), Speed) }); AddInput(new MouseAxisInput { Axis = new Float2(0, 1), Action = new InputScalingAction(new Float3(0, 1, 0), Speed) }); }
public TranslationInputMapping(RyneCamera camera, EditAxis axis, float speed = 1.0f) : base(camera) { Speed = speed; AddInput(new MouseAxisInput { Axis = new Float2(1, 0), Action = new InputMovementAction(new Float3(0.0f), Speed) }); AddInput(new MouseAxisInput { Axis = new Float2(0, 1), Action = new InputMovementAction(new Float3(0.0f), Speed) }); UpdateMapping(camera, axis); }
public sealed override void UpdateMapping(RyneCamera camera, EditAxis axis) { Float3 xAxis, yAxis; if (axis == EditAxis.All) { xAxis = new Float3(1, 0, 0); yAxis = new Float3(0, 1, 0); } else { xAxis = AxisToFloat3(axis); yAxis = xAxis; } MouseAxisInputs[0] = new MouseAxisInput { Axis = new Float2(1, 0), Action = new InputScalingAction(xAxis, Speed) }; MouseAxisInputs[1] = new MouseAxisInput { Axis = new Float2(0, 1), Action = new InputScalingAction(yAxis, Speed) }; }
public sealed override void UpdateMapping(RyneCamera camera, EditAxis axis) { Float3 xAxis, yAxis; if (axis == EditAxis.All) { // Set axes from plane tangents relative to camera Float3 planeNormal = (camera.Focus - new Float3(camera.GetPosition())).Normalize(); xAxis = planeNormal.Cross(camera.Up).Normalize() * -1.0f; yAxis = xAxis.Cross(planeNormal).Normalize(); } else { xAxis = AxisToFloat3(axis); yAxis = xAxis; } MouseAxisInputs[0] = new MouseAxisInput { Axis = new Float2(1, 0), Action = new InputMovementAction(xAxis, Speed, false) }; MouseAxisInputs[1] = new MouseAxisInput { Axis = new Float2(0, 1), Action = new InputMovementAction(yAxis, Speed, false) }; }
/// <summary> /// Displays a shape handle of the specified type. /// </summary> /// <remarks> If the user is holding Alt, the center will stay locked in place.</remarks> /// <param name="baseId">Base identifier.</param> /// <param name="size">Size.</param> /// <param name="center">Center.</param> /// <param name="orientation">Orientation.</param> /// <param name="type">Type.</param> private static void DoShapeHandle( int baseId, ref Vector3 size, ref Vector3 center, Quaternion orientation, WireShapeType type ) { // set handle matrix Matrix4x4 oldMatrix = Handles.matrix; Handles.matrix *= Matrix4x4.TRS(center, orientation, Vector3.one); // generate control Ids int rightId = ObjectX.GenerateHashCode(baseId, (int)type, (int)EditAxis.X, 1); int leftId = ObjectX.GenerateHashCode(baseId, (int)type, (int)EditAxis.X, 2); int upId = ObjectX.GenerateHashCode(baseId, (int)type, (int)EditAxis.Y, 1); int downId = ObjectX.GenerateHashCode(baseId, (int)type, (int)EditAxis.Y, 2); int forwardId = ObjectX.GenerateHashCode(baseId, (int)type, (int)EditAxis.Z, 1); int backId = ObjectX.GenerateHashCode(baseId, (int)type, (int)EditAxis.Z, 2); int currentId = GUIUtility.hotControl; int nearestId = HandleUtility.nearestControl; // cache the center and size when a handle is clicked to use for shift/alt dragging switch (Event.current.type) { case EventType.MouseDown: if ( nearestId == leftId || nearestId == rightId || nearestId == upId || nearestId == downId || nearestId == forwardId || nearestId == backId ) { s_OnClickCenter[baseId] = center; s_OnClickSize[baseId] = size; } break; case EventType.MouseUp: s_OnClickCenter.Remove(baseId); s_OnClickSize.Remove(baseId); currentId = 0; break; } // make sure size is not negative on any dimension size = new Vector3(Mathf.Max(0f, size.x), Mathf.Max(0f, size.y), Mathf.Max(0f, size.z)); // display right/left handles float right = size.x * 0.5f; float left = -size.x * 0.5f; Vector3 offset = Handles.matrix.GetScale(); offset = new Vector3( offset.x == 0f ? 0f : 1f / offset.x, offset.y == 0f ? 0f : 1f / offset.y, offset.z == 0f ? 0f : 1f / offset.z ); offset *= s_HandleOffset; right = LinearHandles.Dot( rightId, val: right, origin: Vector3.right * offset.x, direction: Vector3.right ); right = Mathf.Max(right, left); left = LinearHandles.Dot(leftId, val: left, origin: Vector3.left * offset.x, direction: Vector3.right); left = Mathf.Min(right, left); // display up/down handles float up = size.y * 0.5f; float down = -size.y * 0.5f; up = LinearHandles.Dot(upId, val: up, origin: Vector3.up * offset.y, direction: Vector3.up); up = Mathf.Max(up, down); down = LinearHandles.Dot(downId, val: down, origin: Vector3.down * offset.y, direction: Vector3.up); down = Mathf.Min(up, down); // display forward/back handles float forward = size.z * 0.5f; float back = -size.z * 0.5f; forward = LinearHandles.Dot( forwardId, val: forward, origin: Vector3.forward * offset.z, direction: Vector3.forward ); forward = Mathf.Max(forward, back); back = LinearHandles.Dot(backId, val: back, origin: Vector3.back * offset.z, direction: Vector3.forward); back = Mathf.Min(forward, back); // store which axes are being edited EditAxis editAxis = EditAxis.None; if (currentId == rightId || currentId == leftId) { editAxis = EditAxis.X; } else if (currentId == upId || currentId == downId) { editAxis = EditAxis.Y; } else if (currentId == forwardId || currentId == backId) { editAxis = EditAxis.Z; } // apply constraints to size based on shape type size.x = Mathf.Max(0f, right - left); size.y = Mathf.Max(0f, up - down); size.z = Mathf.Max(0f, forward - back); Vector3 deltaCenter = 0.5f * new Vector3(right + left, up + down, forward + back); float delta; switch (type) { case WireShapeType.Capsule: switch (editAxis) { case EditAxis.X: delta = Mathf.Min(size.x, size.y) - size.x; size.x += delta; size.z = size.x; deltaCenter.x += delta * 0.5f; break; case EditAxis.Y: delta = Mathf.Max(size.y, size.x, size.z) - size.y; size.y += delta; deltaCenter.y += delta * 0.5f; break; case EditAxis.Z: delta = Mathf.Min(size.z, size.y) - size.z; size.z += delta; size.x = size.z; deltaCenter.z += delta * 0.5f; break; } break; case WireShapeType.Cylinder: switch (editAxis) { case EditAxis.X: delta = Mathf.Min(size.x, size.y) - size.x; size.x += delta; size.z = size.x; deltaCenter.x += delta * 0.5f; break; case EditAxis.Z: delta = Mathf.Min(size.z, size.y) - size.z; size.z += delta; size.x = size.z; deltaCenter.z += delta * 0.5f; break; } break; case WireShapeType.Sphere: switch (editAxis) { case EditAxis.X: size.y = size.z = size.x; break; case EditAxis.Y: size.x = size.z = size.y; break; case EditAxis.Z: size.x = size.y = size.z; break; } break; } // apply new center center += orientation * deltaCenter; // scale uniformly using cached size if holding shift key if (s_OnClickSize.ContainsKey(baseId) && Event.current.shift) { float scaleFactor = 1f; switch (editAxis) { case EditAxis.X: scaleFactor = s_OnClickSize[baseId].x > 0f ? size.x / s_OnClickSize[baseId].x : 0f; break; case EditAxis.Y: scaleFactor = s_OnClickSize[baseId].y > 0f ? size.y / s_OnClickSize[baseId].y : 0f; break; case EditAxis.Z: scaleFactor = s_OnClickSize[baseId].z > 0f ? size.z / s_OnClickSize[baseId].z : 0f; break; } size = s_OnClickSize[baseId] * scaleFactor; } // use cached center if holding alt key if (s_OnClickCenter.ContainsKey(baseId) && Event.current.alt) { center = s_OnClickCenter[baseId]; } // draw wire shape switch (type) { case WireShapeType.Box: DrawWireBox(size); break; case WireShapeType.Capsule: DrawWireCylinder(new CylinderProperties(height: size.y, radius: size.x * 0.5f), CylinderCap.Capsule); break; case WireShapeType.Cylinder: DrawWireCylinder(new CylinderProperties(height: size.y, radius: size.x * 0.5f), CylinderCap.Cylinder); break; case WireShapeType.Sphere: float radius = size.x * 0.5f; Handles.DrawWireDisc(Vector3.zero, Vector3.right, radius); Handles.DrawWireDisc(Vector3.zero, Vector3.up, radius); Handles.DrawWireDisc(Vector3.zero, Vector3.forward, radius); // TODO: get this working in non-identity orientations // Vector3 nml = Handles.matrix.MultiplyPoint(Vector3.zero) - Camera.current.transform.position; // float sqrMagRecip = 1f / nml.sqrMagnitude; // float sqrRadius = radius * radius; // radius = Mathf.Sqrt(sqrRadius - (sqrRadius * sqrRadius * sqrMagRecip)); // Handles.DrawWireDisc( // Vector3.zero - sqrRadius * nml * sqrMagRecip, Handles.matrix.inverse.MultiplyVector(nml), radius // ); break; } // reset handle matrix Handles.matrix = oldMatrix; }