public static PolyShapeInfo CloneAndTransformShape(PolyShapeInfo poly, Transform xform, Vector2 spriteSize, SpriteRenderer.FlipMode flip) { MathF.GetTransformDotVec(xform.Angle, xform.Scale, out var xDot, out var yDot); var shape = new PolyShapeInfo(); var center = spriteSize / 2; var verts = poly.Vertices.Select(v => { v = v * PhysicsUnit.LengthToDuality - center; if (flip.HasFlag(SpriteRenderer.FlipMode.Horizontal)) { v.X *= -1; } if (flip.HasFlag(SpriteRenderer.FlipMode.Vertical)) { v.Y *= -1; } //Vector2.Transform(ref v, ref matrix, out var v2); MathF.TransformDotVec(ref v, ref xDot, ref yDot); v += xform.Pos.Xy; return(v); }); if (flip.HasFlag(SpriteRenderer.FlipMode.Horizontal) ^ flip.HasFlag(SpriteRenderer.FlipMode.Vertical)) { verts = verts.Reverse(); } shape.Vertices = verts.ToArray(); return(shape); }
protected override void OnCollectStateDrawcalls(Canvas canvas) { base.OnCollectStateDrawcalls(canvas); GameObject selGameObj = this.selectedBody != null ? this.selectedBody.GameObj : null; Transform selTransform = selGameObj != null ? selGameObj.Transform : null; if (selTransform == null) { return; } if (this.mouseState == CursorState.CreatePolygon) { SelPolyShape selPolyShape = this.allObjSel.OfType <SelPolyShape>().FirstOrDefault(); if (selPolyShape != null) { PolyShapeInfo polyShape = selPolyShape.ActualObject as PolyShapeInfo; Vector2 lockedPos = this.createPolyIndex > 0 ? polyShape.Vertices[this.createPolyIndex - 1] : Vector2.Zero; Vector3 lockedPosWorld = selTransform.GetWorldPoint(new Vector3(lockedPos)); this.DrawLockedAxes(canvas, lockedPosWorld.X, lockedPosWorld.Y, lockedPosWorld.Z, polyShape.AABB.BoundingRadius * 4); } } else if (this.mouseState == CursorState.CreateLoop) { SelLoopShape selLoopShape = this.allObjSel.OfType <SelLoopShape>().FirstOrDefault(); if (selLoopShape != null) { LoopShapeInfo loopShape = selLoopShape.ActualObject as LoopShapeInfo; Vector2 lockedPos = this.createPolyIndex > 0 ? loopShape.Vertices[this.createPolyIndex - 1] : Vector2.Zero; Vector3 lockedPosWorld = selTransform.GetWorldPoint(new Vector3(lockedPos)); this.DrawLockedAxes(canvas, lockedPosWorld.X, lockedPosWorld.Y, lockedPosWorld.Z, loopShape.AABB.BoundingRadius * 4); } } }
private void DrawShapeOutline(Canvas canvas, Transform transform, PolyShapeInfo shape) { Vector3 pos = transform.Pos; float angle = transform.Angle; float scale = transform.Scale; if (this.wrapTexture) { Rect pointBoundingRect = shape.Vertices.BoundingBox(); canvas.State.TextureCoordinateRect = new Rect( pointBoundingRect.W / canvas.State.TextureBaseSize.X, pointBoundingRect.H / canvas.State.TextureBaseSize.Y); } canvas.State.TransformAngle = angle; canvas.State.TransformScale = new Vector2(scale, scale); canvas.FillPolygonOutline(shape.Vertices, this.outlineWidth, pos.X, pos.Y, pos.Z); }
private void DrawShapeArea(Canvas canvas, Transform transform, ShapeInfo shape) { canvas.PushState(); if (shape is CircleShapeInfo) { this.DrawShapeArea(canvas, transform, shape as CircleShapeInfo); } else if (shape is PolyShapeInfo) { PolyShapeInfo polyShape = shape as PolyShapeInfo; Rect bounds = polyShape.Vertices.BoundingBox(); Rect texRect = new Rect(1.0f, 1.0f); if (this.wrapTexture) { texRect.W = bounds.W / canvas.State.TextureBaseSize.X; texRect.H = bounds.H / canvas.State.TextureBaseSize.Y; } if (polyShape.ConvexPolygons != null) { foreach (Vector2[] convexPolygon in polyShape.ConvexPolygons) { Rect localBounds = convexPolygon.BoundingBox(); Rect localTexRect = new Rect( texRect.X + texRect.W * (localBounds.X - bounds.X) / bounds.W, texRect.Y + texRect.H * (localBounds.Y - bounds.Y) / bounds.H, texRect.W * localBounds.W / bounds.W, texRect.H * localBounds.H / bounds.H); this.DrawShapeArea(canvas, transform, convexPolygon, localTexRect); } } } else if (shape is VertexBasedShapeInfo) { VertexBasedShapeInfo vertexShape = shape as VertexBasedShapeInfo; bool isSolid = (vertexShape.ShapeTraits & VertexShapeTrait.IsSolid) != VertexShapeTrait.None; if (isSolid || this.fillHollowShapes) { this.DrawShapeArea(canvas, transform, vertexShape.Vertices); } } canvas.PopState(); }
protected override string UpdateActionText() { Vector2 vertex = Vector2.Zero; if (this.mouseState == CursorState.CreatePolygon || this.mouseState == CursorState.CreateLoop) { Point mousePos = this.PointToClient(Cursor.Position); GameObject selGameObj = this.selectedBody != null ? this.selectedBody.GameObj : null; Transform selTransform = selGameObj != null ? selGameObj.Transform : null; SelPolyShape selPolyShape = this.allObjSel.OfType <SelPolyShape>().FirstOrDefault(); SelLoopShape selLoopShape = this.allObjSel.OfType <SelLoopShape>().FirstOrDefault(); bool hasData = false; if (selPolyShape != null) { PolyShapeInfo polyShape = selPolyShape.ActualObject as PolyShapeInfo; vertex = polyShape.Vertices[this.createPolyIndex]; hasData = true; } else if (selLoopShape != null) { LoopShapeInfo loopShape = selLoopShape.ActualObject as LoopShapeInfo; vertex = loopShape.Vertices[this.createPolyIndex]; hasData = true; } else if (selTransform != null) { Vector3 spaceCoord = this.GetSpaceCoord(new Vector3(mousePos.X, mousePos.Y, selTransform.Pos.Z)); vertex = selTransform.GetLocalPoint(spaceCoord).Xy; hasData = true; } if (hasData) { return (string.Format("Vertex X:{0,9:0.00}/n", vertex.X) + string.Format("Vertex Y:{0,9:0.00}", vertex.Y)); } } return(base.UpdateActionText()); }
private void DrawShape(Canvas canvas, Transform transform, PolyShapeInfo shape, ColorRgba fillColor, ColorRgba outlineColor) { if (shape.ConvexPolygons != null) { // Fill each convex polygon individually foreach (Vector2[] polygon in shape.ConvexPolygons) { this.FillPolygon(canvas, transform, polygon, fillColor); } // Draw all convex polygon edges that are not outlines canvas.State.DepthOffset = this.depthOffset - 0.05f; this.DrawPolygonInternals(canvas, transform, shape.Vertices, shape.ConvexPolygons, outlineColor); canvas.State.DepthOffset = this.depthOffset; } // Draw the polygon outline canvas.State.DepthOffset = this.depthOffset - 0.1f; this.DrawPolygonOutline(canvas, transform, shape.Vertices, outlineColor, true); canvas.State.DepthOffset = this.depthOffset; }
protected internal override void OnCollectDrawcalls(Canvas canvas) { base.OnCollectDrawcalls(canvas); List <RigidBody> visibleColliders = this.QueryVisibleColliders().ToList(); RigidBody selectedBody = this.QuerySelectedCollider(); canvas.State.TextFont = Font.GenericMonospace10; canvas.State.TextInvariantScale = true; canvas.State.ZOffset = -1; Font textFont = canvas.State.TextFont.Res; // Draw Shape layer foreach (RigidBody c in visibleColliders) { if (!c.Shapes.Any()) { continue; } float colliderAlpha = c == selectedBody ? 1.0f : (selectedBody != null ? 0.25f : 0.5f); float maxDensity = c.Shapes.Max(s => s.Density); float minDensity = c.Shapes.Min(s => s.Density); float avgDensity = (maxDensity + minDensity) * 0.5f; Vector3 colliderPos = c.GameObj.Transform.Pos; float colliderScale = c.GameObj.Transform.Scale; int index = 0; foreach (ShapeInfo s in c.Shapes) { CircleShapeInfo circle = s as CircleShapeInfo; PolyShapeInfo poly = s as PolyShapeInfo; // EdgeShapeInfo edge = s as EdgeShapeInfo; LoopShapeInfo loop = s as LoopShapeInfo; ObjectEditorCamViewState editorState = this.View.ActiveState as ObjectEditorCamViewState; float shapeAlpha = colliderAlpha * (selectedBody == null || editorState == null || editorState.SelectedObjects.Any(sel => sel.ActualObject == s) ? 1.0f : 0.5f); float densityRelative = MathF.Abs(maxDensity - minDensity) < 0.01f ? 1.0f : s.Density / avgDensity; ColorRgba clr = s.IsSensor ? this.ShapeSensorColor : this.ShapeColor; ColorRgba fontClr = this.FgColor; Vector2 center = Vector2.Zero; if (!c.IsAwake) { clr = clr.ToHsva().WithSaturation(0.0f).ToRgba(); } if (!s.IsValid) { clr = this.ShapeErrorColor; } if (circle != null) { Vector2 circlePos = circle.Position * colliderScale; MathF.TransformCoord(ref circlePos.X, ref circlePos.Y, c.GameObj.Transform.Angle); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha((0.25f + densityRelative * 0.25f) * shapeAlpha))); canvas.FillCircle( colliderPos.X + circlePos.X, colliderPos.Y + circlePos.Y, colliderPos.Z, circle.Radius * colliderScale); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha(shapeAlpha))); canvas.DrawCircle( colliderPos.X + circlePos.X, colliderPos.Y + circlePos.Y, colliderPos.Z, circle.Radius * colliderScale); center = circlePos; } else if (poly != null) { Vector2[] polyVert = poly.Vertices.ToArray(); for (int i = 0; i < polyVert.Length; i++) { center += polyVert[i]; Vector2.Multiply(ref polyVert[i], colliderScale, out polyVert[i]); MathF.TransformCoord(ref polyVert[i].X, ref polyVert[i].Y, c.GameObj.Transform.Angle); } center /= polyVert.Length; Vector2.Multiply(ref center, colliderScale, out center); MathF.TransformCoord(ref center.X, ref center.Y, c.GameObj.Transform.Angle); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha((0.25f + densityRelative * 0.25f) * shapeAlpha))); canvas.FillPolygon(polyVert, colliderPos.X, colliderPos.Y, colliderPos.Z); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha(shapeAlpha))); canvas.DrawPolygon(polyVert, colliderPos.X, colliderPos.Y, colliderPos.Z); } else if (loop != null) { Vector2[] loopVert = loop.Vertices.ToArray(); for (int i = 0; i < loopVert.Length; i++) { center += loopVert[i]; Vector2.Multiply(ref loopVert[i], colliderScale, out loopVert[i]); MathF.TransformCoord(ref loopVert[i].X, ref loopVert[i].Y, c.GameObj.Transform.Angle); } center /= loopVert.Length; Vector2.Multiply(ref center, colliderScale, out center); MathF.TransformCoord(ref center.X, ref center.Y, c.GameObj.Transform.Angle); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha(shapeAlpha))); canvas.DrawPolygon(loopVert, colliderPos.X, colliderPos.Y, colliderPos.Z); } // Draw shape index if (c == selectedBody) { Vector2 textSize = textFont.MeasureText(index.ToString(CultureInfo.InvariantCulture)); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, fontClr.WithAlpha((shapeAlpha + 1.0f) * 0.5f))); canvas.State.TransformHandle = textSize * 0.5f; canvas.DrawText(index.ToString(CultureInfo.InvariantCulture), colliderPos.X + center.X, colliderPos.Y + center.Y, colliderPos.Z); canvas.State.TransformHandle = Vector2.Zero; } index++; } // Draw center of mass if (c.BodyType == BodyType.Dynamic) { Vector2 localMassCenter = c.LocalMassCenter; MathF.TransformCoord(ref localMassCenter.X, ref localMassCenter.Y, c.GameObj.Transform.Angle, c.GameObj.Transform.Scale); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, this.MassCenterColor.WithAlpha(colliderAlpha))); canvas.DrawLine( colliderPos.X + localMassCenter.X - 5.0f, colliderPos.Y + localMassCenter.Y, colliderPos.Z, colliderPos.X + localMassCenter.X + 5.0f, colliderPos.Y + localMassCenter.Y, colliderPos.Z); canvas.DrawLine( colliderPos.X + localMassCenter.X, colliderPos.Y + localMassCenter.Y - 5.0f, colliderPos.Z, colliderPos.X + localMassCenter.X, colliderPos.Y + localMassCenter.Y + 5.0f, colliderPos.Z); } } }
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); Transform selTransform = this.selectedBody != null && this.selectedBody.GameObj != null ? this.selectedBody.GameObj.Transform : null; Vector3 spaceCoord = selTransform != null?this.GetSpaceCoord(new Vector3(e.X, e.Y, selTransform.Pos.Z)) : Vector3.Zero; Vector2 localPos = selTransform != null?selTransform.GetLocalPoint(spaceCoord).Xy : Vector2.Zero; if (this.mouseState != CursorState.Normal) { this.UpdateCursorImage(); } if (this.mouseState == CursorState.CreatePolygon && this.allObjSel.Any(sel => sel is SelPolyShape)) { SelPolyShape selPolyShape = this.allObjSel.OfType <SelPolyShape>().First(); PolyShapeInfo polyShape = selPolyShape.ActualObject as PolyShapeInfo; List <Vector2> vertices = polyShape.Vertices.ToList(); Vector2 lockedPos = this.createPolyIndex > 0 ? vertices[this.createPolyIndex - 1] : Vector2.Zero; MathF.TransformCoord(ref lockedPos.X, ref lockedPos.Y, selTransform.Angle); MathF.TransformCoord(ref localPos.X, ref localPos.Y, selTransform.Angle); localPos = this.ApplyAxisLock(localPos, lockedPos); MathF.TransformCoord(ref localPos.X, ref localPos.Y, -selTransform.Angle); vertices[this.createPolyIndex] = localPos; polyShape.Vertices = vertices.ToArray(); selPolyShape.UpdatePolyStats(); // Update the body directly after modifying it this.selectedBody.SynchronizeBodyShape(); DualityEditorApp.NotifyObjPropChanged(this, new ObjectSelection(this.selectedBody), ReflectionInfo.Property_RigidBody_Shapes); } else if (this.mouseState == CursorState.CreateLoop && this.allObjSel.Any(sel => sel is SelLoopShape)) { SelLoopShape selPolyShape = this.allObjSel.OfType <SelLoopShape>().First(); LoopShapeInfo polyShape = selPolyShape.ActualObject as LoopShapeInfo; List <Vector2> vertices = polyShape.Vertices.ToList(); Vector2 lockedPos = this.createPolyIndex > 0 ? vertices[this.createPolyIndex - 1] : Vector2.Zero; MathF.TransformCoord(ref lockedPos.X, ref lockedPos.Y, selTransform.Angle); MathF.TransformCoord(ref localPos.X, ref localPos.Y, selTransform.Angle); localPos = this.ApplyAxisLock(localPos, lockedPos); MathF.TransformCoord(ref localPos.X, ref localPos.Y, -selTransform.Angle); vertices[this.createPolyIndex] = localPos; polyShape.Vertices = vertices.ToArray(); selPolyShape.UpdateLoopStats(); // Update the body directly after modifying it this.selectedBody.SynchronizeBodyShape(); DualityEditorApp.NotifyObjPropChanged(this, new ObjectSelection(this.selectedBody), ReflectionInfo.Property_RigidBody_Shapes); } }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); GameObject selGameObj = this.selectedBody != null ? this.selectedBody.GameObj : null; Transform selTransform = selGameObj != null ? selGameObj.Transform : null; if (selTransform == null) { return; } Vector3 spaceCoord = this.GetSpaceCoord(new Vector3(e.X, e.Y, selTransform.Pos.Z)); Vector2 localPos = selTransform.GetLocalPoint(spaceCoord).Xy; if (this.mouseState == CursorState.CreateCircle) { #region CreateCircle if (e.Button == MouseButtons.Left) { CircleShapeInfo newShape = new CircleShapeInfo(1.0f, localPos, 1.0f); UndoRedoManager.BeginMacro(); UndoRedoManager.Do(new CreateRigidBodyShapeAction(this.selectedBody, newShape)); this.createAction = true; this.LeaveCursorState(); this.SelectObjects(new[] { SelShape.Create(newShape) }); this.BeginAction(ObjectAction.Scale); } else if (e.Button == MouseButtons.Right) { this.LeaveCursorState(); } #endregion } else if (this.mouseState == CursorState.CreatePolygon) { #region CreatePolygon if (e.Button == MouseButtons.Left) { bool success = false; if (!this.allObjSel.Any(sel => sel is SelPolyShape)) { PolyShapeInfo newShape = new PolyShapeInfo(new Vector2[] { localPos, localPos, localPos }, 1.0f); UndoRedoManager.Do(new CreateRigidBodyShapeAction(this.selectedBody, newShape)); this.SelectObjects(new[] { SelShape.Create(newShape) }); this.createPolyIndex++; } else { SelPolyShape selPolyShape = this.allObjSel.OfType <SelPolyShape>().First(); PolyShapeInfo polyShape = selPolyShape.ActualObject as PolyShapeInfo; if (this.createPolyIndex <= 2 || MathF.IsPolygonConvex(polyShape.Vertices)) { Vector2 lockedPos = this.createPolyIndex > 0 ? polyShape.Vertices[this.createPolyIndex - 1] : Vector2.Zero; MathF.TransformCoord(ref lockedPos.X, ref lockedPos.Y, selTransform.Angle); MathF.TransformCoord(ref localPos.X, ref localPos.Y, selTransform.Angle); localPos = this.ApplyAxisLock(localPos, lockedPos); MathF.TransformCoord(ref localPos.X, ref localPos.Y, -selTransform.Angle); if (polyShape.Vertices.Length < PolyShapeInfo.MaxVertices) { List <Vector2> vertices = polyShape.Vertices.ToList(); vertices[this.createPolyIndex] = localPos; if (this.createPolyIndex >= vertices.Count - 1) { vertices.Add(localPos); } polyShape.Vertices = vertices.ToArray(); selPolyShape.UpdatePolyStats(); this.createPolyIndex++; } else { Vector2[] vertices = polyShape.Vertices; vertices[this.createPolyIndex] = localPos; polyShape.Vertices = vertices; selPolyShape.UpdatePolyStats(); this.LeaveCursorState(); } } } if (success) { DualityEditorApp.NotifyObjPropChanged(this, new ObjectSelection(this.selectedBody), ReflectionInfo.Property_RigidBody_Shapes); } } else if (e.Button == MouseButtons.Right) { if (this.allObjSel.Any(sel => sel is SelPolyShape)) { SelPolyShape selPolyShape = this.allObjSel.OfType <SelPolyShape>().First(); PolyShapeInfo polyShape = selPolyShape.ActualObject as PolyShapeInfo; List <Vector2> vertices = polyShape.Vertices.ToList(); vertices.RemoveAt(this.createPolyIndex); if (vertices.Count < 3 || this.createPolyIndex < 2) { this.DeleteObjects(new SelPolyShape[] { selPolyShape }); } else { polyShape.Vertices = vertices.ToArray(); selPolyShape.UpdatePolyStats(); } DualityEditorApp.NotifyObjPropChanged(this, new ObjectSelection(this.selectedBody), ReflectionInfo.Property_RigidBody_Shapes); } this.LeaveCursorState(); } #endregion } else if (this.mouseState == CursorState.CreateLoop) { #region CreateLoop if (e.Button == MouseButtons.Left) { bool success = false; if (!this.allObjSel.Any(sel => sel is SelLoopShape)) { LoopShapeInfo newShape = new LoopShapeInfo(new Vector2[] { localPos, localPos + Vector2.UnitX, localPos + Vector2.One }); UndoRedoManager.Do(new CreateRigidBodyShapeAction(this.selectedBody, newShape)); this.SelectObjects(new[] { SelShape.Create(newShape) }); success = true; } else { SelLoopShape selPolyShape = this.allObjSel.OfType <SelLoopShape>().First(); LoopShapeInfo polyShape = selPolyShape.ActualObject as LoopShapeInfo; List <Vector2> vertices = polyShape.Vertices.ToList(); Vector2 lockedPos = this.createPolyIndex > 0 ? vertices[this.createPolyIndex - 1] : Vector2.Zero; MathF.TransformCoord(ref lockedPos.X, ref lockedPos.Y, selTransform.Angle); MathF.TransformCoord(ref localPos.X, ref localPos.Y, selTransform.Angle); localPos = this.ApplyAxisLock(localPos, lockedPos); MathF.TransformCoord(ref localPos.X, ref localPos.Y, -selTransform.Angle); vertices[this.createPolyIndex] = localPos; if (this.createPolyIndex >= vertices.Count - 1) { vertices.Add(localPos); } polyShape.Vertices = vertices.ToArray(); selPolyShape.UpdateLoopStats(); success = true; } if (success) { this.createPolyIndex++; DualityEditorApp.NotifyObjPropChanged(this, new ObjectSelection(this.selectedBody), ReflectionInfo.Property_RigidBody_Shapes); } } else if (e.Button == MouseButtons.Right) { if (this.allObjSel.Any(sel => sel is SelLoopShape)) { SelLoopShape selPolyShape = this.allObjSel.OfType <SelLoopShape>().First(); LoopShapeInfo polyShape = selPolyShape.ActualObject as LoopShapeInfo; List <Vector2> vertices = polyShape.Vertices.ToList(); vertices.RemoveAt(this.createPolyIndex); if (vertices.Count < 3 || this.createPolyIndex < 2) { this.DeleteObjects(new SelLoopShape[] { selPolyShape }); } else { polyShape.Vertices = vertices.ToArray(); selPolyShape.UpdateLoopStats(); } DualityEditorApp.NotifyObjPropChanged(this, new ObjectSelection(this.selectedBody), ReflectionInfo.Property_RigidBody_Shapes); } this.LeaveCursorState(); } #endregion } //else if (this.mouseState == CursorState.CreateEdge) //{ // #region CreateEdge // if (e.Button == MouseButtons.Left) // { // bool success = false; // if (!this.allObjSel.Any(sel => sel is SelEdgeShape)) // { // EdgeShapeInfo newShape = new EdgeShapeInfo(localPos, localPos + Vector2.UnitX); // this.selectedCollider.AddShape(newShape); // this.SelectObjects(new[] { SelShape.Create(newShape) }); // success = true; // } // else // { // SelEdgeShape selEdgeShape = this.allObjSel.OfType<SelEdgeShape>().First(); // EdgeShapeInfo edgeShape = selEdgeShape.ActualObject as EdgeShapeInfo; // switch (this.createPolyIndex) // { // case 0: edgeShape.VertexStart = localPos; break; // case 1: edgeShape.VertexEnd = localPos; break; // } // selEdgeShape.UpdateEdgeStats(); // success = true; // } // if (success) // { // this.createPolyIndex++; // DualityEditorApp.NotifyObjPropChanged(this, // new ObjectSelection(this.selectedCollider), // ReflectionInfo.Property_RigidBody_Shapes); // if (this.createPolyIndex >= 2) // this.LeaveCursorState(); // } // } // else if (e.Button == MouseButtons.Right) // { // if (this.allObjSel.Any(sel => sel is SelEdgeShape)) // { // SelEdgeShape selEdgeShape = this.allObjSel.OfType<SelEdgeShape>().First(); // EdgeShapeInfo edgeShape = selEdgeShape.ActualObject as EdgeShapeInfo; // if (this.createPolyIndex < 1) // this.DeleteObjects(new SelEdgeShape[] { selEdgeShape }); // else // selEdgeShape.UpdateEdgeStats(); // DualityEditorApp.NotifyObjPropChanged(this, // new ObjectSelection(this.selectedCollider), // ReflectionInfo.Property_RigidBody_Shapes); // } // this.LeaveCursorState(); // } // #endregion //} }
protected internal override void OnCollectWorldOverlayDrawcalls(Canvas canvas) { base.OnCollectWorldOverlayDrawcalls(canvas); List <RigidBody> visibleColliders = this.QueryVisibleColliders().ToList(); RigidBody selectedBody = this.QuerySelectedCollider(); canvas.State.TextFont = Font.GenericMonospace10; canvas.State.TextInvariantScale = true; canvas.State.ZOffset = -0.5f; Font textFont = canvas.State.TextFont.Res; // Draw Shape layer foreach (RigidBody body in visibleColliders) { if (!body.Shapes.Any()) { continue; } float colliderAlpha = body == selectedBody ? 1.0f : (selectedBody != null ? 0.25f : 0.5f); float maxDensity = body.Shapes.Max(s => s.Density); float minDensity = body.Shapes.Min(s => s.Density); float avgDensity = (maxDensity + minDensity) * 0.5f; Vector3 objPos = body.GameObj.Transform.Pos; float objAngle = body.GameObj.Transform.Angle; float objScale = body.GameObj.Transform.Scale; int index = 0; foreach (ShapeInfo shape in body.Shapes) { CircleShapeInfo circle = shape as CircleShapeInfo; PolyShapeInfo poly = shape as PolyShapeInfo; ChainShapeInfo chain = shape as ChainShapeInfo; LoopShapeInfo loop = shape as LoopShapeInfo; ObjectEditorCamViewState editorState = this.View.ActiveState as ObjectEditorCamViewState; float shapeAlpha = colliderAlpha * (selectedBody == null || editorState == null || editorState.SelectedObjects.Any(sel => sel.ActualObject == shape) ? 1.0f : 0.5f); float densityRelative = MathF.Abs(maxDensity - minDensity) < 0.01f ? 1.0f : shape.Density / avgDensity; ColorRgba clr = shape.IsSensor ? this.ShapeSensorColor : this.ShapeColor; ColorRgba fontClr = this.FgColor; Vector2 center = Vector2.Zero; if (!body.IsAwake) { clr = clr.ToHsva().WithSaturation(0.0f).ToRgba(); } if (!shape.IsValid) { clr = this.ShapeErrorColor; } bool fillShape = (poly != null || circle != null); Vector2[] shapeVertices = null; if (poly != null) { shapeVertices = poly.Vertices; } else if (loop != null) { shapeVertices = loop.Vertices; } else if (chain != null) { shapeVertices = chain.Vertices; } if (circle != null) { Vector2 circlePos = circle.Position * objScale; MathF.TransformCoord(ref circlePos.X, ref circlePos.Y, objAngle); if (fillShape) { canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha((0.25f + densityRelative * 0.25f) * shapeAlpha))); canvas.FillCircle( objPos.X + circlePos.X, objPos.Y + circlePos.Y, objPos.Z, circle.Radius * objScale); } canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha(shapeAlpha))); canvas.DrawCircle( objPos.X + circlePos.X, objPos.Y + circlePos.Y, objPos.Z, circle.Radius * objScale); center = circlePos; } else if (shapeVertices != null) { ColorRgba vertexFillColor = canvas.State.ColorTint * clr.WithAlpha((0.25f + densityRelative * 0.25f) * shapeAlpha); ColorRgba vertexOutlineColor = canvas.State.ColorTint * clr; // Prepare vertices to submit. We can't use higher-level canvas functionality // here, because we want direct control over the vertex mode. float viewSpaceScale = objScale; Vector3 viewSpacePos = objPos; canvas.DrawDevice.PreprocessCoords(ref viewSpacePos, ref viewSpaceScale); VertexC1P3T2[] drawVertices = new VertexC1P3T2[shapeVertices.Length]; for (int i = 0; i < drawVertices.Length; i++) { drawVertices[i].Pos.X = shapeVertices[i].X; drawVertices[i].Pos.Y = shapeVertices[i].Y; drawVertices[i].Pos.Z = 0.0f; MathF.TransformCoord(ref drawVertices[i].Pos.X, ref drawVertices[i].Pos.Y, objAngle, viewSpaceScale); drawVertices[i].Pos.X += viewSpacePos.X; drawVertices[i].Pos.Y += viewSpacePos.Y; drawVertices[i].Pos.Z += viewSpacePos.Z; drawVertices[i].Color = vertexOutlineColor; } // Calculate the center coordinate for (int i = 0; i < drawVertices.Length; i++) { center += shapeVertices[i]; } center /= shapeVertices.Length; MathF.TransformCoord(ref center.X, ref center.Y, objAngle, objScale); // Make sure to render using an alpha material canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White)); // Fill the shape if (fillShape) { VertexC1P3T2[] fillVertices = drawVertices.Clone() as VertexC1P3T2[]; for (int i = 0; i < fillVertices.Length; i++) { fillVertices[i].Color = vertexFillColor; } canvas.DrawVertices(fillVertices, VertexMode.TriangleFan); } // Draw the outline canvas.DrawVertices(drawVertices, shape is ChainShapeInfo ? VertexMode.LineStrip : VertexMode.LineLoop); } // Draw shape index if (body == selectedBody) { string indexText = index.ToString(); Vector2 textSize = textFont.MeasureText(indexText); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, fontClr.WithAlpha((shapeAlpha + 1.0f) * 0.5f))); canvas.DrawText(indexText, objPos.X + center.X, objPos.Y + center.Y, objPos.Z); } index++; } // Draw center of mass if (body.BodyType == BodyType.Dynamic) { Vector2 localMassCenter = body.LocalMassCenter; MathF.TransformCoord(ref localMassCenter.X, ref localMassCenter.Y, objAngle, objScale); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, this.MassCenterColor.WithAlpha(colliderAlpha))); canvas.DrawLine( objPos.X + localMassCenter.X - 5.0f, objPos.Y + localMassCenter.Y, objPos.Z, objPos.X + localMassCenter.X + 5.0f, objPos.Y + localMassCenter.Y, objPos.Z); canvas.DrawLine( objPos.X + localMassCenter.X, objPos.Y + localMassCenter.Y - 5.0f, objPos.Z, objPos.X + localMassCenter.X, objPos.Y + localMassCenter.Y + 5.0f, objPos.Z); } } }
public RigidBodyEditorSelPolyShape(PolyShapeInfo shape) : base(shape) { }
public SelPolyShape(PolyShapeInfo shape) : base(shape) { this.poly = shape; this.UpdatePolyStats(); }
protected internal override void OnCollectWorldOverlayDrawcalls(Canvas canvas) { base.OnCollectWorldOverlayDrawcalls(canvas); List <RigidBody> visibleColliders = this.QueryVisibleColliders().ToList(); RigidBody selectedBody = this.QuerySelectedCollider(); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White)); canvas.State.TextFont = Font.GenericMonospace10; canvas.State.TextInvariantScale = true; canvas.State.ZOffset = this.depthOffset; Font textFont = canvas.State.TextFont.Res; // Retrieve selected shapes ObjectEditorCamViewState editorState = this.View.ActiveState as ObjectEditorCamViewState; object[] editorSelectedObjects = editorState != null?editorState.SelectedObjects.Select(item => item.ActualObject).ToArray() : new object[0]; bool isAnyBodySelected = (selectedBody != null); bool isAnyShapeSelected = isAnyBodySelected && editorSelectedObjects.OfType <ShapeInfo>().Any(); // Draw Shape layer foreach (RigidBody body in visibleColliders) { if (!body.Shapes.Any()) { continue; } Vector3 objPos = body.GameObj.Transform.Pos; float objAngle = body.GameObj.Transform.Angle; float objScale = body.GameObj.Transform.Scale; bool isBodySelected = (body == selectedBody); float bodyAlpha = isBodySelected ? 1.0f : (isAnyBodySelected ? 0.5f : 1.0f); float maxDensity = body.Shapes.Max(s => s.Density); float minDensity = body.Shapes.Min(s => s.Density); float avgDensity = (maxDensity + minDensity) * 0.5f; int shapeIndex = 0; foreach (ShapeInfo shape in body.Shapes) { CircleShapeInfo circle = shape as CircleShapeInfo; PolyShapeInfo poly = shape as PolyShapeInfo; ChainShapeInfo chain = shape as ChainShapeInfo; LoopShapeInfo loop = shape as LoopShapeInfo; bool isShapeSelected = isBodySelected && editorSelectedObjects.Contains(shape); float shapeAlpha = bodyAlpha * (isShapeSelected ? 1.0f : (isAnyShapeSelected && isBodySelected ? 0.75f : 1.0f)); float densityRelative = MathF.Abs(maxDensity - minDensity) < 0.01f ? 1.0f : shape.Density / avgDensity; ColorRgba shapeColor = shape.IsSensor ? this.ShapeSensorColor : this.ShapeColor; ColorRgba fontColor = this.FgColor; if (!body.IsAwake) { shapeColor = shapeColor.ToHsva().WithSaturation(0.0f).ToRgba(); } if (!shape.IsValid) { shapeColor = this.ShapeErrorColor; } // Draw the shape itself ColorRgba fillColor = shapeColor.WithAlpha((0.25f + densityRelative * 0.25f) * shapeAlpha); ColorRgba outlineColor = ColorRgba.Lerp(shapeColor, fontColor, isShapeSelected ? 0.75f : 0.25f).WithAlpha(shapeAlpha); this.DrawShape(canvas, body.GameObj.Transform, shape, fillColor, outlineColor); // Calculate the center coordinate Vector2 shapeCenter = Vector2.Zero; if (circle != null) { shapeCenter = circle.Position * objScale; } else { Vector2[] shapeVertices = null; if (poly != null) { shapeVertices = poly.Vertices; } else if (loop != null) { shapeVertices = loop.Vertices; } else if (chain != null) { shapeVertices = chain.Vertices; } for (int i = 0; i < shapeVertices.Length; i++) { shapeCenter += shapeVertices[i]; } shapeCenter /= shapeVertices.Length; MathF.TransformCoord(ref shapeCenter.X, ref shapeCenter.Y, objAngle, objScale); } // Draw shape index if (body == selectedBody) { string indexText = shapeIndex.ToString(); Vector2 textSize = textFont.MeasureText(indexText); canvas.State.ColorTint = fontColor.WithAlpha((shapeAlpha + 1.0f) * 0.5f); canvas.DrawText(indexText, objPos.X + shapeCenter.X, objPos.Y + shapeCenter.Y, 0.0f); } shapeIndex++; } // Draw center of mass if (body.BodyType == BodyType.Dynamic) { Vector2 localMassCenter = body.LocalMassCenter; MathF.TransformCoord(ref localMassCenter.X, ref localMassCenter.Y, objAngle, objScale); float size = this.GetScreenConstantScale(canvas, 6.0f); canvas.State.ColorTint = this.MassCenterColor.WithAlpha(bodyAlpha); canvas.DrawLine( objPos.X + localMassCenter.X - size, objPos.Y + localMassCenter.Y, 0.0f, objPos.X + localMassCenter.X + size, objPos.Y + localMassCenter.Y, 0.0f); canvas.DrawLine( objPos.X + localMassCenter.X, objPos.Y + localMassCenter.Y - size, 0.0f, objPos.X + localMassCenter.X, objPos.Y + localMassCenter.Y + size, 0.0f); } // Draw transform center if (body.BodyType == BodyType.Dynamic) { float size = this.GetScreenConstantScale(canvas, 3.0f); canvas.State.ColorTint = this.ObjectCenterColor.WithAlpha(bodyAlpha); canvas.FillCircle(objPos.X, objPos.Y, 0.0f, size); } } }
public SelVertex(PolyShapeInfo shape, int vertexIndex) { Guard.NotNull(shape, "A null shape was selected"); this.shape = shape; this.index = vertexIndex; }