Migrate nozzle limits texture construction to drawable

- Construct and cache textures after use
- Create placeholder textures for use before constructed
- Remove bed texture construction from CreatePrintBedAndVolume
- Issue MatterHackers/MCCentral#5325
Migrate to themed bed colors
- Issue MatterHackers/MCCentral#5320
Cache per hotend bed textures
This commit is contained in:
John Lewin 2019-04-13 02:13:20 -07:00
parent 17eca3b36c
commit 60a1238f54
5 changed files with 180 additions and 139 deletions

View file

@ -435,12 +435,6 @@ namespace MatterHackers.MatterControl
private Mesh _bedMesh;
[JsonIgnore]
public ImageBuffer ActiveBedImage { get; private set; }
[JsonIgnore]
public ImageBuffer GeneratedBedImage { get; private set; }
[JsonIgnore]
public Mesh Mesh
{
@ -449,9 +443,7 @@ namespace MatterHackers.MatterControl
if (_bedMesh == null)
{
// Load bed and build volume meshes
(_bedMesh, _buildVolumeMesh, this.ActiveBedImage) = BedMeshGenerator.CreatePrintBedAndVolume(Printer);
this.GeneratedBedImage = new ImageBuffer(this.ActiveBedImage);
(_bedMesh, _buildVolumeMesh) = BedMeshGenerator.CreatePrintBedAndVolume(Printer);
Task.Run(() =>
{

View file

@ -28,8 +28,15 @@ either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Font;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.VertexSource;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.RenderOpenGl;
using MatterHackers.RenderOpenGl.OpenGl;
using MatterHackers.VectorMath;
@ -41,14 +48,23 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
private ISceneContext sceneContext;
private InteractionLayer.EditorType editorType;
private ThemeConfig theme;
private PrinterConfig printer;
private Color buildVolumeColor;
private int activeBedHotendClippingImage = -1;
private ImageBuffer[] bedTextures = null;
private bool loadingTextures = false;
public FloorDrawable(InteractionLayer.EditorType editorType, ISceneContext sceneContext, Color buildVolumeColor, ThemeConfig theme)
{
this.buildVolumeColor = buildVolumeColor;
this.sceneContext = sceneContext;
this.editorType = editorType;
this.theme = theme;
this.printer = sceneContext.Printer;
{
}
@ -71,6 +87,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
// only render if we are above the bed
if (sceneContext.RendererOptions.RenderBed)
{
this.UpdateFloorImage(sceneContext.Scene.SelectedItem);
GLHelper.Render(
sceneContext.Mesh,
theme.UnderBedColor,
@ -142,6 +160,158 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
}
}
private void UpdateFloorImage(IObject3D selectedItem)
{
// Early exit for invalid cases
if (loadingTextures
|| printer == null
|| printer.Settings.Helpers.NumberOfHotends() != 2
|| printer.Bed.BedShape != BedShape.Rectangular)
{
return;
}
if (bedTextures != null)
{
int hotendIndex = GetActiveHotendIndex(selectedItem);
if (activeBedHotendClippingImage != hotendIndex)
{
this.SetActiveTexture(bedTextures[hotendIndex + 1]);
activeBedHotendClippingImage = hotendIndex;
}
}
else
{
loadingTextures = true;
Task.Run(() =>
{
var placeHolderImage = new ImageBuffer(5, 5);
var graphics = placeHolderImage.NewGraphics2D();
graphics.Clear(theme.BedColor);
SetActiveTexture(placeHolderImage);
try
{
var bedImage = BedMeshGenerator.CreatePrintBedImage(sceneContext.Printer);
bedTextures = new[]
{
bedImage, // No limits, basic themed bed
new ImageBuffer(bedImage), // T0 limits
new ImageBuffer(bedImage), // T1 limits
new ImageBuffer(bedImage) // Unioned T0 & T1 limits
};
GenerateNozzleLimitsTexture(printer, 0, bedTextures[1]);
GenerateNozzleLimitsTexture(printer, 1, bedTextures[2]);
// TODO:
// GenerateNozzleLimitsTexture(printer, 3, bedTextures[3]);
}
catch
{
}
loadingTextures = false;
});
}
}
private void SetActiveTexture(ImageBuffer bedTexture)
{
foreach (var texture in printer.Bed.Mesh.FaceTextures)
{
texture.Value.image = bedTexture;
}
printer.Bed.Mesh.PropertyBag.Clear();
}
private static int GetActiveHotendIndex(IObject3D selectedItem)
{
if (selectedItem == null)
{
return -1;
}
var worldMaterialIndex = selectedItem.WorldMaterialIndex();
if (worldMaterialIndex == -1)
{
worldMaterialIndex = 0;
}
return worldMaterialIndex;
}
private void GenerateNozzleLimitsTexture(PrinterConfig printer, int hotendIndex, ImageBuffer bedplateImage)
{
var xScale = bedplateImage.Width / printer.Settings.BedBounds.Width;
var yScale = bedplateImage.Height / printer.Settings.BedBounds.Height;
int alpha = 80;
var graphics = bedplateImage.NewGraphics2D();
var hotendBounds = printer.Settings.HotendBounds[hotendIndex];
// Scale hotendBounds into textures units
hotendBounds = new RectangleDouble(
hotendBounds.Left * xScale,
hotendBounds.Bottom * yScale,
hotendBounds.Right * xScale,
hotendBounds.Top * yScale);
var imageBounds = bedplateImage.GetBounds();
var dimRegion = new VertexStorage();
dimRegion.MoveTo(imageBounds.Left, imageBounds.Bottom);
dimRegion.LineTo(imageBounds.Right, imageBounds.Bottom);
dimRegion.LineTo(imageBounds.Right, imageBounds.Top);
dimRegion.LineTo(imageBounds.Left, imageBounds.Top);
var targetRect = new VertexStorage();
targetRect.MoveTo(hotendBounds.Right, hotendBounds.Bottom);
targetRect.LineTo(hotendBounds.Left, hotendBounds.Bottom);
targetRect.LineTo(hotendBounds.Left, hotendBounds.Top);
targetRect.LineTo(hotendBounds.Right, hotendBounds.Top);
targetRect.ClosePolygon();
var overlayMinusTargetRect = new CombinePaths(dimRegion, targetRect);
graphics.Render(overlayMinusTargetRect, new Color(Color.Black, alpha));
string hotendTitle = string.Format("{0} {1}", "Nozzle ".Localize(), hotendIndex + 1);
var stringPrinter = new TypeFacePrinter(hotendTitle, theme.DefaultFontSize, bold: true);
var printerBounds = stringPrinter.GetBounds();
int textPadding = 8;
var textBounds = printerBounds;
textBounds.Inflate(textPadding);
var cornerRect = new RectangleDouble(hotendBounds.Right - textBounds.Width, hotendBounds.Top - textBounds.Height, hotendBounds.Right, hotendBounds.Top);
graphics.Render(
new RoundedRectShape(cornerRect, bottomLeftRadius: 6),
theme.PrimaryAccentColor);
graphics.DrawString(
hotendTitle,
hotendBounds.Right - textPadding,
cornerRect.Bottom + (cornerRect.Height / 2 - printerBounds.Height / 2) + 1,
theme.DefaultFontSize,
justification: Justification.Right,
baseline: Baseline.Text,
color: Color.White,
bold: true);
graphics.Render(new Stroke(targetRect, 1), theme.PrimaryAccentColor);
}
{
}
}

View file

@ -68,14 +68,17 @@ namespace MatterHackers.MatterControl
return bedImage;
}
public static (Mesh bed, Mesh volume, ImageBuffer bedImage) CreatePrintBedAndVolume(PrinterConfig printer)
public static (Mesh bed, Mesh volume) CreatePrintBedAndVolume(PrinterConfig printer)
{
Mesh printerBed = null;
Mesh buildVolume = null;
Vector3 displayVolumeToBuild = Vector3.ComponentMax(printer.Bed.ViewerVolume, new Vector3(1, 1, 1));
ImageBuffer bedplateImage = CreatePrintBedImage(printer);
// Temporarily assign a placeholder image as the mesh texture. This will be replaced with a themed image by the view
var placeHolderImage = new ImageBuffer(5, 5);
var graphics = placeHolderImage.NewGraphics2D();
graphics.Clear(Color.Gray.WithAlpha(40));
switch (printer.Bed.BedShape)
{
@ -87,12 +90,13 @@ namespace MatterHackers.MatterControl
{
buildVolume.Vertices[i] = buildVolume.Vertices[i] + new Vector3Float(0, 0, displayVolumeToBuild.Z / 2);
}
var bspTree = FaceBspTree.Create(buildVolume);
buildVolume.FaceBspTree = bspTree;
}
printerBed = PlatonicSolids.CreateCube(displayVolumeToBuild.X, displayVolumeToBuild.Y, 1.8);
printerBed.PlaceTextureOnFaces(0, bedplateImage);
printerBed.PlaceTextureOnFaces(0, placeHolderImage);
break;
case BedShape.Circular:
@ -103,7 +107,7 @@ namespace MatterHackers.MatterControl
}
printerBed = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), 1.8);
printerBed.PlaceTextureOnFaces(0, bedplateImage);
printerBed.PlaceTextureOnFaces(0, placeHolderImage);
}
break;
@ -125,7 +129,7 @@ namespace MatterHackers.MatterControl
}
}
return (printerBed, buildVolume, bedplateImage);
return (printerBed, buildVolume);
}
private static ImageBuffer CreateCircularBedGridImage(PrinterConfig printer)

View file

@ -134,8 +134,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|| settingsKey == SettingsKey.bed_size
|| settingsKey == SettingsKey.print_center)
{
activeBedHotendClippingImage = -1;
this.UpdateFloorImage(sceneContext.Scene.SelectedItem);
this.Invalidate();
}
}

View file

@ -490,8 +490,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
floorDrawable.Draw(this, e, Matrix4X4.Identity, this.World);
}
this.UpdateFloorImage(selectedItem);
DrawInteractionVolumes(e);
foreach (var drawable in drawables.Where(d => d.DrawStage == DrawStage.TransparentContent))
@ -528,127 +526,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
}
}
int activeBedHotendClippingImage = -1;
private void UpdateFloorImage(IObject3D selectedItem)
{
if (sceneContext.Printer == null)
{
return;
}
var bed = sceneContext as BedConfig;
var printer = sceneContext.Printer;
int hotendIndex;
if (selectedItem == null)
{
hotendIndex = -1;
}
else
{
var worldMaterialIndex = selectedItem.WorldMaterialIndex();
if (worldMaterialIndex == -1)
{
worldMaterialIndex = 0;
}
hotendIndex = worldMaterialIndex;
}
if (activeBedHotendClippingImage != hotendIndex)
{
ImageBuffer bedplateImage;
if (hotendIndex == -1)
{
// Reset back to default
bedplateImage = bed.GeneratedBedImage;
}
else
{
// Create new image from current bed texture image
bedplateImage = new ImageBuffer(bed.GeneratedBedImage);
if (printer.Settings.Helpers.NumberOfHotends() == 2
&& printer.Bed.BedShape == BedShape.Rectangular
&& (hotendIndex == 0 || hotendIndex == 1))
{
var xScale = bedplateImage.Width / printer.Settings.BedBounds.Width;
var yScale = bedplateImage.Height / printer.Settings.BedBounds.Height;
int alpha = 80;
var graphics = bedplateImage.NewGraphics2D();
var hotendBounds = printer.Settings.HotendBounds[hotendIndex];
// Scale hotendBounds into textures units
hotendBounds = new RectangleDouble(
hotendBounds.Left * xScale,
hotendBounds.Bottom * yScale,
hotendBounds.Right * xScale,
hotendBounds.Top * yScale);
var imageBounds = bedplateImage.GetBounds();
var dimRegion = new VertexStorage();
dimRegion.MoveTo(imageBounds.Left, imageBounds.Bottom);
dimRegion.LineTo(imageBounds.Right, imageBounds.Bottom);
dimRegion.LineTo(imageBounds.Right, imageBounds.Top);
dimRegion.LineTo(imageBounds.Left, imageBounds.Top);
var targetRect = new VertexStorage();
targetRect.MoveTo(hotendBounds.Right, hotendBounds.Bottom);
targetRect.LineTo(hotendBounds.Left, hotendBounds.Bottom);
targetRect.LineTo(hotendBounds.Left, hotendBounds.Top);
targetRect.LineTo(hotendBounds.Right, hotendBounds.Top);
targetRect.ClosePolygon();
var overlayMinusTargetRect = new CombinePaths(dimRegion, targetRect);
graphics.Render(overlayMinusTargetRect, new Color(Color.Black, alpha));
string hotendTitle = string.Format("{0} {1}", "Nozzle ".Localize(), hotendIndex + 1);
var stringPrinter = new TypeFacePrinter(hotendTitle, theme.DefaultFontSize, bold: true);
var printerBounds = stringPrinter.GetBounds();
int textPadding = 8;
var textBounds = printerBounds;
textBounds.Inflate(textPadding);
var cornerRect = new RectangleDouble(hotendBounds.Right - textBounds.Width, hotendBounds.Top - textBounds.Height, hotendBounds.Right, hotendBounds.Top);
graphics.Render(
new RoundedRectShape(cornerRect, bottomLeftRadius: 6),
theme.PrimaryAccentColor);
graphics.DrawString(
hotendTitle,
hotendBounds.Right - textPadding,
cornerRect.Bottom + (cornerRect.Height / 2 - printerBounds.Height / 2) + 1,
theme.DefaultFontSize,
justification: Justification.Right,
baseline: Baseline.Text,
color: Color.White,
bold: true);
graphics.Render(new Stroke(targetRect, 1), theme.PrimaryAccentColor);
}
}
foreach (var texture in bed.Mesh.FaceTextures)
{
texture.Value.image = bedplateImage;
}
bed.Mesh.PropertyBag.Clear();
activeBedHotendClippingImage = hotendIndex;
}
}
private void DrawInteractionVolumes(DrawEventArgs e)
{
if(SuppressUiVolumes)