/// <summary> /// Snap a Vector3 to the nearest point on the current ProGrids grid if ProGrids is enabled. /// </summary> /// <param name="point"></param> /// <returns></returns> public static float ProGridsSnap(float point) { if (GetProGridsType() == null) { return(point); } if (SnapEnabled()) { return(ProGridsSnapping.SnapValue(point, ProGridsInterface.SnapValue())); } return(point); }
/// <summary> /// Snap a Vector3 to the nearest point on the current ProGrids grid if ProGrids is enabled, with mask. /// </summary> /// <param name="point"></param> /// <param name="mask"></param> /// <returns></returns> public static Vector3 ProGridsSnap(Vector3 point, Vector3 mask) { if (GetProGridsType() == null) { return(point); } if (ProGridsInterface.SnapEnabled()) { float snap = ProGridsInterface.SnapValue(); return(ProGridsSnapping.SnapValue(point, mask * snap)); } return(point); }
internal static void SetPivotLocationAndSnap(ProBuilderMesh mesh) { if (ProGridsInterface.SnapEnabled()) { mesh.transform.position = ProGridsSnapping.SnapValue(mesh.transform.position, ProGridsInterface.SnapValue()); } else if (s_SnapNewShapesToGrid) { mesh.transform.position = ProGridsSnapping.SnapValue(mesh.transform.position, new Vector3( EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ"))); } mesh.Optimize(); }
/// <summary> /// Return the last known grid pivot point. /// </summary> /// <param name="pivot"></param> /// <returns></returns> public static bool GetPivot(out Vector3 pivot) { pivot = Vector3.zero; if (s_GetPivotDelegate == null) { s_GetPivotDelegate = (Func <Vector3>)ReflectionUtility.GetOpenDelegate <Func <Vector3> >(GetProGridsType(), "GetPivot"); } if (s_GetPivotDelegate != null) { pivot = s_GetPivotDelegate(); // earlier version of progrids return a non-snapped pivot point pivot = ProGridsSnapping.SnapValue(pivot, SnapValue()); return(true); } return(false); }
protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!isEditing) { m_Position = Vector3.zero; } EditorHandleUtility.PushMatrix(); Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); EditorGUI.BeginChangeCheck(); Handles.color = Color.blue; m_Position = Handles.Slider2D(m_Position, Vector3.forward, Vector3.right, Vector3.up, HandleUtility.GetHandleSize(m_Position) * .2f, Handles.RectangleHandleCap, 0f, false); Handles.color = Color.green; m_Position = Handles.Slider(m_Position, Vector3.up); Handles.color = Color.red; m_Position = Handles.Slider(m_Position, Vector3.right); Handles.color = Color.white; if (EditorGUI.EndChangeCheck()) { if (!isEditing) { BeginEdit("Translate Textures"); } if (relativeSnapEnabled) { m_Position.x = ProGridsSnapping.SnapValue(m_Position.x, relativeSnapX); m_Position.y = ProGridsSnapping.SnapValue(m_Position.y, relativeSnapY); } else if (progridsSnapEnabled) { m_Position.x = ProGridsSnapping.SnapValue(m_Position.x, progridsSnapValue); m_Position.y = ProGridsSnapping.SnapValue(m_Position.y, progridsSnapValue); } // invert `y` because to users it's confusing that "up" in UV space visually moves the texture down var delta = new Vector4(m_Position.x, -m_Position.y, 0f, 0f); foreach (var value in elementSelection) { var selection = value as TranslateTextureSelection; if (selection == null) { continue; } // Account for object scale delta *= k_Vector3Magnitude / selection.mesh.transform.lossyScale.magnitude; var origins = selection.origins; var positions = selection.textures; // Translating faces is treated as a special case because we want the textures in scene to visually // match the movement of the translation handle. When UVs are scaled, they have the appearance of // moving faster or slower (even though they are translating the correct distances). To avoid this, // we cache the UV scale of each face and modify the translation delta accordingly. This isn't perfect, // as it will not be able to find the scale for sheared or otherwise distorted face UVs. However, for // most cases it maps quite well. if (ProBuilderEditor.selectMode == SelectMode.TextureFace) { foreach (var face in selection.faceAndScale) { var faceDelta = new Vector4(delta.x / face.item2.x, delta.y / face.item2.y, 0f, 0f); foreach (var index in face.item1.distinctIndexes) { positions[index] = origins[index] + faceDelta; } } } else { foreach (var group in value.elementGroups) { foreach (var index in group.indices) { positions[index] = origins[index] + delta; } } } selection.mesh.mesh.SetUVs(k_TextureChannel, positions); } } EditorHandleUtility.PopMatrix(); }
protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!isEditing) { m_Rotation = 0f; } EditorGUI.BeginChangeCheck(); var size = HandleUtility.GetHandleSize(handlePosition); EditorHandleUtility.PushMatrix(); Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); Handles.color = Color.blue; m_Euler.z = m_Rotation; m_Quaternion = Quaternion.Euler(m_Euler); m_Quaternion = Handles.Disc(m_Quaternion, Vector3.zero, Vector3.forward, size, relativeSnapEnabled, relativeSnapRotation); m_Euler = m_Quaternion.eulerAngles; m_Rotation = m_Euler.z; EditorHandleUtility.PopMatrix(); if (EditorGUI.EndChangeCheck()) { if (!isEditing) { BeginEdit("Rotate Textures"); } if (relativeSnapEnabled) { m_Rotation = ProGridsSnapping.SnapValue(m_Rotation, relativeSnapX); } else if (progridsSnapEnabled) { m_Rotation = ProGridsSnapping.SnapValue(m_Rotation, progridsSnapValue); } foreach (var mesh in elementSelection) { if (!(mesh is MeshAndTextures)) { continue; } var mat = (MeshAndTextures)mesh; var origins = mat.origins; var positions = mat.textures; foreach (var group in mat.elementGroups) { foreach (var index in group.indices) { positions[index] = mat.postApplyMatrix.MultiplyPoint( Math.RotateAroundPoint( mat.preApplyMatrix.MultiplyPoint3x4(origins[index]), Vector2.zero, -m_Rotation)); } } mesh.mesh.mesh.SetUVs(k_TextureChannel, positions); } } }
protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { base.DoTool(handlePosition, handleRotation); if (!isEditing) { m_HandlePosition = handlePosition; } #if PROBUILDER_ENABLE_TRANSFORM_ORIGIN_GIZMO if (isEditing) { DrawSelectionOriginGizmos(); } #endif EditorGUI.BeginChangeCheck(); m_HandlePosition = Handles.PositionHandle(m_HandlePosition, handleRotation); m_RawHandleDelta = m_HandlePosition - handlePositionOrigin; var delta = m_RawHandleDelta; if (EditorGUI.EndChangeCheck() && delta.sqrMagnitude > k_MinTranslateDeltaSqrMagnitude) { if (!isEditing) { BeginEdit("Translate Selection"); } if (vertexDragging) { Vector3 nearest; if (FindNearestVertex(currentEvent.mousePosition, out nearest)) { var unrotated = handleRotationOriginInverse * delta; var dir = new Vector3Mask(unrotated, k_CardinalAxisError); if (dir.active == 1) { var rotationDirection = handleRotationOrigin * dir * 10000f; m_HandlePosition = HandleUtility.ProjectPointLine(nearest, handlePositionOrigin + rotationDirection, handlePositionOrigin - rotationDirection); delta = m_HandlePosition - handlePositionOrigin; } } } else if (progridsSnapEnabled) { if (snapAxisConstraint) { m_ActiveAxesModel |= new Vector3Mask(handleRotationOriginInverse * delta, k_CardinalAxisError); m_ActiveAxesWorld = new Vector3Mask(handleRotation * m_ActiveAxesModel); if (m_ActiveAxesWorld.active == 1) { m_HandlePosition = ProGridsSnapping.SnapValueOnRay( new Ray(handlePositionOrigin, delta), delta.magnitude, progridsSnapValue, m_ActiveAxesWorld); } else { m_HandlePosition = ProGridsSnapping.SnapValue(m_HandlePosition, progridsSnapValue); } } else { m_HandlePosition = ProGridsSnapping.SnapValue(m_HandlePosition, progridsSnapValue); } delta = m_HandlePosition - handlePositionOrigin; } #if PROBUILDER_ENABLE_TRANSFORM_ORIGIN_GIZMO if (pivotPoint == PivotPoint.IndividualOrigins && !m_DirectionOriginInitialized) { var mask = new Vector3Mask(handleRotationOriginInverse * delta, k_CardinalAxisError); if (mask.active > 0) { m_IndividualOriginDirection = mask; m_DirectionOriginInitialized = true; } } #endif ApplyTranslation(handleRotationOriginInverse * delta); } // Draw at the end so we get the snapped value if (showHandleInfo && isEditing) { DrawDeltaInfo(string.Format("Translate: <b>{0:F2}</b> {1}", delta.magnitude, (handleRotationOriginInverse * delta).ToString("0.00"))); } }
void ApplyTranslation(Vector3 translation) { var translationMagnitude = translation.magnitude; foreach (var key in elementSelection) { if (!(key is MeshAndPositions)) { continue; } var kvp = (MeshAndPositions)key; var mesh = kvp.mesh; var worldToLocal = mesh.transform.worldToLocalMatrix; var origins = kvp.positions; var positions = mesh.positionsInternal; foreach (var group in kvp.elementGroups) { var postApplyMatrix = GetPostApplyMatrix(group); var preApplyMatrix = postApplyMatrix.inverse; foreach (var index in group.indices) { // res = Group pre-apply matrix * world vertex position // res += translation // res = Group post-apply matrix * res // positions[i] = mesh.worldToLocal * res if (progridsSnapEnabled && !m_SnapAsGroup) { if (snapAxisConstraint && m_ActiveAxesWorld.active == 1) { var wp = postApplyMatrix.MultiplyPoint3x4(preApplyMatrix.MultiplyPoint3x4(origins[index])); var snap = ProGridsSnapping.SnapValueOnRay( new Ray(wp, m_RawHandleDelta), translationMagnitude, progridsSnapValue, m_ActiveAxesWorld); positions[index] = worldToLocal.MultiplyPoint3x4(snap); } else { var wp = postApplyMatrix.MultiplyPoint3x4(translation + preApplyMatrix.MultiplyPoint3x4(origins[index])); var snap = ProGridsSnapping.SnapValue(wp, Vector3.one * progridsSnapValue); positions[index] = worldToLocal.MultiplyPoint3x4(snap); } } else { positions[index] = worldToLocal.MultiplyPoint3x4( postApplyMatrix.MultiplyPoint3x4( translation + preApplyMatrix.MultiplyPoint3x4(origins[index]))); } } } mesh.mesh.vertices = positions; mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); mesh.Refresh(RefreshMask.Normals); } ProBuilderEditor.Refresh(false); }