2017-06-21 23:26:20 -07:00
|
|
|
|
/*
|
2019-01-30 08:08:24 -08:00
|
|
|
|
Copyright (c) 2019, Lars Brubaker
|
2017-06-21 23:26:20 -07:00
|
|
|
|
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.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2017-07-18 18:15:10 -07:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
2017-06-21 23:26:20 -07:00
|
|
|
|
using MatterHackers.Agg;
|
2018-01-23 13:48:21 -08:00
|
|
|
|
using MatterHackers.Agg.Image;
|
2017-06-21 23:26:20 -07:00
|
|
|
|
using MatterHackers.Agg.UI;
|
|
|
|
|
|
using MatterHackers.DataConverters3D;
|
2018-12-21 08:27:40 -08:00
|
|
|
|
using MatterHackers.MatterControl.DesignTools;
|
2018-06-05 13:38:25 -07:00
|
|
|
|
using MatterHackers.MatterControl.PartPreviewWindow.View3D;
|
2019-01-31 07:33:42 -08:00
|
|
|
|
using MatterHackers.MeshVisualizer;
|
2017-06-21 23:26:20 -07:00
|
|
|
|
using MatterHackers.PolygonMesh;
|
|
|
|
|
|
using MatterHackers.RenderOpenGl;
|
|
|
|
|
|
using MatterHackers.RenderOpenGl.OpenGl;
|
|
|
|
|
|
using MatterHackers.VectorMath;
|
|
|
|
|
|
|
2019-01-31 07:33:42 -08:00
|
|
|
|
namespace MatterHackers.MatterControl.PartPreviewWindow
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2019-01-31 07:33:42 -08:00
|
|
|
|
public partial class InteractionLayer : GuiWidget
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2018-07-20 15:40:14 -07:00
|
|
|
|
private static ImageBuffer ViewOnlyTexture;
|
2018-01-23 13:48:21 -08:00
|
|
|
|
|
2018-02-02 18:19:23 -08:00
|
|
|
|
private Color lightWireframe = new Color("#aaa4");
|
|
|
|
|
|
private Color darkWireframe = new Color("#3334");
|
|
|
|
|
|
private Color gCodeMeshColor;
|
|
|
|
|
|
|
2018-07-20 15:40:14 -07:00
|
|
|
|
private InteractiveScene scene;
|
2017-06-21 23:26:20 -07:00
|
|
|
|
|
2019-02-01 16:12:12 -08:00
|
|
|
|
private ISceneContext sceneContext;
|
2017-08-16 17:13:16 -07:00
|
|
|
|
|
2018-10-18 12:42:14 -07:00
|
|
|
|
private ThemeConfig theme;
|
2019-01-31 08:07:19 -08:00
|
|
|
|
private FloorDrawable floorDrawable;
|
2019-01-31 22:04:39 -08:00
|
|
|
|
|
|
|
|
|
|
private ModelRenderStyle modelRenderStyle = ModelRenderStyle.Wireframe;
|
|
|
|
|
|
|
2019-01-31 22:37:52 -08:00
|
|
|
|
private List<IDrawable> drawables = new List<IDrawable>();
|
|
|
|
|
|
private List<IDrawableItem> itemDrawables = new List<IDrawableItem>();
|
2018-07-05 15:15:56 -07:00
|
|
|
|
|
2017-06-21 23:26:20 -07:00
|
|
|
|
public bool AllowBedRenderingWhenEmpty { get; set; }
|
|
|
|
|
|
|
2017-10-31 11:43:25 -07:00
|
|
|
|
public Color BuildVolumeColor { get; set; }
|
2017-06-21 23:26:20 -07:00
|
|
|
|
|
|
|
|
|
|
public override void OnLoad(EventArgs args)
|
|
|
|
|
|
{
|
2019-02-02 13:52:26 -08:00
|
|
|
|
drawables.AddRange(new IDrawable[]
|
2019-02-01 12:45:04 -08:00
|
|
|
|
{
|
2019-02-02 13:52:26 -08:00
|
|
|
|
new AxisIndicatorDrawable(),
|
|
|
|
|
|
new SceneTraceDataDrawable(sceneContext),
|
|
|
|
|
|
new AABBDrawable(sceneContext)
|
2019-02-01 12:45:04 -08:00
|
|
|
|
});
|
2019-02-02 13:52:26 -08:00
|
|
|
|
|
|
|
|
|
|
itemDrawables.AddRange(new IDrawableItem[]
|
2019-02-01 12:45:04 -08:00
|
|
|
|
{
|
2019-02-02 13:52:26 -08:00
|
|
|
|
new SelectedItemDrawable(sceneContext, this),
|
2019-02-02 13:52:46 -08:00
|
|
|
|
new ItemTraceDataDrawable(sceneContext)
|
2019-02-01 12:45:04 -08:00
|
|
|
|
});
|
2019-01-31 22:37:52 -08:00
|
|
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
|
itemDrawables.Add(new InspectedItemDrawable(sceneContext));
|
|
|
|
|
|
#endif
|
2019-01-31 22:04:39 -08:00
|
|
|
|
|
2019-02-02 00:03:09 -08:00
|
|
|
|
base.OnLoad(args);
|
2018-11-16 08:44:56 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-30 08:17:01 -08:00
|
|
|
|
public override List<WidgetAndPosition> FindDescendants(IEnumerable<string> namesToSearchFor, List<WidgetAndPosition> foundChildren, RectangleDouble touchingBounds, SearchType seachType, bool allowInvalidItems = true)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2019-01-31 07:33:42 -08:00
|
|
|
|
foreach (InteractionVolume child in this.InteractionVolumes)
|
2017-10-26 17:57:17 -07:00
|
|
|
|
{
|
|
|
|
|
|
string object3DName = child.Name;
|
|
|
|
|
|
|
|
|
|
|
|
bool nameFound = false;
|
|
|
|
|
|
|
2018-12-30 08:17:01 -08:00
|
|
|
|
foreach (var nameToSearchFor in namesToSearchFor)
|
2017-10-26 17:57:17 -07:00
|
|
|
|
{
|
2018-12-30 08:17:01 -08:00
|
|
|
|
if (seachType == SearchType.Exact)
|
2017-10-26 17:57:17 -07:00
|
|
|
|
{
|
2018-12-30 08:17:01 -08:00
|
|
|
|
if (object3DName == nameToSearchFor)
|
|
|
|
|
|
{
|
|
|
|
|
|
nameFound = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-10-26 17:57:17 -07:00
|
|
|
|
}
|
2018-12-30 08:17:01 -08:00
|
|
|
|
else
|
2017-10-26 17:57:17 -07:00
|
|
|
|
{
|
2018-12-30 08:17:01 -08:00
|
|
|
|
if (nameToSearchFor == ""
|
|
|
|
|
|
|| object3DName.Contains(nameToSearchFor))
|
|
|
|
|
|
{
|
|
|
|
|
|
nameFound = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-10-26 17:57:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-10-27 14:19:26 -07:00
|
|
|
|
if (nameFound
|
|
|
|
|
|
&& child.CollisionVolume != null)
|
2017-10-26 17:57:17 -07:00
|
|
|
|
{
|
|
|
|
|
|
AxisAlignedBoundingBox bounds = child.CollisionVolume.GetAxisAlignedBoundingBox();
|
|
|
|
|
|
bounds = bounds.NewTransformed(child.TotalTransform);
|
|
|
|
|
|
|
|
|
|
|
|
RectangleDouble screenBoundsOfObject3D = RectangleDouble.ZeroIntersection;
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetTopCorner(i)));
|
|
|
|
|
|
screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetBottomCorner(i)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (touchingBounds.IsTouching(screenBoundsOfObject3D))
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector3 renderPosition = bounds.Center;
|
|
|
|
|
|
Vector2 objectCenterScreenSpace = this.World.GetScreenPosition(renderPosition);
|
2017-10-31 12:51:16 -07:00
|
|
|
|
Point2D screenPositionOfObject3D = new Point2D((int)objectCenterScreenSpace.X, (int)objectCenterScreenSpace.Y);
|
2017-10-26 17:57:17 -07:00
|
|
|
|
|
2017-10-27 14:19:26 -07:00
|
|
|
|
foundChildren.Add(new WidgetAndPosition(this, screenPositionOfObject3D, object3DName, child));
|
2017-10-26 17:57:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-14 08:57:24 -07:00
|
|
|
|
foreach (var child in scene.Children)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
string object3DName = child.Name;
|
|
|
|
|
|
if (object3DName == null && child.MeshPath != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
object3DName = Path.GetFileName(child.MeshPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nameFound = false;
|
|
|
|
|
|
|
2018-12-30 08:17:01 -08:00
|
|
|
|
foreach (var nameToSearchFor in namesToSearchFor)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2018-12-30 08:17:01 -08:00
|
|
|
|
if (seachType == SearchType.Exact)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2018-12-30 08:17:01 -08:00
|
|
|
|
if (object3DName == nameToSearchFor)
|
|
|
|
|
|
{
|
|
|
|
|
|
nameFound = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-06-21 23:26:20 -07:00
|
|
|
|
}
|
2018-12-30 08:17:01 -08:00
|
|
|
|
else
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2018-12-30 08:17:01 -08:00
|
|
|
|
if (nameToSearchFor == ""
|
|
|
|
|
|
|| object3DName.Contains(nameToSearchFor))
|
|
|
|
|
|
{
|
|
|
|
|
|
nameFound = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-06-21 23:26:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (nameFound)
|
|
|
|
|
|
{
|
|
|
|
|
|
AxisAlignedBoundingBox bounds = child.TraceData().GetAxisAlignedBoundingBox();
|
|
|
|
|
|
|
|
|
|
|
|
RectangleDouble screenBoundsOfObject3D = RectangleDouble.ZeroIntersection;
|
|
|
|
|
|
for(int i=0; i<4; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetTopCorner(i)));
|
|
|
|
|
|
screenBoundsOfObject3D.ExpandToInclude(this.World.GetScreenPosition(bounds.GetBottomCorner(i)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (touchingBounds.IsTouching(screenBoundsOfObject3D))
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector3 renderPosition = bounds.Center;
|
|
|
|
|
|
Vector2 objectCenterScreenSpace = this.World.GetScreenPosition(renderPosition);
|
2017-10-31 12:51:16 -07:00
|
|
|
|
Point2D screenPositionOfObject3D = new Point2D((int)objectCenterScreenSpace.X, (int)objectCenterScreenSpace.Y);
|
2017-06-21 23:26:20 -07:00
|
|
|
|
|
2017-10-27 14:19:26 -07:00
|
|
|
|
foundChildren.Add(new WidgetAndPosition(this, screenPositionOfObject3D, object3DName, child));
|
2017-06-21 23:26:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-30 08:17:01 -08:00
|
|
|
|
return base.FindDescendants(namesToSearchFor, foundChildren, touchingBounds, seachType, allowInvalidItems);
|
2017-06-21 23:26:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-12-21 08:27:40 -08:00
|
|
|
|
private void DrawObject(IObject3D object3D, List<Object3DView> transparentMeshes, DrawEventArgs e)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2018-12-21 08:27:40 -08:00
|
|
|
|
var selectedItem = scene.SelectedItem;
|
|
|
|
|
|
|
2017-11-28 15:34:49 -08:00
|
|
|
|
foreach (var item in object3D.VisibleMeshes())
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2018-01-23 13:48:21 -08:00
|
|
|
|
// check for correct persistable rendering
|
2019-01-31 07:33:42 -08:00
|
|
|
|
if(InteractionLayer.ViewOnlyTexture != null
|
2018-05-29 17:46:59 -07:00
|
|
|
|
&& item.Mesh.Faces.Count > 0)
|
2018-01-23 13:48:21 -08:00
|
|
|
|
{
|
|
|
|
|
|
ImageBuffer faceTexture = null;
|
2019-01-11 16:49:34 -08:00
|
|
|
|
|
|
|
|
|
|
//item.Mesh.FaceTexture.TryGetValue((item.Mesh.Faces[0], 0), out faceTexture);
|
2019-01-31 07:33:42 -08:00
|
|
|
|
bool hasPersistableTexture = faceTexture == InteractionLayer.ViewOnlyTexture;
|
2018-01-23 13:48:21 -08:00
|
|
|
|
|
2018-05-29 17:46:59 -07:00
|
|
|
|
if (item.WorldPersistable())
|
2018-01-23 13:48:21 -08:00
|
|
|
|
{
|
|
|
|
|
|
if (hasPersistableTexture)
|
|
|
|
|
|
{
|
|
|
|
|
|
// make sure it does not have the view only texture
|
2018-05-29 17:46:59 -07:00
|
|
|
|
item.Mesh.RemoveTexture(ViewOnlyTexture, 0);
|
2018-01-23 13:48:21 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!hasPersistableTexture)
|
|
|
|
|
|
{
|
|
|
|
|
|
// make sure it does have the view only texture
|
2018-05-29 17:46:59 -07:00
|
|
|
|
var aabb = item.Mesh.GetAxisAlignedBoundingBox();
|
2018-01-23 13:48:21 -08:00
|
|
|
|
var matrix = Matrix4X4.CreateScale(.5, .5, 1);
|
|
|
|
|
|
matrix *= Matrix4X4.CreateRotationZ(MathHelper.Tau / 8);
|
2018-05-29 17:46:59 -07:00
|
|
|
|
item.Mesh.PlaceTexture(ViewOnlyTexture, matrix);
|
2018-01-23 13:48:21 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-02-01 14:47:05 -08:00
|
|
|
|
Color drawColor = this.GetItemColor(item, selectedItem);
|
2017-08-01 17:38:07 -07:00
|
|
|
|
|
2019-02-01 14:47:05 -08:00
|
|
|
|
bool hasTransparentTextures = item.Mesh.FaceTextures.Any(ft => ft.Value.image.HasTransparency);
|
2019-01-11 16:49:34 -08:00
|
|
|
|
|
2018-03-05 10:24:26 -08:00
|
|
|
|
if ((drawColor.alpha == 255
|
2019-01-11 16:49:34 -08:00
|
|
|
|
&& !hasTransparentTextures)
|
2019-01-31 22:29:21 -08:00
|
|
|
|
|| (item == scene.DebugItem))
|
2017-08-25 12:39:52 -07:00
|
|
|
|
{
|
2018-02-02 18:33:35 -08:00
|
|
|
|
// Render as solid
|
2018-11-01 09:36:58 -07:00
|
|
|
|
GLHelper.Render(item.Mesh,
|
|
|
|
|
|
drawColor,
|
|
|
|
|
|
item.WorldMatrix(),
|
|
|
|
|
|
sceneContext.ViewState.RenderType,
|
|
|
|
|
|
item.WorldMatrix() * World.ModelviewMatrix,
|
2018-10-11 07:57:23 -07:00
|
|
|
|
darkWireframe, () => Invalidate());
|
2017-08-25 12:39:52 -07:00
|
|
|
|
}
|
2018-02-02 18:19:23 -08:00
|
|
|
|
else if (drawColor != Color.Transparent)
|
2017-08-25 12:39:52 -07:00
|
|
|
|
{
|
2018-02-02 18:33:35 -08:00
|
|
|
|
// Queue for transparency
|
2018-05-29 17:46:59 -07:00
|
|
|
|
transparentMeshes.Add(new Object3DView(item, drawColor));
|
2017-08-25 12:39:52 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-07-05 15:15:56 -07:00
|
|
|
|
bool isSelected = selectedItem != null
|
2018-06-05 13:38:25 -07:00
|
|
|
|
&& (selectedItem.DescendantsAndSelf().Any((i) => i == item)
|
2018-06-21 21:02:37 -07:00
|
|
|
|
|| selectedItem.Parents<ModifiedMeshObject3D>().Any((mw) => mw == item));
|
2018-02-02 18:00:21 -08:00
|
|
|
|
|
2019-01-31 22:37:52 -08:00
|
|
|
|
// Invoke all item Drawables
|
2019-02-02 13:53:59 -08:00
|
|
|
|
foreach(var drawable in itemDrawables.Where(d => d.DrawStage != DrawStage.Last && d.Enabled))
|
2019-01-31 22:37:52 -08:00
|
|
|
|
{
|
2019-02-02 00:03:09 -08:00
|
|
|
|
drawable.Draw(this, item, isSelected, e, Matrix4X4.Identity, this.World);
|
2019-01-31 22:37:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-25 12:39:52 -07:00
|
|
|
|
// turn lighting back on after rendering selection outlines
|
|
|
|
|
|
GL.Enable(EnableCap.Lighting);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-08-03 11:59:27 -07:00
|
|
|
|
|
2019-02-01 14:47:05 -08:00
|
|
|
|
private Color GetItemColor(IObject3D item, IObject3D selectedItem)
|
2017-11-28 15:34:49 -08:00
|
|
|
|
{
|
2018-02-04 00:38:50 -08:00
|
|
|
|
Color drawColor = item.WorldColor();
|
|
|
|
|
|
if (item.WorldOutputType() == PrintOutputTypes.Support)
|
2017-11-28 15:34:49 -08:00
|
|
|
|
{
|
|
|
|
|
|
drawColor = new Color(Color.Yellow, 120);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If there is a printer - check if the object is within the bed volume (has no AABB outside the bed volume)
|
|
|
|
|
|
if (sceneContext.Printer != null)
|
|
|
|
|
|
{
|
2018-08-23 13:24:48 -07:00
|
|
|
|
if (!sceneContext.Printer.InsideBuildVolume(item))
|
2017-11-28 15:34:49 -08:00
|
|
|
|
{
|
|
|
|
|
|
drawColor = new Color(drawColor, 65);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// check if we should be rendering materials (this overrides the other colors)
|
2018-05-09 08:41:29 -07:00
|
|
|
|
if (sceneContext.ViewState.RenderType == RenderTypes.Materials)
|
2017-11-28 15:34:49 -08:00
|
|
|
|
{
|
2018-02-04 00:38:50 -08:00
|
|
|
|
drawColor = MaterialRendering.Color(item.WorldMaterialIndex());
|
2017-11-28 15:34:49 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-14 12:55:56 -08:00
|
|
|
|
if(drawColor.alpha != 255
|
2017-12-15 15:22:35 -08:00
|
|
|
|
&& item is Object3D item3D)
|
2017-12-14 12:55:56 -08:00
|
|
|
|
{
|
2017-12-15 15:22:35 -08:00
|
|
|
|
item3D.EnsureTransparentSorting();
|
2017-12-14 12:55:56 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-02-01 14:47:05 -08:00
|
|
|
|
if (selectedItem is ISelectableChildContainer selectableChildContainer)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (item.AncestorsAndSelf().Any(i => selectableChildContainer.SelectedChildren.Contains(i.ID)))
|
|
|
|
|
|
{
|
|
|
|
|
|
drawColor = new Color(drawColor, 200);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!sceneContext.ViewState.ModelView)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (modelRenderStyle == ModelRenderStyle.WireframeAndSolid)
|
|
|
|
|
|
{
|
|
|
|
|
|
drawColor = gCodeMeshColor;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (modelRenderStyle == ModelRenderStyle.Wireframe)
|
|
|
|
|
|
{
|
|
|
|
|
|
drawColor = new Color(gCodeMeshColor, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (modelRenderStyle == ModelRenderStyle.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
drawColor = Color.Transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-11-28 15:34:49 -08:00
|
|
|
|
return drawColor;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-17 10:52:47 -07:00
|
|
|
|
public enum EditorType { Printer, Part }
|
|
|
|
|
|
|
|
|
|
|
|
public EditorType EditorMode { get; set; } = EditorType.Part;
|
2017-08-16 17:13:16 -07:00
|
|
|
|
|
2018-02-02 18:19:23 -08:00
|
|
|
|
private int BackToFrontXY(Object3DView a, Object3DView b)
|
2017-08-25 12:39:52 -07:00
|
|
|
|
{
|
2018-02-09 12:24:04 -08:00
|
|
|
|
var meshA = a.Object3D.Mesh;
|
|
|
|
|
|
var meshB = b.Object3D.Mesh;
|
|
|
|
|
|
|
|
|
|
|
|
if (meshA == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (meshB == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-11 16:49:34 -08:00
|
|
|
|
var aCenterWorld = Vector3Ex.Transform(meshA.GetAxisAlignedBoundingBox().Center, a.Object3D.Matrix);
|
2017-10-31 12:51:16 -07:00
|
|
|
|
aCenterWorld.Z = 0; // we only want to look at the distance on xy in world space
|
2019-01-11 16:49:34 -08:00
|
|
|
|
var aCenterInViewSpace = Vector3Ex.Transform(aCenterWorld, World.ModelviewMatrix);
|
2017-08-25 12:39:52 -07:00
|
|
|
|
|
2019-01-11 16:49:34 -08:00
|
|
|
|
var bCenterWorld = Vector3Ex.Transform(meshB.GetAxisAlignedBoundingBox().Center, b.Object3D.Matrix);
|
2017-10-31 12:51:16 -07:00
|
|
|
|
bCenterWorld.Z = 0; // we only want to look at the distance on xy in world space
|
2019-01-11 16:49:34 -08:00
|
|
|
|
var bCenterInViewSpace = Vector3Ex.Transform(bCenterWorld, World.ModelviewMatrix);
|
2017-08-25 12:39:52 -07:00
|
|
|
|
|
|
|
|
|
|
return bCenterInViewSpace.LengthSquared.CompareTo(aCenterInViewSpace.LengthSquared);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-02-01 11:59:29 -08:00
|
|
|
|
private void DrawGlContent(DrawEventArgs e)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2018-02-02 18:19:23 -08:00
|
|
|
|
var gcodeOptions = sceneContext.RendererOptions;
|
|
|
|
|
|
|
2019-01-19 15:20:48 -08:00
|
|
|
|
if (gcodeOptions.GCodeModelView)
|
2018-02-02 18:19:23 -08:00
|
|
|
|
{
|
2019-01-19 15:20:48 -08:00
|
|
|
|
modelRenderStyle = ModelRenderStyle.WireframeAndSolid;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
modelRenderStyle = ModelRenderStyle.None;
|
2018-02-02 18:19:23 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-02-01 21:51:46 -08:00
|
|
|
|
foreach (var drawable in drawables.Where(d => d.DrawStage == DrawStage.First))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (drawable.Enabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
drawable.Draw(this, e, Matrix4X4.Identity, this.World);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GLHelper.SetGlContext(this.World, renderSource.TransformToScreenSpace(renderSource.LocalBounds), lighting);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var drawable in drawables.Where(d => d.DrawStage == DrawStage.OpaqueContent))
|
2019-02-01 12:30:40 -08:00
|
|
|
|
{
|
2019-02-01 12:31:18 -08:00
|
|
|
|
if (drawable.Enabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
drawable.Draw(this, e, Matrix4X4.Identity, this.World);
|
|
|
|
|
|
}
|
2019-02-01 12:30:40 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-02 18:19:23 -08:00
|
|
|
|
// Draw solid objects, extract transparent
|
|
|
|
|
|
var transparentMeshes = new List<Object3DView>();
|
2019-02-01 11:58:19 -08:00
|
|
|
|
|
2019-02-13 10:26:02 -08:00
|
|
|
|
var selectedItem = scene.SelectedItem;
|
|
|
|
|
|
bool suppressNormalDraw = false;
|
|
|
|
|
|
if (selectedItem != null)
|
|
|
|
|
|
{
|
2019-02-01 11:58:19 -08:00
|
|
|
|
// Invoke existing IEditorDraw when iterating items
|
2019-02-13 10:26:02 -08:00
|
|
|
|
if (selectedItem is IEditorDraw editorDraw)
|
2019-02-01 11:58:19 -08:00
|
|
|
|
{
|
|
|
|
|
|
// TODO: Putting the drawing code in the IObject3D means almost certain bindings to MatterControl in IObject3D. If instead
|
|
|
|
|
|
// we had a UI layer object that used binding to register scene drawing hooks for specific types, we could avoid the bindings
|
2019-02-13 10:26:02 -08:00
|
|
|
|
editorDraw.DrawEditor(this, transparentMeshes, e, ref suppressNormalDraw);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in scene.Children)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (item.Visible
|
|
|
|
|
|
&& (item != selectedItem || suppressNormalDraw == false))
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawObject(item, transparentMeshes, e);
|
2019-02-01 11:58:19 -08:00
|
|
|
|
}
|
2017-06-21 23:26:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-25 12:39:52 -07:00
|
|
|
|
transparentMeshes.Sort(BackToFrontXY);
|
|
|
|
|
|
|
2019-01-11 16:49:34 -08:00
|
|
|
|
var bedNormalInViewSpace = Vector3Ex.TransformNormal(Vector3.UnitZ, World.ModelviewMatrix).GetNormal();
|
|
|
|
|
|
var pointOnBedInViewSpace = Vector3Ex.Transform(new Vector3(10, 10, 0), World.ModelviewMatrix);
|
|
|
|
|
|
var lookingDownOnBed = Vector3Ex.Dot(bedNormalInViewSpace, pointOnBedInViewSpace) < 0;
|
2017-08-25 12:39:52 -07:00
|
|
|
|
|
2019-01-31 08:07:19 -08:00
|
|
|
|
floorDrawable.LookingDownOnBed = lookingDownOnBed;
|
|
|
|
|
|
|
2017-08-25 12:39:52 -07:00
|
|
|
|
if (lookingDownOnBed)
|
|
|
|
|
|
{
|
2019-01-31 08:07:19 -08:00
|
|
|
|
floorDrawable.Draw(this, e, Matrix4X4.Identity, this.World);
|
2017-11-28 15:41:41 -08:00
|
|
|
|
}
|
2017-11-28 15:34:49 -08:00
|
|
|
|
|
2018-09-20 15:18:06 -07:00
|
|
|
|
var wireColor = Color.Transparent;
|
|
|
|
|
|
switch(modelRenderStyle)
|
|
|
|
|
|
{
|
|
|
|
|
|
case ModelRenderStyle.Wireframe:
|
|
|
|
|
|
wireColor = darkWireframe;
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case ModelRenderStyle.WireframeAndSolid:
|
|
|
|
|
|
wireColor = lightWireframe;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2019-01-31 13:45:49 -08:00
|
|
|
|
|
2018-02-02 18:19:23 -08:00
|
|
|
|
// Draw transparent objects
|
|
|
|
|
|
foreach (var item in transparentMeshes)
|
2017-11-28 15:41:41 -08:00
|
|
|
|
{
|
2018-02-02 18:19:23 -08:00
|
|
|
|
var object3D = item.Object3D;
|
2017-11-28 15:41:41 -08:00
|
|
|
|
GLHelper.Render(
|
|
|
|
|
|
object3D.Mesh,
|
2018-02-02 18:19:23 -08:00
|
|
|
|
item.Color,
|
2018-02-04 00:38:50 -08:00
|
|
|
|
object3D.WorldMatrix(),
|
2017-11-28 15:41:41 -08:00
|
|
|
|
RenderTypes.Outlines,
|
2018-02-04 00:38:50 -08:00
|
|
|
|
object3D.WorldMatrix() * World.ModelviewMatrix,
|
2018-09-20 15:18:06 -07:00
|
|
|
|
wireColor);
|
2017-08-25 12:39:52 -07:00
|
|
|
|
}
|
2017-11-28 15:41:41 -08:00
|
|
|
|
|
|
|
|
|
|
if (!lookingDownOnBed)
|
2017-08-25 12:39:52 -07:00
|
|
|
|
{
|
2019-01-31 08:07:19 -08:00
|
|
|
|
floorDrawable.Draw(this, e, Matrix4X4.Identity, this.World);
|
2017-08-25 12:39:52 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DrawInteractionVolumes(e);
|
2017-10-21 16:09:39 -07:00
|
|
|
|
|
2019-02-01 21:51:46 -08:00
|
|
|
|
foreach (var drawable in drawables.Where(d => d.DrawStage == DrawStage.TransparentContent))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (drawable.Enabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
drawable.Draw(this, e, Matrix4X4.Identity, this.World);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GLHelper.UnsetGlContext();
|
|
|
|
|
|
|
2019-02-02 13:53:59 -08:00
|
|
|
|
// Invoke DrawStage.Last item drawables
|
|
|
|
|
|
foreach (var item in scene.Children)
|
|
|
|
|
|
{
|
|
|
|
|
|
// HACK: Consider how shared code in DrawObject can be reused to prevent duplicate execution
|
|
|
|
|
|
bool isSelected = selectedItem != null
|
|
|
|
|
|
&& (selectedItem.DescendantsAndSelf().Any((i) => i == item)
|
|
|
|
|
|
|| selectedItem.Parents<ModifiedMeshObject3D>().Any((mw) => mw == item));
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var itemDrawable in itemDrawables.Where(d => d.DrawStage == DrawStage.Last && d.Enabled))
|
|
|
|
|
|
{
|
|
|
|
|
|
itemDrawable.Draw(this, item, isSelected, e, Matrix4X4.Identity, this.World);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Invoke DrawStage.Last scene drawables
|
2019-02-01 21:51:46 -08:00
|
|
|
|
foreach (var drawable in drawables.Where(d => d.DrawStage == DrawStage.Last))
|
2019-01-31 22:04:39 -08:00
|
|
|
|
{
|
2019-02-01 12:31:18 -08:00
|
|
|
|
if (drawable.Enabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
drawable.Draw(this, e, Matrix4X4.Identity, this.World);
|
|
|
|
|
|
}
|
2019-01-31 22:04:39 -08:00
|
|
|
|
}
|
2017-08-25 12:39:52 -07:00
|
|
|
|
}
|
2017-06-21 23:26:20 -07:00
|
|
|
|
|
2017-08-24 13:58:06 -07:00
|
|
|
|
private void DrawInteractionVolumes(DrawEventArgs e)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
if(SuppressUiVolumes)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// draw on top of anything that is already drawn
|
2019-01-31 07:33:42 -08:00
|
|
|
|
foreach (InteractionVolume interactionVolume in this.InteractionVolumes)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
|
|
|
|
|
if (interactionVolume.DrawOnTop)
|
|
|
|
|
|
{
|
|
|
|
|
|
GL.Disable(EnableCap.DepthTest);
|
2017-08-24 13:58:06 -07:00
|
|
|
|
interactionVolume.DrawGlContent(new DrawGlContentEventArgs(false, e));
|
2017-06-21 23:26:20 -07:00
|
|
|
|
GL.Enable(EnableCap.DepthTest);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Draw again setting the depth buffer and ensuring that all the interaction objects are sorted as well as we can
|
2019-01-31 07:33:42 -08:00
|
|
|
|
foreach (InteractionVolume interactionVolume in this.InteractionVolumes)
|
2017-06-21 23:26:20 -07:00
|
|
|
|
{
|
2017-08-24 13:58:06 -07:00
|
|
|
|
interactionVolume.DrawGlContent(new DrawGlContentEventArgs(true, e));
|
2017-06-21 23:26:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-02-02 18:19:23 -08:00
|
|
|
|
|
|
|
|
|
|
public enum ModelRenderStyle
|
|
|
|
|
|
{
|
|
|
|
|
|
Solid,
|
|
|
|
|
|
Wireframe,
|
|
|
|
|
|
WireframeAndSolid,
|
|
|
|
|
|
None
|
|
|
|
|
|
}
|
2019-02-13 10:26:02 -08:00
|
|
|
|
}
|
2018-02-02 18:19:23 -08:00
|
|
|
|
|
2019-02-13 10:26:02 -08:00
|
|
|
|
public class Object3DView
|
|
|
|
|
|
{
|
|
|
|
|
|
public Color Color { get; set; }
|
2018-02-02 18:19:23 -08:00
|
|
|
|
|
2019-02-13 10:26:02 -08:00
|
|
|
|
public IObject3D Object3D { get; }
|
2018-02-02 18:19:23 -08:00
|
|
|
|
|
2019-02-13 10:26:02 -08:00
|
|
|
|
public Object3DView(IObject3D source, Color color)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.Object3D = source;
|
|
|
|
|
|
this.Color = color;
|
2018-02-02 18:19:23 -08:00
|
|
|
|
|
2019-02-13 10:26:02 -08:00
|
|
|
|
if (source is Object3D object3D
|
|
|
|
|
|
&& color != source.Color
|
|
|
|
|
|
&& color.alpha != 255)
|
|
|
|
|
|
{
|
|
|
|
|
|
object3D.EnsureTransparentSorting();
|
2018-02-02 18:19:23 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-06-21 23:26:20 -07:00
|
|
|
|
}
|
2017-11-28 15:34:49 -08:00
|
|
|
|
}
|