private static Transform GetMovieButtonTransform(int index, AaRectangle2 rect) { return(new Transform(ButtonHalfHeight, Quaternion.Identity, new Vector3( rect.MinX + ButtonHalfHeight + ((int)index) * ((rect.Width - 2 * ButtonHalfWidth) / (AllMovieButtons.Length - 1)), rect.MinY - ButtonHalfHeight, 0))); }
protected StoryFlowchartNodeGizmoComponent(IEmbeddedResources embeddedResources, IViewService viewService) { this.viewService = viewService; GlobalRectangle = new AaRectangle2(Vector2.Zero, 1, 1); var squareModel = embeddedResources.SimplePlaneXyModel(); var material = StandardMaterial.New(this) .SetDiffuseColor(x => x.DiffuseColorToUse()) .SetDiffuseMap(x => x.DiffuseMapToUse()) .SetIgnoreLighting(true) .SetHighlightEffect(x => x.viewService.SelectedNode == ReferencedNode ? HighlightEffect.RainbowBorder : x.viewService.ClosestStoryNode == ReferencedNode ? HighlightEffect.Pulsating : HighlightEffect.None); visualElement = new ModelVisualElement <StoryFlowchartNodeGizmoComponent>(this) .SetModel(squareModel) .SetMaterial(material) .SetTransform(x => Transform.Translation(new Vector3(x.GlobalRectangle.Center, x.Depth * 0.1f))) .SetNonUniformScale(x => new Vector3(x.GlobalRectangle.HalfWidth, -/*todo: correct text-coords*/ x.GlobalRectangle.HalfHeight, 1)); hittable = new RectangleHittable <StoryFlowchartNodeGizmoComponent>(this, Transform.Identity, x => new AaRectangle2(Vector2.Zero, x.GlobalRectangle.HalfWidth, x.GlobalRectangle.HalfHeight), x => - x.Depth); }
public DragRectangleInputLock(IUndoRedoService undoRedo, IRectangleComponent nodeRectAspect, IPlacementSurface space, Vector2 anchorPointOnRect) { this.undoRedo = undoRedo; this.nodeRectAspect = nodeRectAspect; this.space = space; this.anchorPointOnRect = anchorPointOnRect; originalRect = nodeRectAspect.Rectangle; }
public PolylineCirclePackingBorder(IEnumerable <Vector2> rawPoints, float circleRadius) { points = Normalize(rawPoints); this.circleRadius = circleRadius; circleRadiusSq = circleRadius.Sq(); BoundingRect = AaRectangle2.BoundingRect(points); Area = CalculateArea(points); }
public ResizeRectangleInputLock(IRectangleComponent nodeRectAspect, IUndoRedoService undoRedo, IPlacementSurface space, ResizeRectangleGizmoPlace place) { this.nodeRectAspect = nodeRectAspect; this.undoRedo = undoRedo; this.space = space; this.place = place; originalRect = nodeRectAspect.Rectangle; }
public CirclePackingCircleGrid(float circleRadius, AaRectangle2 boundingRect) { cellSize = CellSizeInRadii * circleRadius; var gridWidth = (int)MathHelper.Ceiling(boundingRect.Width / cellSize); var gridHeight = (int)MathHelper.Ceiling(boundingRect.Height / cellSize); gridSize = new IntSize2(gridWidth, gridHeight); cellCircleCounts = new int[gridSize.Area]; circleIndices = new int[gridSize.Area * MaxCirclesPerCell]; minCorner = boundingRect.MinMin; }
private AaRectangle2 CalculateButtonPanelRectangle() { var buttonPanelWidth = AllMovieButtons.Length * 2 * ButtonHalfWidth + (AllMovieButtons.Length - 1) * ButtonHorizontalMargin; var buttonPanelLeftX = Rectangle.Center.X - buttonPanelWidth / 2; var buttonPanelBottomY = Rectangle.MinY - (ButtonHalfHeight * 2); var buttonPanelRect = AaRectangle2.FromCornerAndDimensions(buttonPanelLeftX, buttonPanelBottomY, buttonPanelWidth, ButtonHalfHeight * 2); return(buttonPanelRect); }
private void AdjustRectangleAndSetCurve() { var entityRect = rectangleAspect.Rectangle; var layoutBasedPoints = curve .Select(xy => entityRect.Center + new Vector2(xy.X * entityRect.HalfWidth, xy.Y * entityRect.HalfHeight)) .ToArray(); float minX = float.MaxValue; float minY = float.MaxValue; float maxX = float.MinValue; float maxY = float.MinValue; foreach (var point in layoutBasedPoints) { if (point.X < minX) { minX = point.X; } if (point.X > maxX) { maxX = point.X; } if (point.Y < minY) { minY = point.Y; } if (point.Y > maxY) { maxY = point.Y; } } var newRect = new AaRectangle2(new Vector2(minX, minY), new Vector2(maxX, maxY)); var adjustedCurve = layoutBasedPoints.Select(xy => { var result = xy - newRect.Center; result.X /= newRect.HalfWidth; result.Y /= newRect.HalfHeight; return(result); }).ToArray(); rectangleAspect.Rectangle = newRect; richTextAspect.BorderCurve = adjustedCurve; richTextAspect.VisualBorderCurve = adjustedCurve; undoRedo.OnChange(); }
private static IEnumerable <Vector2> GenerateHoneycomb(AaRectangle2 boundingRect, float circleRadius) { var doubleRadius = 2 * circleRadius; var minIndexX = (int)(boundingRect.MinX / doubleRadius) - 2; var maxIndexX = (int)(boundingRect.MaxX / doubleRadius) + 2; var minIndexY = (int)(boundingRect.MinY / doubleRadius) - 2; var maxIndexY = (int)(boundingRect.MaxY / doubleRadius) + 2; var h = doubleRadius * MathHelper.Cos(MathHelper.Pi / 6); for (var j = minIndexY; j <= maxIndexY; j++) { var zeroCircleCenter = j % 2 == 0 ? new Vector2(0, h * j) : new Vector2(circleRadius, h * j); for (var i = minIndexX; i <= maxIndexX; i++) { yield return(zeroCircleCenter + new Vector2(i * doubleRadius, 0)); } } }
private void FlushStrip(BuildingContext context, int paragraphIndex, float tabOffset, SubList <Subspan> subspans, bool isFirstStrip, bool isLastStrip) { // todo: consider direction var paragraph = context.Text.Paragraphs[paragraphIndex]; //if (!isLastStrip) // subspans = TrimEnd(subspans); var commonSize = MeasureSubspans(context, subspans); var stripSize = new Size2(context.RemainingShape.Width, commonSize.Height); if (paragraph.Style.Alignment != RtParagraphAlignment.Justify || isLastStrip) { // todo: tabs var mergedSubspans = MergeSubspans(subspans); var newRectangles = new RichTextBoxLayoutSpan[mergedSubspans.Count]; var strip = AaRectangle2.FromCornerAndDimensions( context.StripStartPoint.X, context.StripStartPoint.Y, commonSize.Width, commonSize.Height); var rectOffsetX = context.StripStartPoint.X + tabOffset; var charIndex = 0; for (var i = 0; i < mergedSubspans.Count; i++) { var subspan = mergedSubspans[i]; var subspanSize = MeasureSubspan(subspan); var charWidths = subspan.Text.Select(x => measurer.GetCharSize(x, subspan.Style).Width).ToArray(); var subspanWidthWithoutKerning = charWidths.Sum(); var kerningAdjustment = subspanSize.Width / subspanWidthWithoutKerning; var adjustedCharWidths = charWidths.Select(x => x * kerningAdjustment).ToArray(); var charOffsets = Enumerable.Range(0, subspan.Text.Length).Select(x => adjustedCharWidths.Take(x).Sum()).ToArray(); newRectangles[i] = new RichTextBoxLayoutSpan { TextRelPosition = subspan.TextRelPosition, TextAbsPosition = context.Text.GetGlobalIndex(subspan.TextRelPosition), Bounds = new AaRectangle2( new Vector2(rectOffsetX, context.StripStartPoint.Y), new Vector2(rectOffsetX + subspanSize.Width, context.StripStartPoint.Y + commonSize.Height)), Strip = strip, CharOffsets = charOffsets, Text = subspan.Text, Style = subspan.Style, Embedding = subspan.Embedding, EmbeddingHandler = subspan.EmbeddingHandler, EmbeddingImage = subspan.EmbeddingImage }; rectOffsetX += subspanSize.Width; charIndex += subspan.Text.Length; } var adjustment = 0f; switch (paragraph.Style.Alignment) { case RtParagraphAlignment.Left: break; case RtParagraphAlignment.Center: var leftCenterX = rectOffsetX / 2; var stripCenter = stripSize.Width / 2; adjustment = stripCenter - leftCenterX; break; case RtParagraphAlignment.Right: adjustment = stripSize.Width - rectOffsetX; break; case RtParagraphAlignment.Justify: default: throw new ArgumentOutOfRangeException(); } for (var i = 0; i < newRectangles.Length; i++) { newRectangles[i].Bounds.Center.X += adjustment; } context.LayoutSpans.AddRange(newRectangles); context.RemainingShape = new AaRectangle2(context.RemainingShape.MinMin + Vector2.UnitY * stripSize.Height, context.RemainingShape.MaxMax); if (isFirstStrip) { // todo: adjust for other directions var bulletStr = paragraph.Style.ListStyle.GetIconFor(paragraph.Style.TabCount, /*todo*/ 0); FlushBullet(context, new Vector2(tabOffset, strip.MaxY), bulletStr, subspans.First().Style); } } else { throw new NotImplementedException(); } }
private void ArrangeAndDecorateRoot(IStoryGraph sg, int nodeIndex) { var cStory = sg.Aspects[nodeIndex]; var node = sg.NodeObjects[nodeIndex]; var children = sg.Children[nodeIndex]; var numChildren = children.Count; if (numChildren < 2) { var viewpointProps = new TargetedControlledCameraY.Props { Target = Vector3.Zero, Distance = MathHelper.FrustumDistance, FieldOfView = MathHelper.PiOver4, ZNear = 0.1f, ZFar = 100.0f }; cStory.SetDynamicParts(new StoryNodeDynamicParts { DefaultViewpointMechanism = new WallDefaultViewpointMechanism(node, viewpointProps), Hittable = new DummyHittable(), VisualElements = new IVisualElement[0] }); foreach (var child in children) { ArrangeAndDecorateRoot(sg, child); } } else { var distr = CalculateDistribution(numChildren); var radius = distr.RelativeRadius; var oneMore = children.SelectMany(x => sg.Children[x]).Any(); for (int i = 0; i < numChildren; i++) { var pitch = distr.Angles[i].Pitch; var yaw = distr.Angles[i].Yaw; if (oneMore) { //var internalRadius = radius / 2; ArrangeAndDecorateRoot(sg, children[i]); //var yaw = yawPitchBounds.Center.X; //var pitch = yawPitchBounds.Center.Y; var pos = ToCartesian(yaw, pitch, radius * 20); var zAxis = (-pos).Normalize(); var xAxis = Vector3.Cross(Vector3.UnitY, zAxis).Normalize(); var yAxis = Vector3.Cross(zAxis, xAxis); var rotation = Quaternion.RotationToFrame(xAxis, yAxis); sg.NodeObjects[children[i]].Transform = new Transform(1, rotation, pos); //ArrangeAndDecorateInternal(sg, children[i], // AaRectangle2.FromCenter(new Vector2(yaw, pitch), HalfWidth / radius, HalfHeight / radius), // radius); } else { ArrangeAndDecorateInternal(sg, children[i], AaRectangle2.FromCenter(new Vector2(yaw, pitch), HalfWidth / radius, HalfHeight / radius), radius); } } var viewpointProps = new LookAroundCamera.Props { Distance = distr.RelativeRadius, FieldOfView = 0.75f * MathHelper.Pi, ZNear = 0.1f, ZFar = 100.0f, Pitch = 0//MathHelper.PiOver2 + 0.1f }; cStory.SetDynamicParts(new StoryNodeDynamicParts { DefaultViewpointMechanism = new SphereDefaultViewpointMechanism(node, viewpointProps), Hittable = new DummyHittable(), VisualElements = new IVisualElement[0] }); } }
private void ArrangeAndDecorateInternal(IStoryGraph sg, int nodeId, AaRectangle2 yawPitchBounds, float radius) { var cStory = sg.Aspects[nodeId]; var node = sg.NodeObjects[nodeId]; var children = sg.Children[nodeId]; var numChildren = children.Count; var yaw = yawPitchBounds.Center.X; var pitch = yawPitchBounds.Center.Y; var pos = ToCartesian(yaw, pitch, radius); var zAxis = (-pos).Normalize(); var xAxis = Vector3.Cross(Vector3.UnitY, zAxis).Normalize(); var yAxis = Vector3.Cross(zAxis, xAxis); var rotation = Quaternion.RotationToFrame(xAxis, yAxis); node.Transform = new Transform(1, rotation, pos); var numRows = (int)Math.Ceiling(MathHelper.Sqrt(numChildren)); var numCols = (int)Math.Ceiling((float)numChildren / numRows); var totalHeightRequired = MinVerticalDistance * numRows; var totalWidthRequired = MinHorizontalDistance * numRows; var minChildrenRadius = Math.Max(totalWidthRequired / yawPitchBounds.Width, totalHeightRequired / yawPitchBounds.Height); var childRadius = Math.Max(radius + MinRadiusDistance, minChildrenRadius); for (var i = 0; i < numChildren; i++) { var child = children[i]; var row = i / numCols; var col = i % numCols; var childYawWidth = yawPitchBounds.Width / numCols; var childYawHeight = yawPitchBounds.Height / numRows; var childYaw = yawPitchBounds.MinX + childYawWidth * (row + 0.5f); var childPitch = yawPitchBounds.MinY + childYawHeight * (col * 0.5f); var childYawPitchBounds = AaRectangle2.FromCenter(new Vector2(childYaw, childPitch), HalfWidth / childRadius, HalfHeight / childRadius); ArrangeAndDecorateInternal(sg, child, childYawPitchBounds, childRadius); } var visuals = new [] { ModelVisualElement.New(sg.Aspects[sg.Root]) .SetModel(frustumModel) .SetMaterial(frustumMaterial) .SetTransform(new Transform(0.5f, Quaternion.Identity, new Vector3(0, 0, 0.5f * MathHelper.FrustumDistance))) .SetHide(x => !x.ShowAux1) }; var viewpointProps = new TargetedControlledCameraY.Props { Target = Vector3.Zero, Distance = MathHelper.FrustumDistance, FieldOfView = MathHelper.PiOver4, ZNear = 0.1f, ZFar = 100.0f }; var transform2D = new Transform(2, Quaternion.Identity, -MathHelper.FrustumDistance * Vector3.UnitZ); cStory.SetDynamicParts(new StoryNodeDynamicParts { DefaultViewpointMechanism = new WallDefaultViewpointMechanism(node, viewpointProps), Hittable = GetHittableComponent(node, transform2D), VisualElements = visuals, PlacementSurface2D = new PlanarPlacementSurface(node, Transform.Identity), PlacementSurface3D = new PlanarPlacementSurface(node, new Transform(0.05f, Quaternion.Identity, new Vector3(0, 0, 0.5f * MathHelper.FrustumDistance))) }); }
private static void GetExternalPart(LineSegment3 segment, BuildingPrimitive primitive, List <LineSegment3> results) { var invTransform = primitive.Transform.Invert(); var transformedSeg = new LineSegment3(segment.Point1 * invTransform, segment.Point2 * invTransform); var seg = new LineSegment2(transformedSeg.Point1.Xz, transformedSeg.Point2.Xz); if (primitive.Type == BuildingPrimitiveType.Rectangle) { var rect = new AaRectangle2(Vector2.Zero, primitive.Scale.X, primitive.Scale.Z); var conains1 = rect.ContainsPoint(seg.Point1); var conains2 = rect.ContainsPoint(seg.Point2); if (conains1 && conains2) { return; } if (!conains1 && !conains2) { var p = Vector2.Zero; int c = 0; foreach (var rectSegment in rect.GetSegments()) { var rsi = rectSegment.Intersect(seg); if (rsi.HasValue) { p += rsi.Value; c++; } } if (c > 0) { var t = ((p / c) - seg.Point1).Length() / (seg.Point2 - seg.Point1).Length(); var m = segment.Point1 + (segment.Point2 - segment.Point1) * t; GetExternalPart(new LineSegment3(segment.Point1, m), primitive, results); GetExternalPart(new LineSegment3(m, segment.Point2), primitive, results); return; } results.Add(segment); return; } var swap = conains1; if (swap) { CodingHelper.Swap(ref seg.Point1, ref seg.Point2); } var inter = seg.Intersect(new LineSegment2( new Vector2(-primitive.Scale.X, -primitive.Scale.Z), new Vector2(-primitive.Scale.X, primitive.Scale.Z))); if (inter.HasValue) { var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap); results.Add(rs1); return; } inter = seg.Intersect(new LineSegment2( new Vector2(primitive.Scale.X, -primitive.Scale.Z), new Vector2(primitive.Scale.X, primitive.Scale.Z))); if (inter.HasValue) { var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap); results.Add(rs1); return; } inter = seg.Intersect(new LineSegment2( new Vector2(-primitive.Scale.X, primitive.Scale.Z), new Vector2(primitive.Scale.X, primitive.Scale.Z))); if (inter.HasValue) { var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap); results.Add(rs1); return; } inter = seg.Intersect(new LineSegment2( new Vector2(-primitive.Scale.X, -primitive.Scale.Z), new Vector2(primitive.Scale.X, -primitive.Scale.Z))); if (inter.HasValue) { var rs1 = To3(seg.Point1, inter.Value, primitive.Transform, swap); results.Add(rs1); return; } var rs2 = segment; results.Add(rs2); return; } else { var circle = new Circle2(Vector2.Zero, primitive.Scale.X); var conains1 = circle.Contains(seg.Point1); var conains2 = circle.Contains(seg.Point2); if (conains1 && conains2) { return; } if (!conains1 && !conains2) { var rs1 = segment; results.Add(rs1); return; } var swap = conains1; if (swap) { CodingHelper.Swap(ref seg.Point1, ref seg.Point2); } var dpp = seg.Point2 - seg.Point1; var dpc = seg.Point1; var a = dpp.LengthSquared(); var b = Vector2.Dot(dpp, dpc); var c = dpc.LengthSquared() - circle.Radius.Sq(); var discr = b * b - a * c; if (discr < 0) { results.Add(segment); return; } if (discr < MathHelper.Eps5) { results.Add(segment); return; //var l = -b / a; //if (0 <= l && l <= 1) } { var sqrdscr = MathHelper.Sqrt(discr); var l1 = (-b + sqrdscr) / a; var l2 = (-b - sqrdscr) / a; if (0 <= l1 && l1 <= 1) { var rs1 = To3(seg.Point1, Vector2.Lerp(seg.Point1, seg.Point2, l1), primitive.Transform, swap); results.Add(rs1); } if (0 <= l2 && l2 <= 1) { var rs1 = To3(seg.Point1, Vector2.Lerp(seg.Point1, seg.Point2, l2), primitive.Transform, swap); results.Add(rs1); } } } }
private static Transform GetMovieSpeedTransform(AaRectangle2 rect) { return(new Transform(ButtonHalfHeight, Quaternion.Identity, new Vector3( rect.MinX + ButtonHalfHeight, rect.MaxY - ButtonHalfHeight, 0))); }