public InspectTreeNode3D(InspectTreeNode node, InspectTreeState state) { void NodePropertyChanged(object sender, PropertyChangedEventArgs args) { var senderNode = sender as InspectTreeNode; switch (args.PropertyName) { case nameof(InspectTreeNode.Children): break; case nameof(InspectTreeNode.IsSelected): case nameof(InspectTreeNode.IsMouseOver): UpdateMaterial(); break; case nameof(InspectTreeNode.IsExpanded): foreach (var child in Children.OfType <InspectTreeNode3D> ()) { child.IsFlattened = !senderNode.IsExpanded; } break; } } Node = node; node.PropertyChanged += NodePropertyChanged; childIndex = state.AddChild(node.View); }
void BuildPrimaryPlane(InspectTreeState state) { var displayMode = state.Mode; Brush brush = new SolidColorBrush(EmptyColor); var view = Node.View; var parent = Node.View.Parent; var matrix = Matrix3D.Identity; if (view.Layer != null) { view = view.Layer; } var zFightOffset = childIndex * zFightIncrement; var zOffset = ZSpacing + zFightOffset; if (view.Transform != null) { var render = view.Transform; matrix = new Matrix3D { M11 = render.M11, M12 = render.M12, M13 = render.M13, M14 = render.M14, M21 = render.M21, M22 = render.M22, M23 = render.M23, M24 = render.M24, M31 = render.M31, M32 = render.M32, M33 = render.M33, M34 = render.M34, OffsetX = render.OffsetX, OffsetY = render.OffsetY, OffsetZ = render.OffsetZ + zOffset }; } var size = new Size(view.Width, view.Height); var visual = new DrawingVisual(); using (var context = visual.RenderOpen()) { if (view.BestCapturedImage != null && displayMode.HasFlag(DisplayMode.Content)) { var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.StreamSource = new MemoryStream(view.BestCapturedImage); bitmap.EndInit(); context.DrawImage(bitmap, new Rect(size)); } if (displayMode.HasFlag(DisplayMode.Frames)) { context.DrawRectangle( null, new Pen(new SolidColorBrush(Color.FromRgb(0xd3, 0xd3, 0xd3)), 0.5), new Rect(size)); } } brush = new ImageBrush { ImageSource = new DrawingImage(visual.Drawing) }; var geometry = new MeshGeometry3D() { Positions = new Point3DCollection { new Point3D(0, 0, 0), new Point3D(0, -size.Height, 0), new Point3D(size.Width, -size.Height, 0), new Point3D(size.Width, 0, 0) }, TextureCoordinates = new PointCollection { new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0) }, TriangleIndices = new Int32Collection { 0, 1, 2, 0, 2, 3 }, }; var backGeometry = new MeshGeometry3D() { Positions = geometry.Positions, TextureCoordinates = geometry.TextureCoordinates, TriangleIndices = geometry.TriangleIndices, Normals = new Vector3DCollection { new Vector3D(0, 0, -1), new Vector3D(0, 0, -1), new Vector3D(0, 0, -1), new Vector3D(0, 0, -1) } }; material = new DiffuseMaterial(brush) { Color = BlurColor }; Content = new Model3DGroup() { Children = new Model3DCollection { new GeometryModel3D { Geometry = geometry, Material = material }, new GeometryModel3D { Geometry = backGeometry, BackMaterial = material, }, }, Transform = new ScaleTransform3D { ScaleX = Math.Ceiling(view.Width) / size.Width, ScaleY = -Math.Ceiling(view.Height) / size.Height, ScaleZ = 1 } }; var group = new Transform3DGroup(); if ((parent == null && !Node.View.IsFakeRoot) || (parent?.IsFakeRoot ?? false)) { var unitScale = 1.0 / Math.Max(view.Width, view.Height); group.Children = new Transform3DCollection { new TranslateTransform3D { OffsetX = -view.Width / 2.0, OffsetY = -view.Height / 2.0, OffsetZ = zOffset }, new ScaleTransform3D(unitScale, -unitScale, 1), expandTransform }; } else { if (view.Transform != null) { group.Children = new Transform3DCollection { new MatrixTransform3D() { Matrix = matrix }, expandTransform }; } else { group.Children = new Transform3DCollection { new TranslateTransform3D(view.X, view.Y, zOffset), expandTransform }; } } Transform = group; }
public InspectViewNode(InspectTreeNode node, InspectTreeState state) { Node = node; node.PropertyChanged += NodePropertyChanged; this.childIndex = state.AddChild(node.View); }
InspectViewNode IInspectTree3DNode <InspectViewNode> .BuildChild(InspectTreeNode node, InspectTreeState state) { var child = new InspectViewNode(node, state); node.Build3D(child, state); return(child); }
void IInspectTree3DNode <InspectViewNode> .BuildPrimaryPlane(InspectTreeState state) => BuildPrimaryPlane(state);
void BuildPrimaryPlane(InspectTreeState state) { var view = View; if (View.Layer != null) { view = View.Layer; } Geometry = CreateGeometry((nfloat)view.Width, (nfloat)view.Height); var renderImage = state.Mode == DisplayMode.Content || state.Mode == DisplayMode.FramesAndContent; var materialContents = InspectViewMaterial.Create(view, renderImage); var firstMaterial = SCNMaterial.Create(); firstMaterial.Transparency = renderImage ? 1 : 0; firstMaterial.Diffuse.Contents = materialContents; firstMaterial.DoubleSided = true; var highlightMaterial = SCNMaterial.Create(); highlightMaterial.Diffuse.ContentColor = NSColor.SelectedMenuItem; highlightMaterial.Transparency = 0; highlightMaterial.DoubleSided = true; var renderBounds = state.Mode == DisplayMode.Frames || state.Mode == DisplayMode.FramesAndContent; var boundsMaterial = SCNMaterial.Create(); boundsMaterial.Diffuse.Contents = boundsColor = renderBounds ? NSColor.LightGray : NSColor.Clear; boundsMaterial.Transparency = 1; boundsMaterial.DoubleSided = true; Geometry.Materials = new [] { highlightMaterial, firstMaterial, boundsMaterial }; UpdateState(); // This is a hack to avoid Z-fighting of planes/frames that intersect within // the same node-depth level (or if we ever allow ZSpacing to drop to zero). // z-fighting appears on some controls such as some subviews of UISwitch. // A better solution would be to only apply this where an intersection exists. var zFightOffset = childIndex / ZFightDenominator; var zOffset = ZSpacing + zFightOffset; //var siblingOffset = childIndex - (ParentNode as InspectViewNode)?.childIndex ?? 0; //var zOffset = siblingOffset * ZSpacing; if ((View.Parent == null && !View.IsFakeRoot) || (View.Parent?.IsFakeRoot ?? false)) { var unitScale = (nfloat)(1.0 / Math.Max(view.Width, view.Height)); var translate = SCNMatrix4.CreateTranslation( (nfloat)(-view.Width / 2.0), (nfloat)(-view.Height / 2.0), zOffset); var scale = SCNMatrix4.Scale(unitScale, -unitScale, unitScale); Transform = SCNMatrix4.Mult(translate, scale); } else if (!view.IsFakeRoot) { if (view.Transform != null) { var parentTransform = SCNMatrix4.Identity; var render = view.Transform; var transform = new SCNMatrix4 { M11 = (nfloat)render.M11, M12 = (nfloat)render.M12, M13 = (nfloat)render.M13, M14 = (nfloat)render.M14, M21 = (nfloat)render.M21, M22 = (nfloat)render.M22, M23 = (nfloat)render.M23, M24 = (nfloat)render.M24, M31 = (nfloat)render.M31, M32 = (nfloat)render.M32, M33 = (nfloat)render.M33, M34 = (nfloat)render.M34, M41 = (nfloat)render.OffsetX, M42 = (nfloat)render.OffsetY, M43 = (nfloat)render.OffsetZ, M44 = (nfloat)render.M44 }; transform = SCNMatrix4.Mult(parentTransform, transform); Transform = SCNMatrix4.Mult( transform, SCNMatrix4.CreateTranslation(0, 0, zOffset)); } else { Transform = SCNMatrix4.CreateTranslation( (nfloat)view.X, (nfloat)view.Y, zOffset); } } }