From 229931039bab3fadc610912de1c371e1a11eee97 Mon Sep 17 00:00:00 2001 From: LarsBrubaker Date: Sat, 6 Oct 2018 15:09:01 -0700 Subject: [PATCH 1/4] Added a line for the color editing of all parts Added a color editor to Public Property editor --- .../DesignTools/PublicPropertyEditor.cs | 16 +++- .../PartPreviewWindow/ItemColorButton.cs | 16 +++- .../PartPreviewWindow/SelectedObjectPanel.cs | 26 ++++-- .../View3D/ColorSwatchSelector.cs | 17 ++-- .../UIFields/ColorField.cs | 92 +++++++++++++++++++ 5 files changed, 144 insertions(+), 23 deletions(-) create mode 100644 MatterControlLib/SlicerConfiguration/UIFields/ColorField.cs diff --git a/MatterControlLib/DesignTools/PublicPropertyEditor.cs b/MatterControlLib/DesignTools/PublicPropertyEditor.cs index b5653699d..461379e5a 100644 --- a/MatterControlLib/DesignTools/PublicPropertyEditor.cs +++ b/MatterControlLib/DesignTools/PublicPropertyEditor.cs @@ -101,6 +101,7 @@ namespace MatterHackers.MatterControl.DesignTools private static Type[] allowedTypes = { typeof(double), typeof(int), typeof(char), typeof(string), typeof(bool), + typeof(Color), typeof(Vector2), typeof(Vector3), typeof(DirectionVector), typeof(DirectionAxis), typeof(ChildrenSelector), @@ -187,7 +188,7 @@ namespace MatterHackers.MatterControl.DesignTools return row; } - private static FlowLayoutWidget CreateSettingsRow(string labelText, string toolTipText = null) + public static FlowLayoutWidget CreateSettingsRow(string labelText, string toolTipText = null) { var rowContainer = new FlowLayoutWidget(FlowDirection.LeftToRight) { @@ -299,6 +300,19 @@ namespace MatterHackers.MatterControl.DesignTools rowContainer = CreateSettingsRow(property, field); } + else if (propertyValue is Color color) + { + var field = new ColorField(theme, object3D.Color); + field.Initialize(0); + field.ValueChanged += (s, e) => + { + property.SetValue(field.Color); + object3D?.Invalidate(new InvalidateArgs(context.item, InvalidateType.Properties, undoBuffer)); + propertyGridModifier?.UpdateControls(new PublicPropertyChange(context, property.PropertyInfo.Name)); + }; + + rowContainer = CreateSettingsRow(property, field); + } else if (propertyValue is Vector2 vector2) { var field = new Vector2Field(); diff --git a/MatterControlLib/PartPreviewWindow/ItemColorButton.cs b/MatterControlLib/PartPreviewWindow/ItemColorButton.cs index ea60aa5af..8bd3ff653 100644 --- a/MatterControlLib/PartPreviewWindow/ItemColorButton.cs +++ b/MatterControlLib/PartPreviewWindow/ItemColorButton.cs @@ -41,13 +41,18 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { private ColorButton colorButton; - public ItemColorButton(InteractiveScene scene, ThemeConfig theme) + public event EventHandler ColorChanged; + + public ItemColorButton(ThemeConfig theme, Color selectedColor) { this.ToolTipText = "Color".Localize(); + HAnchor = HAnchor.Fit; + VAnchor = VAnchor.Fit; + this.DynamicPopupContent = () => { - return new ColorSwatchSelector(scene, theme, buttonSize: 16, buttonSpacing: new BorderDouble(1, 1, 0, 0), colorNotifier: (newColor) => colorButton.BackgroundColor = newColor) + return new ColorSwatchSelector(theme, buttonSize: 16, buttonSpacing: new BorderDouble(1, 1, 0, 0), colorNotifier: (newColor) => colorButton.BackgroundColor = newColor) { Padding = theme.DefaultContainerPadding, BackgroundColor = this.HoverColor @@ -56,7 +61,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var scaledButtonSize = 14 * GuiWidget.DeviceScale; - colorButton = new ColorButton(scene.SelectedItem?.Color ?? theme.SlightShade) + colorButton = new ColorButton(selectedColor == Color.Transparent ? theme.SlightShade : selectedColor) { Width = scaledButtonSize, Height = scaledButtonSize, @@ -67,6 +72,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow BorderColor = theme.GetBorderColor(75) }; + colorButton.BackgroundColorChanged += (s, e) => + { + ColorChanged?.Invoke(this, null); + }; + this.AddChild(colorButton); } diff --git a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs index e83a8d166..01c8edcf1 100644 --- a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs +++ b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs @@ -42,6 +42,7 @@ using MatterHackers.Localizations; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.DesignTools; using MatterHackers.MatterControl.Library; +using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.MeshVisualizer; using MatterHackers.VectorMath; using static JsonPath.JsonPathContext.ReflectionValueSystem; @@ -79,13 +80,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var scene = sceneContext.Scene; - var itemColorButton = new ItemColorButton(scene, theme) - { - Width = 30, - Height = 30, - }; - toolbar.AddChild(itemColorButton); - var itemMaterialButton = new ItemMaterialButton(scene, theme) { Width = 30, @@ -179,11 +173,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var selectedItem = scene.SelectedItem; if (selectedItem != null) { - itemColorButton.Color = (selectedItem.Color == Color.Transparent) ? theme.MinimalHighlight : selectedItem.Color; itemMaterialButton.Color = MaterialRendering.Color(selectedItem.MaterialIndex, theme.MinimalHighlight); } - itemColorButton.Enabled = selectedItem != null; itemMaterialButton.Enabled = selectedItem != null; flattenButton.Enabled = selectedItem?.CanFlatten == true; removeButton.Enabled = selectedItem != null; @@ -260,6 +252,22 @@ namespace MatterHackers.MatterControl.PartPreviewWindow bool allowOperations = true; + // put in a color edit field + var field = new ColorField(theme, selectedItem.Color); + field.Initialize(0); + field.ValueChanged += (s, e) => + { + if (selectedItem.Color != field.Color) + { + undoBuffer.AddAndDo(new ChangeColor(selectedItem, field.Color)); + } + }; + + var row = PublicPropertyEditor.CreateSettingsRow("Color".Localize()); + row.AddChild(field.Content); + editorPanel.AddChild(row); + + // put in the normal editor if (selectedItem is ComponentObject3D componentObject && componentObject.Finalized) { diff --git a/MatterControlLib/PartPreviewWindow/View3D/ColorSwatchSelector.cs b/MatterControlLib/PartPreviewWindow/View3D/ColorSwatchSelector.cs index 2c40b3c2b..c4440d52e 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/ColorSwatchSelector.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/ColorSwatchSelector.cs @@ -37,7 +37,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { public class ColorSwatchSelector : FlowLayoutWidget { - public ColorSwatchSelector(InteractiveScene scene, ThemeConfig theme, BorderDouble buttonSpacing, int buttonSize = 32, Action colorNotifier = null) + public ColorSwatchSelector(ThemeConfig theme, BorderDouble buttonSpacing, int buttonSize = 32, Action colorNotifier = null) : base(FlowDirection.TopToBottom) { var scaledButtonSize = buttonSize * GuiWidget.DeviceScale; @@ -61,11 +61,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow for (int colorIndex = 0; colorIndex < colorCount; colorIndex++) { var color = ColorF.FromHSL(colorIndex / (double)colorCount, 1, lightness[rowIndex]).ToColor(); - colorRow.AddChild(MakeColorButton(scene, color, scaledButtonSize, buttonSpacing, colorChanged)); + colorRow.AddChild(MakeColorButton(color, scaledButtonSize, buttonSpacing, colorChanged)); } // put in white and black buttons - colorRow.AddChild(MakeColorButton(scene, grayLevel[rowIndex], scaledButtonSize, buttonSpacing, colorChanged)); + colorRow.AddChild(MakeColorButton(grayLevel[rowIndex], scaledButtonSize, buttonSpacing, colorChanged)); switch(rowIndex) { @@ -79,26 +79,24 @@ namespace MatterHackers.MatterControl.PartPreviewWindow }; resetButton.Click += (s, e) => { - scene.UndoBuffer.AddAndDo(new ChangeColor(scene.SelectedItem, Color.Transparent)); - // The colorChanged action displays the given color - use .MinimalHighlight rather than no color - colorChanged(theme.MinimalHighlight); + colorChanged(Color.Transparent); }; colorRow.AddChild(resetButton); break; case 1: - colorRow.AddChild(MakeColorButton(scene, new Color("#555"), scaledButtonSize, buttonSpacing, colorChanged)); + colorRow.AddChild(MakeColorButton(new Color("#555"), scaledButtonSize, buttonSpacing, colorChanged)); break; case 2: - colorRow.AddChild(MakeColorButton(scene, new Color("#222"), scaledButtonSize, buttonSpacing, colorChanged)); + colorRow.AddChild(MakeColorButton(new Color("#222"), scaledButtonSize, buttonSpacing, colorChanged)); break; } } } - private GuiWidget MakeColorButton(InteractiveScene scene, Color color, double buttonSize, BorderDouble buttonSpacing, Action colorChanged) + private GuiWidget MakeColorButton(Color color, double buttonSize, BorderDouble buttonSpacing, Action colorChanged) { var button = new ColorButton(color) { @@ -111,7 +109,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { UiThread.RunOnIdle(() => { - scene.UndoBuffer.AddAndDo(new ChangeColor(scene.SelectedItem, button.BackgroundColor)); colorChanged(button.BackgroundColor); }); }; diff --git a/MatterControlLib/SlicerConfiguration/UIFields/ColorField.cs b/MatterControlLib/SlicerConfiguration/UIFields/ColorField.cs new file mode 100644 index 000000000..4b9e81dcd --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/UIFields/ColorField.cs @@ -0,0 +1,92 @@ +/* +Copyright (c) 2017, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.Agg; +using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.PartPreviewWindow; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.SlicerConfiguration +{ + public class ColorField : UIField + { + public static readonly int VectorXYEditWidth = (int)(60 * GuiWidget.DeviceScale + .5); + + private ItemColorButton colorWidget; + private ThemeConfig theme; + private Color initialColor; + + public ColorField(ThemeConfig theme, Color initialColor) + { + this.theme = theme; + this.initialColor = initialColor; + } + + public Color Color + { + get + { + return new Color(colorWidget.Color); + } + + set + { + colorWidget.Color = value; + } + } + + public override void Initialize(int tabIndex) + { + var container = new FlowLayoutWidget(); + + colorWidget = new ItemColorButton(theme, initialColor); + colorWidget.ColorChanged += (s, e) => + { + base.OnValueChanged(new FieldChangedEventArgs(true)); + }; + + container.AddChild(colorWidget); + + this.Content = container; + } + + protected override string ConvertValue(string newValue) + { + // Ensure we have a two value CSV or force to '0,0' + return (newValue?.Split(',').Length == 2) ? newValue.Trim() : "0,0"; + } + + protected override void OnValueChanged(FieldChangedEventArgs fieldChangedEventArgs) + { + colorWidget.Color = new Color(this.Value); + + base.OnValueChanged(fieldChangedEventArgs); + } + } +} From b5dacdfa5619e0b62f83c9a882da860d99d0b378 Mon Sep 17 00:00:00 2001 From: LarsBrubaker Date: Sun, 7 Oct 2018 12:12:08 -0700 Subject: [PATCH 2/4] Most of the code to make the material edit show up in the property view is written --- .../PartPreviewWindow/ItemColorButton.cs | 11 ++- .../PartPreviewWindow/ItemMaterialButton.cs | 21 ++++- .../PartPreviewWindow/MaterialControls.cs | 48 +--------- .../PartPreviewWindow/SelectedObjectPanel.cs | 94 ++++++------------- .../View3D/UndoCommands/ChangeMaterial.cs | 86 +++++++++++++++++ .../UIFields/ColorField.cs | 8 -- .../UIFields/MaterialIndexField.cs | 72 ++++++++++++++ 7 files changed, 214 insertions(+), 126 deletions(-) create mode 100644 MatterControlLib/PartPreviewWindow/View3D/UndoCommands/ChangeMaterial.cs create mode 100644 MatterControlLib/SlicerConfiguration/UIFields/MaterialIndexField.cs diff --git a/MatterControlLib/PartPreviewWindow/ItemColorButton.cs b/MatterControlLib/PartPreviewWindow/ItemColorButton.cs index 8bd3ff653..12460428d 100644 --- a/MatterControlLib/PartPreviewWindow/ItemColorButton.cs +++ b/MatterControlLib/PartPreviewWindow/ItemColorButton.cs @@ -46,21 +46,22 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public ItemColorButton(ThemeConfig theme, Color selectedColor) { this.ToolTipText = "Color".Localize(); + var scaledButtonSize = 14 * GuiWidget.DeviceScale; - HAnchor = HAnchor.Fit; - VAnchor = VAnchor.Fit; + Width = 30 * GuiWidget.DeviceScale; + Height = 30 * GuiWidget.DeviceScale; this.DynamicPopupContent = () => { return new ColorSwatchSelector(theme, buttonSize: 16, buttonSpacing: new BorderDouble(1, 1, 0, 0), colorNotifier: (newColor) => colorButton.BackgroundColor = newColor) { Padding = theme.DefaultContainerPadding, - BackgroundColor = this.HoverColor + BackgroundColor = this.HoverColor, + HAnchor = HAnchor.Fit, + VAnchor = VAnchor.Fit }; }; - var scaledButtonSize = 14 * GuiWidget.DeviceScale; - colorButton = new ColorButton(selectedColor == Color.Transparent ? theme.SlightShade : selectedColor) { Width = scaledButtonSize, diff --git a/MatterControlLib/PartPreviewWindow/ItemMaterialButton.cs b/MatterControlLib/PartPreviewWindow/ItemMaterialButton.cs index 6ebdf01f2..ae2c8dffd 100644 --- a/MatterControlLib/PartPreviewWindow/ItemMaterialButton.cs +++ b/MatterControlLib/PartPreviewWindow/ItemMaterialButton.cs @@ -34,6 +34,7 @@ using MatterHackers.Agg.Image; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; +using MatterHackers.MeshVisualizer; namespace MatterHackers.MatterControl.PartPreviewWindow { @@ -41,25 +42,35 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { private ColorButton materialColorButton; - public ItemMaterialButton(InteractiveScene scene, ThemeConfig theme) + public event EventHandler MaterialChanged; + + public ItemMaterialButton(ThemeConfig theme, int initialMaterialIndex) { this.ToolTipText = "Material".Localize(); var scaledButtonSize = 14 * GuiWidget.DeviceScale; + Width = 30 * GuiWidget.DeviceScale; + Height = 30 * GuiWidget.DeviceScale; + this.DynamicPopupContent = () => { - //return new ColorSwatchSelector(scene, theme, buttonSize: 16, buttonSpacing: new BorderDouble(1, 1, 0, 0), colorNotifier: (newColor) => colorButton.BackgroundColor = newColor) - - return new MaterialControls(scene, theme, colorNotifier: (newColor) => materialColorButton.BackgroundColor = newColor) + var materialControl = new MaterialControls(theme, initialMaterialIndex) { Padding = theme.DefaultContainerPadding, BackgroundColor = this.HoverColor, HAnchor = HAnchor.Fit, VAnchor = VAnchor.Fit }; + + materialControl.IndexChanged += (s, e) => + { + MaterialChanged?.Invoke(this, e); + }; + + return materialControl; }; - materialColorButton = new ColorButton(scene.SelectedItem?.Color ?? theme.SlightShade) + materialColorButton = new ColorButton(MaterialRendering.Color(initialMaterialIndex, theme.MinimalHighlight)) { Width = scaledButtonSize, Height = scaledButtonSize, diff --git a/MatterControlLib/PartPreviewWindow/MaterialControls.cs b/MatterControlLib/PartPreviewWindow/MaterialControls.cs index e6ee6a45d..53af628c9 100644 --- a/MatterControlLib/PartPreviewWindow/MaterialControls.cs +++ b/MatterControlLib/PartPreviewWindow/MaterialControls.cs @@ -41,13 +41,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { private ObservableCollection materialButtons = new ObservableCollection(); private ThemeConfig theme; - private InteractiveScene scene; + public event EventHandler IndexChanged; - public MaterialControls(InteractiveScene scene, ThemeConfig theme, Action colorNotifier = null) + public MaterialControls(ThemeConfig theme, int initialMaterialIndex) : base(FlowDirection.TopToBottom) { this.theme = theme; - this.scene = scene; this.HAnchor = HAnchor.Fit; this.VAnchor = VAnchor.Fit; @@ -71,12 +70,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow buttonView.AddChild(new ColorButton(MaterialRendering.Color(extruderIndex, theme.MinimalHighlight)) { - Margin = new BorderDouble(right: 5), Width = scaledButtonSize, Height = scaledButtonSize, VAnchor = VAnchor.Center, DrawGrid = true, - //DoubleBuffer = true }); buttonView.AddChild(new TextWidget(name, pointSize: theme.DefaultFontSize, textColor: theme.Colors.PrimaryTextColor) @@ -95,7 +92,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow HAnchor = HAnchor.Fit, VAnchor = VAnchor.Fit, TextColor = theme.Colors.PrimaryTextColor, - Checked = extruderIndex == scene.SelectedItem.MaterialIndex + Checked = extruderIndex == initialMaterialIndex }; materialButtons.Add(radioButton); this.AddChild(radioButton); @@ -103,50 +100,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow int localExtruderIndex = extruderIndex; radioButton.Click += (sender, e) => { - var selectedItem = scene.SelectedItem; - if (selectedItem != null) - { - selectedItem.MaterialIndex = localExtruderIndex; - - colorNotifier?.Invoke(MaterialRendering.Color(localExtruderIndex, theme.MinimalHighlight)); - - scene.Invalidate(new InvalidateArgs(null, InvalidateType.Material)); - } + IndexChanged?.Invoke(this, localExtruderIndex); }; } - - scene.SelectionChanged += Scene_SelectionChanged; - } - - private void Scene_SelectionChanged(object sender, EventArgs e) - { - var selectedItem = scene.SelectedItem; - - if (selectedItem != null - && materialButtons?.Count > 0) - { - bool setSelection = false; - // Set the material selector to have the correct material button selected - for (int i = 0; i < materialButtons.Count; i++) - { - // the first button is 'Default' so we are looking for the button that is i - 1 (0 = material 1 = button 1) - if (selectedItem.MaterialIndex == i - 1) - { - ((RadioButton)materialButtons[i]).Checked = true; - setSelection = true; - } - } - - if (!setSelection) - { - ((RadioButton)materialButtons[0]).Checked = true; - } - } } public override void OnClosed(EventArgs e) { - scene.SelectionChanged -= Scene_SelectionChanged; base.OnClosed(e); } diff --git a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs index 01c8edcf1..50a59dd6c 100644 --- a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs +++ b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs @@ -80,13 +80,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var scene = sceneContext.Scene; - var itemMaterialButton = new ItemMaterialButton(scene, theme) - { - Width = 30, - Height = 30, - }; - toolbar.AddChild(itemMaterialButton); - // put in a make permanent button var icon = AggContext.StaticData.LoadIcon("noun_766157.png", 16, 16, theme.InvertIcons).SetPreMultiply(); var flattenButton = new IconButton(icon, theme) @@ -171,62 +164,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } var selectedItem = scene.SelectedItem; - if (selectedItem != null) - { - itemMaterialButton.Color = MaterialRendering.Color(selectedItem.MaterialIndex, theme.MinimalHighlight); - } - itemMaterialButton.Enabled = selectedItem != null; flattenButton.Enabled = selectedItem?.CanFlatten == true; removeButton.Enabled = selectedItem != null; overflowButton.Enabled = selectedItem != null; }; } - /// - /// Behavior from removed Edit button - keeping around for reuse as an advanced feature in the future - /// - /// - private async Task EditChildInIsolatedContext() - { - var bed = new BedConfig(ApplicationController.Instance.Library.PartHistory); - - var partPreviewContent = this.Parents().FirstOrDefault(); - partPreviewContent.CreatePartTab( - "New Part", - bed, - theme); - - var clonedItem = this.item.Clone(); - - // Edit in Identity transform - clonedItem.Matrix = Matrix4X4.Identity; - - await bed.LoadContent( - new EditContext() - { - ContentStore = new DynamicContentStore((libraryItem, object3D) => - { - var replacement = object3D.Clone(); - - this.item.Parent.Children.Modify(list => - { - list.Remove(item); - - // Restore matrix of item being replaced - replacement.Matrix = item.Matrix; - - list.Add(replacement); - - item = replacement; - }); - - sceneContext.Scene.SelectedItem = replacement; - }), - SourceItem = new InMemoryLibraryItem(clonedItem), - }); - } - public GuiWidget ContentPanel { get; set; } private JsonPathContext pathResolver = new JsonPathContext(); @@ -253,19 +197,41 @@ namespace MatterHackers.MatterControl.PartPreviewWindow bool allowOperations = true; // put in a color edit field - var field = new ColorField(theme, selectedItem.Color); - field.Initialize(0); - field.ValueChanged += (s, e) => + var colorField = new ColorField(theme, selectedItem.Color); + colorField.Initialize(0); + colorField.ValueChanged += (s, e) => { - if (selectedItem.Color != field.Color) + if (selectedItem.Color != colorField.Color) { - undoBuffer.AddAndDo(new ChangeColor(selectedItem, field.Color)); + undoBuffer.AddAndDo(new ChangeColor(selectedItem, colorField.Color)); } }; - var row = PublicPropertyEditor.CreateSettingsRow("Color".Localize()); - row.AddChild(field.Content); - editorPanel.AddChild(row); + var colorRow = PublicPropertyEditor.CreateSettingsRow("Color".Localize()); + colorRow.AddChild(colorField.Content); + colorField.Content.MouseDown += (s, e) => + { + // make sure the render mode is set to shaded or outline + }; + editorPanel.AddChild(colorRow); + + // put in a material edit field + var materialField = new MaterialIndexField(theme, selectedItem.MaterialIndex); + materialField.Initialize(0); + materialField.ValueChanged += (s, e) => + { + if (selectedItem.MaterialIndex != materialField.MaterialIndex) + { + undoBuffer.AddAndDo(new ChangeMaterial(selectedItem, materialField.MaterialIndex)); + } + }; + + var materialRow = PublicPropertyEditor.CreateSettingsRow("Material".Localize()); + materialRow.AddChild(materialField.Content); + materialField.Content.MouseDown += (s, e) => + { + // make sure the render mode is set to material + }; editorPanel.AddChild(materialRow); // put in the normal editor if (selectedItem is ComponentObject3D componentObject diff --git a/MatterControlLib/PartPreviewWindow/View3D/UndoCommands/ChangeMaterial.cs b/MatterControlLib/PartPreviewWindow/View3D/UndoCommands/ChangeMaterial.cs new file mode 100644 index 000000000..59b2981f5 --- /dev/null +++ b/MatterControlLib/PartPreviewWindow/View3D/UndoCommands/ChangeMaterial.cs @@ -0,0 +1,86 @@ +/* +Copyright (c) 2017, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System.Collections.Generic; +using System.Linq; +using MatterHackers.Agg; +using MatterHackers.Agg.UI; +using MatterHackers.DataConverters3D; + +namespace MatterHackers.MatterControl.PartPreviewWindow +{ + public class ChangeMaterial : IUndoRedoCommand + { + List itemsPrintOutputType = new List(); + List itemsMaterialIndex = new List(); + List itemsToChange = new List(); + int materialIndex; + + public ChangeMaterial(IObject3D selectedItem, int materialIndex) + { + this.materialIndex = materialIndex; + if (selectedItem is SelectionGroupObject3D) + { + SetData(selectedItem.Children.ToList()); + } + else + { + SetData(new List { selectedItem }); + } + } + + void SetData(List itemsToChange) + { + foreach (var item in itemsToChange) + { + this.itemsToChange.Add(item); + this.itemsMaterialIndex.Add(item.MaterialIndex); + this.itemsPrintOutputType.Add(item.OutputType); + } + } + + void IUndoRedoCommand.Do() + { + foreach(var item in this.itemsToChange) + { + item.OutputType = PrintOutputTypes.Solid; + item.MaterialIndex = materialIndex; + } + } + + void IUndoRedoCommand.Undo() + { + for(int i=0; i< this.itemsToChange.Count; i++) + { + itemsToChange[i].OutputType = itemsPrintOutputType[i]; + itemsToChange[i].MaterialIndex = itemsMaterialIndex[i]; + } + } + } +} diff --git a/MatterControlLib/SlicerConfiguration/UIFields/ColorField.cs b/MatterControlLib/SlicerConfiguration/UIFields/ColorField.cs index 4b9e81dcd..52dc84cf5 100644 --- a/MatterControlLib/SlicerConfiguration/UIFields/ColorField.cs +++ b/MatterControlLib/SlicerConfiguration/UIFields/ColorField.cs @@ -36,8 +36,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { public class ColorField : UIField { - public static readonly int VectorXYEditWidth = (int)(60 * GuiWidget.DeviceScale + .5); - private ItemColorButton colorWidget; private ThemeConfig theme; private Color initialColor; @@ -76,12 +74,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration this.Content = container; } - protected override string ConvertValue(string newValue) - { - // Ensure we have a two value CSV or force to '0,0' - return (newValue?.Split(',').Length == 2) ? newValue.Trim() : "0,0"; - } - protected override void OnValueChanged(FieldChangedEventArgs fieldChangedEventArgs) { colorWidget.Color = new Color(this.Value); diff --git a/MatterControlLib/SlicerConfiguration/UIFields/MaterialIndexField.cs b/MatterControlLib/SlicerConfiguration/UIFields/MaterialIndexField.cs new file mode 100644 index 000000000..6196b7cbe --- /dev/null +++ b/MatterControlLib/SlicerConfiguration/UIFields/MaterialIndexField.cs @@ -0,0 +1,72 @@ +/* +Copyright (c) 2017, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.Agg; +using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.PartPreviewWindow; + +namespace MatterHackers.MatterControl.SlicerConfiguration +{ + public class MaterialIndexField : UIField + { + private ItemMaterialButton materialWidget; + private ThemeConfig theme; + + public MaterialIndexField(ThemeConfig theme, int materialIndex) + { + this.theme = theme; + this.MaterialIndex = materialIndex; + } + + public int MaterialIndex { get; set; } + + public override void Initialize(int tabIndex) + { + var container = new FlowLayoutWidget(); + + materialWidget = new ItemMaterialButton(theme, MaterialIndex); + materialWidget.MaterialChanged += (s, e) => + { + MaterialIndex = e; + base.OnValueChanged(new FieldChangedEventArgs(true)); + }; + + container.AddChild(materialWidget); + + this.Content = container; + } + + protected override void OnValueChanged(FieldChangedEventArgs fieldChangedEventArgs) + { + materialWidget.Color = new Color(this.Value); + + base.OnValueChanged(fieldChangedEventArgs); + } + } +} \ No newline at end of file From 593a32cfa6330d6e9b6f677b6c7dc8b477083d7c Mon Sep 17 00:00:00 2001 From: LarsBrubaker Date: Sun, 7 Oct 2018 18:11:02 -0700 Subject: [PATCH 3/4] Finishing color and material buttons in properties panel Added ability to auto switch to view mode for correct setting being changed issue: MatterHackers/MatterControl#3799 When setting color or material, switch to correct view mode --- .../PartPreviewWindow/DropButton.cs | 12 ++-- .../PartPreviewWindow/SelectedObjectPanel.cs | 12 +++- .../View3D/PrinterBar/PrinterActionsBar.cs | 61 +++++++++++-------- .../PartPreviewWindow/View3D/View3DWidget.cs | 4 -- .../PartPreviewWindow/ViewStyleButton.cs | 4 ++ 5 files changed, 55 insertions(+), 38 deletions(-) diff --git a/MatterControlLib/PartPreviewWindow/DropButton.cs b/MatterControlLib/PartPreviewWindow/DropButton.cs index 40b3af745..baa4f2b04 100644 --- a/MatterControlLib/PartPreviewWindow/DropButton.cs +++ b/MatterControlLib/PartPreviewWindow/DropButton.cs @@ -37,7 +37,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { public class DropButton : SimpleButton { - private bool menuVisible; + public bool MenuVisible { get; private set; } public DropButton(ThemeConfig theme) : base(theme) @@ -67,7 +67,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public override Color BackgroundColor { - get => menuVisible ? theme.SlightShade : base.BackgroundColor; + get => MenuVisible ? theme.SlightShade : base.BackgroundColor; set => base.BackgroundColor = value; } @@ -75,14 +75,14 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public override void OnMouseDown(MouseEventArgs mouseEvent) { - downWhileOpen = menuVisible; + downWhileOpen = MenuVisible; base.OnMouseDown(mouseEvent); } public override void OnClick(MouseEventArgs mouseEvent) { - if (!menuVisible + if (!MenuVisible && !downWhileOpen) { var popupContent = this.PopupContent(); @@ -96,12 +96,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow if (this.Parents().FirstOrDefault() is SystemWindow systemWindow) { - menuVisible = true; + MenuVisible = true; void popupContent_Closed(object sender, EventArgs e) { // Reset menuVisible - menuVisible = false; + MenuVisible = false; popupContent.Closed -= popupContent_Closed; } diff --git a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs index 50a59dd6c..7a40994f2 100644 --- a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs +++ b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs @@ -212,6 +212,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow colorField.Content.MouseDown += (s, e) => { // make sure the render mode is set to shaded or outline + if (sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Shaded + && sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Outlines) + { + // make sure the render mode is set to material + sceneContext.ViewState.RenderType = RenderOpenGl.RenderTypes.Outlines; + } }; editorPanel.AddChild(colorRow); @@ -230,7 +236,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow materialRow.AddChild(materialField.Content); materialField.Content.MouseDown += (s, e) => { - // make sure the render mode is set to material + if (sceneContext.ViewState.RenderType != RenderOpenGl.RenderTypes.Materials) + { + // make sure the render mode is set to material + sceneContext.ViewState.RenderType = RenderOpenGl.RenderTypes.Materials; + } }; editorPanel.AddChild(materialRow); // put in the normal editor diff --git a/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrinterActionsBar.cs b/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrinterActionsBar.cs index a4ff88639..a088fbd91 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrinterActionsBar.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrinterActionsBar.cs @@ -199,33 +199,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow if (!buttonIsBeingClicked) { - double displayTime = 2; - double pulseTime = .5; - double totalSeconds = 0; - Color backgroundColor = activeButton.BackgroundColor; - Color hightlightColor = theme.Colors.PrimaryAccentColor.AdjustContrast(theme.Colors.PrimaryTextColor, 6).ToColor(); - // Show a highlight on the button as the user did not click it - Animation flashBackground = null; - flashBackground = new Animation() - { - DrawTarget = activeButton, - FramesPerSecond = 10, - Update = (s1, updateEvent) => - { - totalSeconds += updateEvent.SecondsPassed; - if (totalSeconds < displayTime) - { - double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime); - activeButton.BackgroundColor = new Color(hightlightColor, (int)(blend * 255)); - } - else - { - activeButton.BackgroundColor = backgroundColor; - flashBackground.Stop(); - } - } - }; - flashBackground.Start(); + activeButton.FlashBackground(theme.Colors.PrimaryAccentColor.AdjustContrast(theme.Colors.PrimaryTextColor, 6).ToColor()); } } }; @@ -460,4 +434,37 @@ namespace MatterHackers.MatterControl.PartPreviewWindow }); } } + + public static class WidgetAnimationExtensions + { + public static void FlashBackground(this GuiWidget widget, Color hightlightColor) + { + double displayTime = 2; + double pulseTime = .5; + double totalSeconds = 0; + Color backgroundColor = widget.BackgroundColor; + // Show a highlight on the button as the user did not click it + Animation flashBackground = null; + flashBackground = new Animation() + { + DrawTarget = widget, + FramesPerSecond = 10, + Update = (s1, updateEvent) => + { + totalSeconds += updateEvent.SecondsPassed; + if (totalSeconds < displayTime) + { + double blend = AttentionGetter.GetFadeInOutPulseRatio(totalSeconds, pulseTime); + widget.BackgroundColor = new Color(hightlightColor, (int)(blend * 255)); + } + else + { + widget.BackgroundColor = backgroundColor; + flashBackground.Stop(); + } + } + }; + flashBackground.Start(); + } + } } \ No newline at end of file diff --git a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs index d75cbae42..556b36b8c 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs @@ -55,8 +55,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public readonly int EditButtonHeight = 44; - private bool hasDrawn = false; - private Color[] SelectionColors = new Color[] { new Color(131, 4, 66), new Color(227, 31, 61), new Color(255, 148, 1), new Color(247, 224, 23), new Color(143, 212, 1) }; private Stopwatch timeSinceLastSpin = new Stopwatch(); private Stopwatch timeSinceReported = new Stopwatch(); @@ -673,8 +671,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } - hasDrawn = true; - base.OnDraw(graphics2D); if (selectedItem != null) diff --git a/MatterControlLib/PartPreviewWindow/ViewStyleButton.cs b/MatterControlLib/PartPreviewWindow/ViewStyleButton.cs index 5cac0d29f..c263ebc31 100644 --- a/MatterControlLib/PartPreviewWindow/ViewStyleButton.cs +++ b/MatterControlLib/PartPreviewWindow/ViewStyleButton.cs @@ -76,6 +76,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow if (e.Data == UserSettingsKey.defaultRenderSetting) { iconButton.SetIcon(viewIcons[sceneContext.ViewState.RenderType]); + if (!this.MenuVisible) + { + iconButton.FlashBackground(theme.Colors.PrimaryAccentColor.AdjustContrast(theme.Colors.PrimaryTextColor, 6).ToColor()); + } } } From 7b5ae761f3920526b8fd1765453238e368448522 Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Mon, 8 Oct 2018 09:09:42 -0700 Subject: [PATCH 4/4] Implement missing field tests --- .../MatterControl/SliceSettingsFieldTests.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/MatterControl.Tests/MatterControl/SliceSettingsFieldTests.cs b/Tests/MatterControl.Tests/MatterControl/SliceSettingsFieldTests.cs index 2dadac7d9..0e053c282 100644 --- a/Tests/MatterControl.Tests/MatterControl/SliceSettingsFieldTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/SliceSettingsFieldTests.cs @@ -288,6 +288,18 @@ namespace MatterControl.Tests.MatterControl Assert.Fail(); } + [Test, Ignore("Not Implemented")] + public void MaterialIndexFieldTest() + { + Assert.Fail(); + } + + [Test, Ignore("Not Implemented")] + public void ColorFieldTest() + { + Assert.Fail(); + } + [Test, Ignore("Not Implemented")] public void ChildrenSelectorListFieldTest() {