// indices arrays are optional - if null is passed the index will be 0, 1, 2... up to values array length. // this is done to avoid allocating a separate array just to pass linear indices internal static UVTransform CalculateDelta(IList <Vector2> src, IList <int> srcIndices, IList <Vector2> dst, IList <int> dstIndices) { // rotate to match target points by comparing the angle between old UV and new auto projection Vector2 srcAngle = src[GetIndex(srcIndices, 1)] - src[GetIndex(srcIndices, 0)]; Vector2 dstAngle = dst[GetIndex(dstIndices, 1)] - dst[GetIndex(dstIndices, 0)]; float rotation = Vector2.Angle(dstAngle, srcAngle); if (Vector2.Dot(Vector2.Perpendicular(dstAngle), srcAngle) < 0) { rotation = 360f - rotation; } Vector2 dstCenter = dstIndices == null?Bounds2D.Center(dst) : Bounds2D.Center(dst, dstIndices); // inverse the rotation to get an axis-aligned scale Vector2 dstSize = GetRotatedSize(dst, dstIndices, dstCenter, -rotation); Bounds2D srcBounds = srcIndices == null ? new Bounds2D(src) : new Bounds2D(src, srcIndices); Vector2 scale = dstSize.DivideBy(srcBounds.size); Vector2 srcCenter = srcBounds.center * scale; return(new UVTransform() { translation = dstCenter - srcCenter, rotation = rotation, scale = dstSize.DivideBy(srcBounds.size) }); }
internal Sprite(JsonValue json, Vector2 size) { _texSize = size; _pixelPosition = VectorFromJson(json["position"]); _pixelSize = VectorFromJson(json["size"]); _pixelAnchor = VectorFromJson(json["anchor"]); _position = _pixelPosition.DivideBy(size); _size = _pixelSize.DivideBy(size); _anchor = _pixelAnchor.DivideBy(size); }
/** * When modifying single properties, also set the textureGroup back to 0 since * generally users don't want their face UVs to snap back to form after applying * a change. */ public static void TranslateOffset(Vector2 delta, pb_Object[] sel) { delta.x = -delta.x; for (int i = 0; i < sel.Length; i++) { foreach (pb_Face q in sel[i].SelectedFaces) { q.uv.offset -= delta.DivideBy(q.uv.scale); } sel[i].RefreshUV(pb_Editor.instance.SelectedFacesInEditZone[i]); } }
/** * When modifying single properties, also set the textureGroup back to 0 since * generally users don't want their face UVs to snap back to form after applying * a change. */ public static void TranslateOffset(Vector2 delta, pb_Object[] sel) { delta.x = -delta.x; for(int i = 0; i < sel.Length; i++) { foreach(pb_Face q in sel[i].SelectedFaces) { q.uv.offset -= delta.DivideBy(q.uv.scale); } sel[i].RefreshUV(pb_Editor.instance.SelectedFacesInEditZone[i]); } }
/** * New scale, previous scale */ internal void SceneScaleTool(Vector2 textureScale, Vector2 previousScale) { textureScale.x = 1f / textureScale.x; textureScale.y = 1f / textureScale.y; previousScale.x = 1f / previousScale.x; previousScale.y = 1f / previousScale.y; if(ControlKey) textureScale = pbUtil.SnapValue(textureScale, pref_gridSnapValue); if(!modifyingUVs) { pbUndo.RecordObjects(selection, "Scale UVs"); OnBeginUVModification(); } if(mode == UVMode.Mixed || mode == UVMode.Manual) { for(int n = 0; n < selection.Length; n++) { pb_Object pb = selection[n]; Vector2[] uvs = pb.msh.uv; foreach(int i in distinct_indices[n]) { uvs[i] = uv_origins[n][i].ScaleAroundPoint(uvOrigin, textureScale); uvs_canvas_space[n][i] = pb_Handle_Utility.UVToGUIPoint(uvs[i], uvGridSize); } pb.SetUV(uvs); pb.msh.uv = uvs; } } /** * Auto mode scales UVs prior to rotation, so we have to do it separately here. */ if(mode == UVMode.Mixed || mode == UVMode.Auto) { Vector2 delta = textureScale.DivideBy(previousScale); for(int n = 0; n < selection.Length; n++) { pb_Face[] autoFaces = System.Array.FindAll(selection[n].SelectedFaces, x => !x.manualUV); foreach(pb_Face face in autoFaces) { face.uv.scale = Vector2.Scale(face.uv.scale, delta); } selection[n].RefreshUV(autoFaces); } RefreshSelectedUVCoordinates(); } nearestElement.valid = false; needsRepaint = true; }