public IStoryLayoutInstance ArrangeAndDecorate(IStoryGraph sg) { var springModel = new NestedCirclesStorySpringModel(coroutineService, x => ArrangeAndDecorateInternal(sg.Root, 0, x, sg), sg); springModel.Apply(); return(new BasicStoryLayoutInstance(sg)); }
private void ArrangeAndDecorateInternal(int nodeIndex, int level, NestedCirclesStorySpringModel springModel, IStoryGraph sg) { var node = sg.NodeObjects[nodeIndex]; var aspect = sg.Aspects[nodeIndex]; var index = node.Id; var dynamicParts = new StoryNodeDynamicParts(); var scale = springModel.GetVisualRadius(index); var visualElems = new List <IVisualElement> { new ModelVisualElement <object>(null) .SetModel(circleModel) .SetMaterial(circleMaterials[level % circleMaterials.Length]) .SetRenderState(circleRenderState) .SetTransform(Transform.Scaling(scale)) .SetTransformSpace(TransformSpace.ScreenAlighned) }; var transform = Transform.Translation(new Vector3(springModel.GetPosition(index), 0)); node.Transform = transform; if (level == 0) { var edgeVisuals = sg.Edges.Select(edge => CreateEdgeVisualElement(node, sg.NodeObjects[edge.First], sg.NodeObjects[edge.Second])); visualElems.AddRange(edgeVisuals); } if (sg.Children[index].Any()) { foreach (var childIndex in sg.Children[index]) { ArrangeAndDecorateInternal(childIndex, level + 1, springModel, sg); } } dynamicParts.VisualElements = visualElems; dynamicParts.Hittable = new CircleHittable <ISceneNode>(node, Transform.Identity, x => new Circle2(Vector2.Zero, scale), x => - 0.01f * level); dynamicParts.DefaultViewpointMechanism = new OrthoDefaultViewpointMechanism(node, new PlaneOrthoBoundControlledCamera.Props { Target = Vector2.Zero, Distance = 1.5f * scale, ZNear = 0.1f, ZFar = 1000f }); aspect.SetDynamicParts(dynamicParts); }