public IMView(Graph <T, P> graph, IViewParent <T, P> parent) { this.graph = graph; this.parent = parent; entityDrawerBounds = new Dictionary <T, Rect>(); edgeMarkerBounds = new Dictionary <Relation <T, P>, Rect>(); entitySelection = new HashSet <T>(); dragEdgeSource = new HashSet <T>(); // draw the targets last drawOrdered = new LinkedList <T>(graph.Vertices); foreach (var target in graph.Vertices.Where(parent.IsSeed)) { drawOrdered.Remove(target); drawOrdered.AddLast(target); } // initialize the drawers tagDrawer = new BasicRelationDrawer <T, P>(); entityWidgetType = (EntityWidgetType)GUIUtil.GetPrefsInt(PrefsKeyLayout, (int)defaultWidgetType); InitEntityWidget(); // make the graph fill the view transform = GetOptimalTransform(); }
void DrawMinimap() { var entityViewPositions = graph.VerticesData.Values.Select(data => transform.Apply(data.pos)); var style = SkinManager.GetSkin().minimap; Rect drawRect = parent.GetViewRect(); minimapRect = Minimap.GetRect(SkinManager.GetSkin().minimap, Settings.Instance.minimapLocation, drawRect); minimapTransform = Minimap.Draw(entityViewPositions, minimapRect, drawRect, false, style); }
public void FitViewRectToGraph(bool immediately) { if (immediately) { transform = GetOptimalTransform(); return; } // viewRect: canvas shrunk down to 80% Rect viewRect = parent.GetViewRect(); viewRect = Util.CenterRect(viewRect.center, viewRect.GetExtents() * 0.8f); // find graphRect (logical coords) var logicalPositions = graph.VerticesData.Values.Select(v => v.pos); Rect logicalPosBounds = Util.GetBounds(logicalPositions).ClampExtents(0.01f, 0.01f, float.MaxValue, float.MaxValue); var logicalExtents = logicalPosBounds.GetExtents(); var viewExtents = viewRect.GetExtents(); // fit logical extents into display extents var fullScale = new Vector2( viewExtents.x / logicalExtents.x, viewExtents.y / logicalExtents.y ); var targetScale = transform.scale.Clamp(fullScale * 0.5f, fullScale); bool scaleChange = targetScale != transform.scale; var targetTransform = new Transform2d(transform.translation, targetScale, transform.rotation); var targetViewGraphBounds = targetTransform.Apply(logicalPosBounds); float xOver = targetViewGraphBounds.xMax - viewRect.xMax; float xUnder = targetViewGraphBounds.xMin - viewRect.xMin; float yOver = targetViewGraphBounds.yMax - viewRect.yMax; float yUnder = targetViewGraphBounds.yMin - viewRect.yMin; var shift = new Vector2( xOver > 0 ? xOver : xUnder < 0 ? xUnder : 0, yOver > 0 ? yOver : yUnder < 0 ? yUnder : 0); bool translateChanged = shift != Vector2.zero; if (scaleChange || translateChanged) { targetTransform.translation -= shift; Tweener.gen.Add(new Tween <Transform2d>(t => transform = t, 0.2f, TweenUtil.Transform2(transform, targetTransform, TwoValueEasing.Linear))); } }
static Transform2d Zoom(Transform2d transform, bool zoomIn, bool affectX, bool affectY, Vector2 fixPosition) { // adjust the offset such that the window stays centered on the same graph position var fixPositionBase = transform.Revert(fixPosition); var targetTransform = new Transform2d(transform); if (affectX) { targetTransform.scale.x *= zoomIn ? 3f / 2 : 2f / 3; } if (affectY) { targetTransform.scale.y *= zoomIn ? 3f / 2 : 2f / 3; } var newfixPosition = targetTransform.Apply(fixPositionBase); targetTransform.translation += fixPosition - newfixPosition; return(targetTransform); }
// get a transform that makes the graph fit into the view rect public static Transform2d FitPointsIntoRect(IEnumerable <Vector2> logicalPositions, Rect displayRect) { // get bounds, ensure they are non-zero Rect logicalPosBounds = Util.GetBounds(logicalPositions).ClampExtents(0.01f, 0.01f, float.MaxValue, float.MaxValue); var logicalExtents = logicalPosBounds.GetExtents(); var displayExtents = displayRect.GetExtents(); // fit logical extents into display extents var scale = new Vector2( logicalExtents.x == 0 ? 0 : displayExtents.x / logicalExtents.x, logicalExtents.y == 0 ? 0 : displayExtents.y / logicalExtents.y ); // translation: put points center into outer rect center Vector2 pointsCenter = new Vector2(logicalPosBounds.center.x * scale.x, logicalPosBounds.center.y * scale.y); Vector2 translation = displayRect.center - pointsCenter; var transform = new Transform2d(translation, scale, 0); return(transform); }
public static void Copy(Transform2d from, Transform2d to) { to.translation = from.translation; to.scale = from.scale; to.rotation = from.rotation; }
public Transform2d(Transform2d other) { this.translation = other.translation; this.scale = other.scale; this.rotation = other.rotation; }
public void HandleEvent(Event ev) { switch (ev.rawType) { case EventType.mouseUp: draggedEntity = null; selectionRectActive = false; parent.RepaintView(); break; } switch (ev.type) { case EventType.mouseDown: // clicked on minimap -> focos camera on click pos if (Settings.Instance.showMinimap && minimapRect.Contains(ev.mousePosition)) { SetCenter(minimapTransform.Revert(ev.mousePosition)); break; } var clickEntity = GetEntityAtPosition(ev.mousePosition); if (clickEntity != null) { foreach (var source in dragEdgeSource) { parent.GetBackend().CreateRelation(source, clickEntity); } dragEdgeSource = new HashSet <T>(); if (ev.button == 0) // left click { draggedEntity = clickEntity; // update selection bool controlHeld = (ev.modifiers & EventModifiers.Control) != 0; if (controlHeld) { if (entitySelection.Contains(clickEntity)) { entitySelection.Remove(clickEntity); } else { entitySelection.Add(clickEntity); } } else { entitySelection = new HashSet <T>(new[] { clickEntity }); } OnEntitySelectionChange(); parent.RepaintView(); } } else // clickEntity == null { var clickEdge = GetEdgeAtPosition(ev.mousePosition); if (clickEdge == null) // clickEdge == null && clickEntity == null { if (ev.button != 1) // not a right click { bool controlHeld = (ev.modifiers & EventModifiers.Control) != 0; if (!controlHeld) { entitySelection = new HashSet <T>(); } // stop edge creation dragEdgeSource = new HashSet <T>(); // start rect selection selectionRectActive = true; selectionRectOrigin = ev.mousePosition; parent.RepaintView(); } } } break; case EventType.ContextClick: var ccEntity = GetEntityAtPosition(ev.mousePosition); if (ccEntity != null) { if (!entitySelection.Contains(ccEntity)) { entitySelection = new HashSet <T>() { ccEntity } } ; HandleEntityContextClick(entitySelection); Event.current.Use(); break; } var ccEdge = GetEdgeAtPosition(ev.mousePosition); if (ccEdge != null) { HandleRelationContextClick(ccEdge); Event.current.Use(); break; } break; case EventType.MouseMove: // update hover item and repaint if it changed var newHoverEntity = GetEntityAtPosition(ev.mousePosition); var newHoverRelation = (newHoverEntity != null) ? null : GetEdgeAtPosition(ev.mousePosition); bool hoverChange = newHoverEntity != hoverEntity || newHoverRelation != hoverRelation; hoverEntity = newHoverEntity; hoverRelation = newHoverRelation; bool doRepaint = hoverChange; // movement over the hover-item requires a repainted tooltip // also repaint if we are dragging an edge doRepaint |= dragEdgeSource.Any(); if (doRepaint) { parent.RepaintView(); } break; case EventType.MouseUp: draggedEntity = null; selectionRectActive = false; parent.RepaintView(); break; case EventType.MouseDrag: if (draggedEntity != null) { parent.MoveEntity(draggedEntity, transform.RevertScale(ev.delta)); } else if (selectionRectActive) // update selection { // GetBounds ensures that xmin < xmax and ymin < ymax var selectionRect = Util.GetBounds(new[] { ev.mousePosition, selectionRectOrigin }); var touchedEntityBounds = entityDrawerBounds.Where(pair => selectionRect.Intersects(pair.Value)); entitySelection = new HashSet <T>(touchedEntityBounds.Select(pair => pair.Key)); OnEntitySelectionChange(); } else { Shift(ev.delta); } parent.RepaintView(); break; case EventType.ScrollWheel: bool xZoom = (ev.modifiers & EventModifiers.Control) == 0; bool yZoom = (ev.modifiers & EventModifiers.Shift) == 0; bool zoomIn = Settings.Instance.invertZoom ? ev.delta.y > 0 : ev.delta.y < 0; var targetTransform = Zoom(transform, zoomIn, xZoom, yZoom, ev.mousePosition); Tweener.gen.Add(new Tween <Transform2d>(t => transform = t, 0.1f, TweenUtil.Transform2(transform, targetTransform, TwoValueEasing.Linear))); //.MoveTransform2dTo(transform, t=>Zoom(t, zoomIn, xZoom, yZoom, ev.mousePosition), 0.1f, true); ev.Use(); parent.RepaintView(); break; } }