/// <summary> /// Displays a disc handle. /// </summary> /// <returns> /// The disc radius. /// </returns> /// <param name="id">Control identifier.</param> /// <param name="radius">Radius.</param> /// <param name="origin">Origin.</param> /// <param name="orientation">Orientation.</param> /// <param name="label">Label.</param> /// <param name="fillMode">Fill mode.</param> private static float DoDisc( int id, float radius, Vector3 origin, Quaternion orientation, string label, FillMode fillMode ) { // set handle matrix Matrix4x4 oldMatrix = Handles.matrix; Handles.matrix *= Matrix4x4.TRS(origin, orientation, Vector3.one); // create handles radius = LinearHandles.Dot(id, val: radius, origin: Vector3.zero, direction: Vector3.forward, label: label); radius = LinearHandles.Dot(id, val: radius, origin: Vector3.zero, direction: Vector3.right); radius = LinearHandles.Dot(id, val: radius, origin: Vector3.zero, direction: Vector3.back); radius = LinearHandles.Dot(id, val: radius, origin: Vector3.zero, direction: Vector3.left); // draw disc Color color = Handles.color; SceneGUI.SetHandleAlpha(color.a * SceneGUI.LineAlphaScalar); Handles.DrawWireDisc(Vector3.zero, Vector3.up, radius); // optionally fill the disc if (fillMode == FillMode.Solid) { SceneGUI.SetHandleAlpha(color.a * SceneGUI.FillAlphaScalar); Handles.DrawSolidDisc(Vector3.zero, Vector3.up, radius); } // reset color Handles.color = color; // reset handle matrix Handles.matrix = oldMatrix; // return the result return(radius); }
/// <summary> /// Displays a translation handle at the specified location with a customizable size and control ID that also /// respects the current scene GUI alpha. /// </summary> /// <remarks> /// Unity's built-in translation handle does not allow size specification, always renders fully opaque, and will /// result in control ID conflicts if there are multiple instances on the screen at once. /// </remarks> /// <param name="baseId">Base identifier. Each axis its own unique hash based off this value.</param> /// <param name="position">Position.</param> /// <param name="orientation">Orientation.</param> /// <param name="size">Size.</param> public static Vector3 Translation(int baseId, Vector3 position, Quaternion orientation, float size) { Color oldColor = Handles.color; size = SceneGUI.GetFixedHandleSize(position, size); Handles.color = EditorGUIX.xHandleColor * SceneGUI.CurrentAlphaScalar; GUI.SetNextControlName( ObjectX.GenerateHashCode(baseId, s_TranslationHandleHash, (int)EditAxis.X).ToString() ); position = Handles.Slider(position, orientation * Vector3.right, size, Handles.ArrowCap, 1f); Handles.color = EditorGUIX.yHandleColor * SceneGUI.CurrentAlphaScalar; GUI.SetNextControlName( ObjectX.GenerateHashCode(baseId, s_TranslationHandleHash, (int)EditAxis.Y).ToString() ); position = Handles.Slider(position, orientation * Vector3.up, size, Handles.ArrowCap, 1f); Handles.color = EditorGUIX.zHandleColor * SceneGUI.CurrentAlphaScalar; GUI.SetNextControlName( ObjectX.GenerateHashCode(baseId, s_TranslationHandleHash, (int)EditAxis.Z).ToString() ); position = Handles.Slider(position, orientation * Vector3.forward, size, Handles.ArrowCap, 1f); // TODO: add 2-axis sliders // position = Handles.DoPlanarHandle(Handles.PlaneHandle.xzPlane, position, orientation, size * 0.25f); // position = Handles.DoPlanarHandle(Handles.PlaneHandle.xyPlane, position, orientation, size * 0.25f); // position = Handles.DoPlanarHandle(Handles.PlaneHandle.yzPlane, position, orientation, size * 0.25f); Handles.color = oldColor; return(position); }
/// <summary> /// Displays an angle handle. /// </summary> /// <returns>The handle's angle value.</returns> /// <param name="id">Control identifier.</param> /// <param name="angle">Angle.</param> /// <param name="origin">Origin.</param> /// <param name="orientation">Orientation.</param> /// <param name="radius">Radius.</param> /// <param name="label">Label.</param> /// <param name="fillType">Fill type.</param> private static float Angle( int id, float angle, Vector3 origin, Quaternion orientation, float radius, string label, FillType fillType ) { // set handle matrix Matrix4x4 oldMatrix = Handles.matrix; Handles.matrix *= Matrix4x4.TRS(origin, orientation, Vector3.one); // BUG: Slider2D only works in a matrix with a scale of 1 float scaleFactor = Handles.matrix.GetScale().GetMaxValue(); radius *= scaleFactor; Handles.matrix = Matrix4x4.TRS( Handles.matrix.MultiplyPoint(Vector3.zero), Quaternion.LookRotation( Handles.matrix.MultiplyVector(Vector3.forward), Handles.matrix.MultiplyVector(Vector3.up) ), Vector3.one ); // create handle Vector3 handlePosition = Quaternion.AngleAxis(angle, Vector3.up) * Vector3.forward * radius; handlePosition = Handles.Slider2D( handlePosition, Vector3.right, Vector3.forward, Vector3.right, SceneGUI.GetFixedHandleSize(handlePosition, SceneGUI.DotHandleSize), Handles.DotCap, 0f ); Handles.DrawLine(Vector3.zero, handlePosition); float newAngle = Vector3.Angle( Vector3.forward, handlePosition ) * Mathf.Sign(Vector3.Dot(Vector3.right, handlePosition.normalized)); angle += GetDeltaAngle(angle % 360f, newAngle); // fill arc if (fillType == FillType.Solid) { Color c = Handles.color; SceneGUI.SetHandleAlpha(c.a * SceneGUI.FillAlphaScalar); Handles.DrawSolidArc(Vector3.zero, Vector3.up, Vector3.forward, angle, radius); Handles.color = c; } // draw the label if requested if (!string.IsNullOrEmpty(label)) { Handles.Label(Quaternion.AngleAxis(angle, Vector3.up) * Vector3.forward * radius, label); } // reset handle matrix Handles.matrix = oldMatrix; // return result return(angle); }
/// <summary> /// Raises the enable event. /// </summary> protected virtual void OnEnable() { m_DisplayHandlePreferencesMethod = GetType().GetStaticMethod("DisplayHandlePreferences"); m_FirstTarget = this.target; foreach (Object t in this.targets) { if (t != null) { m_InspectedObjects.Add(t, new SerializedObject(t)); } } if (this.ImplementsSceneGUIOverlay) { SceneGUI.RegisterObjectGUICallback(this as ISceneGUIContext, OnSceneGUIOverlay); } Undo.undoRedoPerformed += ApplyModificationsAndUpdateGUIContents; Undo.postprocessModifications += OnModifyProperty; }
/// <summary> /// Raises the enable event. /// </summary> protected virtual void OnEnable() { m_DisplayHandlePreferencesMethod = GetType().GetMethod( "DisplayHandlePreferences", ReflectionX.staticBindingFlags ); m_FirstTarget = this.target; foreach (Object t in this.targets) { if (t != null) { m_InspectedObjects.Add(t, new SerializedObject(t)); } } if (this.ImplementsSceneGUIOverlay) { SceneGUI.RegisterObjectGUICallback(this as ISceneGUIContext, OnSceneGUIOverlay); } Undo.undoRedoPerformed += UpdateGUIContents; }
/// <summary> /// Raises the scene GUI event. /// </summary> protected virtual void OnSceneGUI() { // early out if the target is null, e.g., if it was destroyed in an earlier callback this frame or if scene gui is disabled if (this.target == null || !SceneGUI.IsEnabled) { return; } if (this.ImplementsSceneGUIHandles) { Color oldColor = Handles.color; Matrix4x4 oldMatrix = Handles.matrix; Handles.matrix = this.HandleMatrix; DisplaySceneGUIHandles(); Handles.color = oldColor; Handles.matrix = oldMatrix; } if (this.ImplementsSceneGUIOverlay) { SceneGUI.Display(this); } }
/// <summary> /// Displays a slider. /// </summary> /// <returns>The new value.</returns> /// <param name="id">Control identifier.</param> /// <param name="val">Value.</param> /// <param name="origin">Origin.</param> /// <param name="direction">Direction.</param> /// <param name="label">Label.</param> /// <param name="capScale">A scale factor for the slider cap.</param> /// <param name="displayMode">Display mode.</param> /// <param name="capFunction">Default cap function (used for line handles).</param> private static float Slider( int id, float val, Vector3 origin, Vector3 direction, string label, float capScale, DisplayMode displayMode, Handles.DrawCapFunction capFunction ) { // set handle matrix Matrix4x4 oldMatrix = Handles.matrix; Handles.matrix *= Matrix4x4.TRS(origin, Quaternion.identity, Vector3.one); // normalize direction direction.Normalize(); // draw a label if requested if (!string.IsNullOrEmpty(label)) { Handles.Label(direction * val, label); } // perform special setup based on display mode Handles.DrawCapFunction cap = capFunction == null ? Handles.DotCap : capFunction; switch (displayMode) { case DisplayMode.Arrow: cap = Handles.ArrowCap; break; case DisplayMode.Cone: cap = Handles.ConeCap; break; case DisplayMode.Dot: cap = Handles.DotCap; capScale *= SceneGUI.DotHandleSize; break; case DisplayMode.Line: Handles.DrawLine(Vector3.zero, direction * val); capScale *= SceneGUI.DotHandleSize; break; } // create a slider Vector3 initialPosition = direction * val; s_Do1DSliderParams[0] = id; s_Do1DSliderParams[1] = initialPosition; s_Do1DSliderParams[2] = direction; s_Do1DSliderParams[3] = SceneGUI.GetFixedHandleSize(initialPosition, capScale); s_Do1DSliderParams[4] = cap; s_Do1DSliderParams[5] = 1f; // TODO: do something with snap Vector3 vDelta = (Vector3)s_Do1DSlider.Invoke(null, s_Do1DSliderParams) - initialPosition; float delta = vDelta.magnitude; if (delta > s_RequiredMinHandleChange) { val += delta * Mathf.Sign(Vector3.Dot(vDelta, direction)); } // reset handle matrix Handles.matrix = oldMatrix; // return results return(val); }
/// <summary> /// Raises the disable event. /// </summary> protected virtual void OnDisable() { SceneGUI.DeregisterObjectGUICallback(this as ISceneGUIContext); Undo.undoRedoPerformed -= ApplyModificationsAndUpdateGUIContents; Undo.postprocessModifications -= OnModifyProperty; }
/// <summary> /// Raises the disable event. /// </summary> protected virtual void OnDisable() { SceneGUI.DeregisterObjectGUICallback(this as ISceneGUIContext); Undo.undoRedoPerformed -= UpdateGUIContents; }