/// <summary> /// Align texture to extends for a given face /// </summary> /// <param name="extends"></param> /// <param name="face"></param> /// <param name="justifyType"></param> public void AlignTextureToExtendsForFace(AABB extends, SolidFace face, TextureProperties.JustifyType justifyType) { if (face.TextureMapping.TextureLocked) { return; } // get projected min/max float projMinU = Vector3.Dot(extends.Min, face.TextureMapping.UAxis) / face.TextureMapping.UScale; float projMinV = Vector3.Dot(extends.Min, face.TextureMapping.VAxis) / face.TextureMapping.VScale; float projMaxU = Vector3.Dot(extends.Max, face.TextureMapping.UAxis) / face.TextureMapping.UScale; float projMaxV = Vector3.Dot(extends.Max, face.TextureMapping.VAxis) / face.TextureMapping.VScale; // check if V axis is 90 degrees lockwise of U axis if (face.TextureMapping.VAxis.SignedAngleTo(face.TextureMapping.UAxis, face.Normal) < 0) { float temp = projMinU; projMinU = projMaxU; projMaxU = temp; } switch (justifyType) { case TextureProperties.JustifyType.Top: face.TextureMapping.VShift = -projMaxV + face.Texture.Height; break; case TextureProperties.JustifyType.Bottom: face.TextureMapping.VShift = -projMinV; break; case TextureProperties.JustifyType.Left: face.TextureMapping.UShift = -projMinU; break; case TextureProperties.JustifyType.Right: face.TextureMapping.UShift = -projMaxU + face.Texture.Width; break; case TextureProperties.JustifyType.Center: float deltaU = (projMinU + projMaxU) / 2; float deltaV = (projMinV + projMaxV) / 2; face.TextureMapping.UShift = -deltaU + face.Texture.Width / 2f; face.TextureMapping.VShift = -deltaV + face.Texture.Height / 2f; break; } }
private void OnTexturePropertiesJustifyClicked(TextureProperties textureProperties, TextureProperties.JustifyType justifyType) { if (CurrentSolidManipulationMode == SolidManipulationMode.Vertex) { return; } // collect solid and group map objects CustomOperation setSolidPropertiesOperation = new CustomOperation(); setSolidPropertiesOperation.OnMapObjectGroup = group => group.MapObjectList.ForEach(m => m.PerformOperation(setSolidPropertiesOperation)); AABB extends = new AABB(); // create extends for all selected faces if treat as one is true if (textureProperties.TreatAsOne) { CustomOperation createExtendsOperation = new CustomOperation(); createExtendsOperation.OnMapObjectGroup = group => group.MapObjectList.ForEach(m => m.PerformOperation(createExtendsOperation)); createExtendsOperation.OnSolid = solid => { solid.Faces.Where(f => f.Selected).ToList() .ForEach(face => { IEnumerable <Vector3> points = solid.GetVerticesForFace(face).Select(v => v.Position); extends.Grow(points); }); }; Selection.PerformOperation(createExtendsOperation); } setSolidPropertiesOperation.OnSolid = solid => { solid.Faces.Where(f => f.Selected).ToList().ForEach(face => { // create extends for this face if Treat as one is false if (!textureProperties.TreatAsOne) { extends.Reset(); extends.Grow(solid.GetVerticesForFace(face).Select(v => v.Position)); } switch (justifyType) { case TextureProperties.JustifyType.Fit: solid.FitTextureToExtendsForFace(extends, face); break; case TextureProperties.JustifyType.Top: case TextureProperties.JustifyType.Bottom: case TextureProperties.JustifyType.Left: case TextureProperties.JustifyType.Right: case TextureProperties.JustifyType.Center: solid.AlignTextureToExtendsForFace(extends, face, justifyType); break; } solid.CalculateTextureCoordinatesForFace(face, true); }); }; Selection.PerformOperation(setSolidPropertiesOperation); SceneDocument.IsDirty = true; UpdateUserInterface(); RenderViewports(); }