public IEnumerable <GameLine> GetLinesInRect(DoubleRect rect, bool precise) { var ret = _editorcells.LinesInRect(rect); if (precise) { var newret = new List <GameLine>(ret.Count); foreach (var line in ret) { if (GameLine.DoesLineIntersectRect( line, new DoubleRect( rect.Left, rect.Top, rect.Width, rect.Height)) ) { newret.Add(line); } } return(newret); } return(ret); }
/// <summary> /// Moves the line in the track, grid, and renderer. /// Updates extensions /// Notifies the undo/timeline managers /// </summary> public void MoveLine( GameLine line, Vector2d pos1, Vector2d pos2) { if (line.Position != pos1 || line.Position2 != pos2) { var clone = line.Clone(); var std = line as StandardLine; if (std != null) { SaveCells(line.Position, line.Position2); SaveCells(pos1, pos2); if (_updateextensions) { RemoveExtensions(std); } Track.MoveLine(std, pos1, pos2); if (_updateextensions) { AddExtensions(std); } } else { line.Position = pos1; line.Position2 = pos2; } _editorcells.RemoveLine(clone); _editorcells.AddLine(line); RegisterUndoAction(clone, line); _renderer.RedrawLine(line); } }
/// <summary> /// Snaps the point specified in endpoint of line to another line if within snapradius /// </summary> protected void SnapLineEnd(TrackWriter trk, GameLine line, Vector2d endpoint) { var ignore = new int[] { line.ID }; GetSnapPoint( trk, line.Position, line.Position2, endpoint, ignore, out var snap, line is StandardLine); if (snap == endpoint) { return; } if (line.Position == endpoint) { // don't snap to the same point. if (line.Position2 != snap) { trk.MoveLine(line, snap, line.Position2); } } else if (line.Position2 == endpoint) { // don't snap to the same point. if (line.Position != snap) { trk.MoveLine(line, line.Position, snap); } } }
private bool DoAction(TrackWriter track, GameLine beforeact, GameLine afteract) { if (beforeact == null && afteract == null) { throw new ArgumentNullException( "undo action with no values"); } // remove line if (afteract == null) { track.RemoveLine(beforeact); } // add line else if (beforeact == null) { track.AddLine(afteract.Clone()); } // Replace line else if (beforeact.Type != afteract.Type) { track.RemoveLine(beforeact); track.AddLine(afteract); } //move action else { track.ReplaceLine(beforeact, afteract.Clone()); } return(!(beforeact is SceneryLine)); }
private void UpdateHover(Vector2d gamepos) { _hoverline = null; using (var trk = game.Track.CreateTrackReader()) { GameLine selected; if (UI.InputUtils.CheckPressed(UI.Hotkey.ToolToggleSelection)) { selected = SelectLine(trk, gamepos, out bool knob); } else { selected = SelectInSelection(trk, gamepos)?.line; } if (selected != null) { _hoverline = selected; } } if (CornerContains(gamepos, _nodetop = true, _nodeleft = true) || CornerContains(gamepos, _nodetop = true, _nodeleft = false) || CornerContains(gamepos, _nodetop = false, _nodeleft = false) || CornerContains(gamepos, _nodetop = false, _nodeleft = true)) { _hoverscale = true; } }
private void DropLine() { if (_active) { _hoverline = _selection.line; _hoverknob = !_selection.BothJoints; _hoverknobjoint1 = _selection.joint1; } _lifelocking = false; if (_active) { if (_selection != null) { game.Track.UndoManager.BeginAction(); game.Track.UndoManager.AddChange(_selection.clone, _selection.line); foreach (var s in _selection.snapped) { game.Track.UndoManager.AddChange(s.clone, s.line); } game.Track.UndoManager.EndAction(); } game.Invalidate(); } _active = false; _selection = null; }
private void Stop(bool defertomovetool) { if (Active) { SaveMovedSelection(); } Active = false; UnselectBox(); Unselect(); CancelDrawBox(); _selectionbox = DoubleRect.Empty; _movingselection = false; _movemade = false; _snapline = null; _hoverline = null; _snapknob1 = false; _snapknob2 = false; _scaling = false; _rotating = false; _hoverscale = false; if (defertomovetool) { DeferToMoveTool(); } }
public void RemoveLine(GameLine line) { switch (line.Type) { case LineType.Blue: BlueLines--; break; case LineType.Red: RedLines--; break; case LineType.Scenery: SceneryLines--; break; } LineLookup.Remove(line.ID); Lines.Remove(line.ID); if (line.ID == LinesMax) { LinesMax = line.ID - 1; } if (line.ID == LinesMin) { LinesMin = line.ID + 1; } if (line is StandardLine stl) { RemoveLineFromGrid(stl); } }
private static LineVertex[] GenerateLine(GameLine line, bool hit) { int color = 0; if (line is StandardLine stl) { if (hit) { color = Utility.ColorToRGBA_LE(line.Color); } else if (stl.Trigger != null) { var trigger = Utility.ColorToRGBA_LE( Constants.TriggerLineColor); color = Utility.ChangeAlpha(trigger, 254); } } var lineverts = LineRenderer.CreateTrackLine( line.Position, line.Position2, 2 * line.Width, color); return(lineverts); }
public override void OnUndoRedo(bool isundo, object undohint) { if (Active && (_selection.Count != 0 || _boxselection.Count != 0) && (undohint is int[] lineids)) { if (lineids.Length != 0) { Stop(false); _hoverline = null; Active = true; using (var trk = game.Track.CreateTrackWriter()) { foreach (var lineid in lineids) { var line = trk.Track.LineLookup[lineid]; _selectedlines.Add(line.ID); var selection = new LineSelection(line, true, null); _selection.Add(selection); line.SelectionState = SelectionState.Selected; game.Track.RedrawLine(line); } } _selectionbox = GetBoxFromSelected(_selection); return; } } Stop(true); }
private void SnapJoints(TrackReader trk, GameLine line, ref Vector2d joint1, ref Vector2d joint2) { HashSet <int> ignoreids = new HashSet <int>(); ignoreids.Add(_selection.line.ID); foreach (var snapped in _selection.snapped) { ignoreids.Add(snapped.line.ID); } var snapj1 = joint1; var snapj2 = joint2; bool j1snapped = false; bool j2snapped = false; bool ignorescenery = line is StandardLine; if (_selection.joint1) { j1snapped = GetSnapPoint(trk, joint1, line.Position2, joint1, ignoreids, out snapj1, ignorescenery); } if (_selection.joint2) { j2snapped = GetSnapPoint(trk, line.Position, joint2, joint2, ignoreids, out snapj2, ignorescenery); } if (_selection.BothJoints) { var j1diff = snapj1 - joint1; var j2diff = snapj2 - joint2; if (j1snapped && j2snapped) { if (j1diff.Length < j2diff.Length) { j2snapped = false; } else { j1snapped = false; } } if (j1snapped) { joint2 += j1diff; } else if (j2snapped) { joint1 += j2diff; } } if (j1snapped) { joint1 = snapj1; } else if (j2snapped) { joint2 = snapj2; } }
/// <summary> /// Initialize a lineselection automatically generating clone and applying bothjoints /// </summary> public LineSelection(GameLine Line, bool bothjoints) { line = Line; clone = line.Clone(); joint1 = bothjoints; joint2 = bothjoints; snapped = new List <LineSelection>(); }
/// <summary> /// Initialize a lineselection automatically generating clone and generating joint snap /// </summary> public LineSelection(GameLine Line, Vector2d snapjoint) { line = Line; clone = line.Clone(); joint1 = line.Position == snapjoint; joint2 = line.Position2 == snapjoint; snapped = new List <LineSelection>(); }
/// <summary> /// Initialize a lineselection automatically generating clone and applying bothjoints /// </summary> public LineSelection(GameLine Line, bool bothjoints, List <LineSelection> Snapped) { line = Line; clone = line.Clone(); joint1 = bothjoints; joint2 = bothjoints; snapped = Snapped; }
/// <summary> /// After calling beginaction the current state will be added tothe action /// </summary> public void AddChange(GameLine before, GameLine after) { if (_currentaction == null) { throw new Exception("UndoManager current action null"); } _currentaction.States.Add(before?.Clone()); _currentaction.States.Add(after?.Clone()); }
public void TryMoveForward() { if (CurrentLine.NextLine == null || !CurrentLine.NextLine.IsCanMoveToPosition(CurrentPosition)) { return; } CurrentLine = CurrentLine.NextLine; PlayerForwardMovedEvent.Invoke(); }
private void LineChanged( GameLine line, LineRenderer renderer, Dictionary <int, int> lookup, bool hit) { var lineverts = GenerateLine(line, hit); renderer.ChangeLine(lookup[line.ID], lineverts); }
private void RemoveLine( GameLine line, LineRenderer renderer, Dictionary <int, int> lookup) { int start = lookup[line.ID]; renderer.RemoveLine(start); // preserve the id in the lookup in event of undo }
private void ClearGameField() { while (_lines.Count > 0) { GameLine line = _lines[0]; line.Release(); PoolsContainer.PushObjectByPrefab(line.gameObject, line.PrefabForPulling); _lines.RemoveAt(0); } }
private void DrawHover(GameLine line, bool knob1, bool knob2, bool selected = false) { var start = line.Position; var end = line.Position2; var width = line.Width; var elapsed = _hovertime.ElapsedMilliseconds; int animtime = 250; if (_hovertime.IsRunning) { if (elapsed > animtime * 2) { if (_hoverclick) { _hovertime.Stop(); } else { _hovertime.Stop(); } } game.Track.Invalidate(); } float hoverratio; if (_hoverclick) { animtime = 75; elapsed += 75 / 4; hoverratio = Math.Min(animtime, elapsed) / (float)animtime; } else { hoverratio = Math.Min((Math.Min(animtime, elapsed) / (float)animtime), 0.5f); } var both = knob1 == knob2 == true; var linealpha = both ? 64 : 48; if (selected && both) { linealpha += 16; } GameRenderer.RenderRoundedLine( start, end, Color.FromArgb(linealpha, Color.FromArgb(127, 127, 127)), (width * 2)); bool canlifelock = CanLifelock && line.Type != LineType.Scenery; GameRenderer.DrawKnob(start, knob1, canlifelock, width, hoverratio); GameRenderer.DrawKnob(end, knob2, canlifelock, width, hoverratio); }
public void RemoveLine(GameLine line) { RequiresUpdate = true; using (_sync.AcquireWrite()) { _lineactions.Enqueue( new Tuple <LineActionType, GameLine>( LineActionType.Remove, line)); } }
/// <summary> /// Replaces the line in the track, grid, and renderer. /// Updates extensions /// Notifies the undo/timeline managers /// </summary> public void ReplaceLine(GameLine oldline, GameLine newline) { if (oldline.ID != newline.ID) { throw new Exception("can only replace lines with the same id"); } RegisterUndoAction(oldline, newline); var std = oldline as StandardLine; bool triggerchange = false; if (std != null) { SaveCells(oldline.Position, oldline.Position2); SaveCells(newline.Position, newline.Position2); if (_updateextensions) { RemoveExtensions(std); } var newstd = (StandardLine)newline; using (Track.Grid.Sync.AcquireWrite()) { // this could be a moveline, i think. Track.Grid.RemoveLine(std); Track.Grid.AddLine(newstd); } if (_updateextensions) { AddExtensions(newstd); } if (std.Trigger != null || newstd.Trigger != null) { if (std.Trigger == null) { triggerchange = true; } else if (!std.Trigger.CompareTo(newstd.Trigger)) { triggerchange = true; } } } _editorcells.RemoveLine(oldline); _editorcells.AddLine(newline); Track.LineLookup[newline.ID] = newline; if (triggerchange) { _timeline.TriggerChanged(newline); } _renderer.RedrawLine(newline); }
private void AddLineByPrefab(GameLine prefab) { GameLine line = PoolsContainer.PullObjectByPrefab <GameLine>(prefab.gameObject, Container.transform); line.PrefabForPulling = prefab.gameObject; line.InitialiLine(GameFieldSettings.FieldSize.x); if (_lines.Count > 0) { _lines[_lines.Count - 1].SetNextLine(line); } _lines.Add(line); }
private void UpdateLine(TrackWriter trk, GameLine current, GameLine replacement) { MakingChange(); if (replacement is StandardLine stl) { stl.CalculateConstants(); } trk.ReplaceLine(current, replacement); _editor.NotifyTrackChanged(); _editor.Invalidate(); }
public GameLine[] GetLines() { GameLine[] ret = new GameLine[LineLookup.Count]; int index = ret.Length - 1; foreach (var id in Lines) { ret[index] = LineLookup[id]; index--; } return(ret); }
protected GameLine FixNoFakie2(Timeline timeline, GameLine line, Vector2d movejoint) { const double shiftDist = 1.0e1; const int attemptCount = 500; int offset = game.Track.Offset; var lastFrame = timeline.GetFrame(offset - 1); bool usingjoint1 = line.Position == movejoint; Random rnd = new Random(); rnd.NextDouble(); //Call this once to make sure the RNG is fully shuffled (just in case initial seeds correlate a bit) if (!lastFrame.Crashed) { Vector2d jointPos = movejoint; //The position of the joint which will be moved GameLine currentLine = line; GameLine newLine = currentLine; //The new line position once the modifier has been applied for (int i = 0; i < attemptCount; i++) { jointPos.X = movejoint.X + shiftDist * rnd.NextDouble(); jointPos.Y = movejoint.Y + shiftDist * rnd.NextDouble(); if (usingjoint1) { newLine.Position = jointPos; } else { newLine.Position2 = jointPos; } using (var trk = game.Track.CreateTrackWriter()) { trk.DisableUndo(); trk.MoveLine(currentLine, newLine.Position, newLine.Position2, false); currentLine = newLine; } Rider thisFrame = lastFrame.Simulate(game.Track.getTrack()); if (!thisFrame.SledBroken) { using (var trk = game.Track.CreateTrackWriter()) trk.MoveLine(currentLine, line.Position, line.Position2, false); return(newLine); } } using (var trk = game.Track.CreateTrackWriter()) trk.MoveLine(currentLine, line.Position, line.Position2, false); } return(line); }
protected GameLine CreateLine( TrackWriter trk, Vector2d start, Vector2d end, bool inv, bool snapstart, bool snapend) { GameLine added = null; switch (Swatch.Selected) { case LineType.Blue: added = new StandardLine(start, end, inv); break; case LineType.Red: var red = new RedLine(start, end, inv) { Multiplier = Swatch.RedMultiplier }; red.CalculateConstants(); //multiplier needs to be recalculated added = red; break; case LineType.Scenery: added = new SceneryLine(start, end) { Width = Swatch.GreenMultiplier }; break; default: //In case no swatch is chosen select blue and make a blue line added = new StandardLine(start, end, inv); Swatch.Selected = LineType.Blue; break; } trk.AddLine(added); if (Swatch.Selected != LineType.Scenery) { if (snapstart) { SnapLineEnd(trk, added, added.Position); } if (snapend) { SnapLineEnd(trk, added, added.Position2); } } game.Track.Invalidate(); return(added); }
public void AddLine(GameLine line) { if (line.Type == LineType.Scenery) { if (line.ID == GameLine.UninitializedID || line.ID >= 0) { line.ID = _sceneryidcounter--; } else if (line.ID <= _sceneryidcounter) { _sceneryidcounter = line.ID - 1; } } else { if (line.ID == GameLine.UninitializedID) { line.ID = _idcounter++; } else if (line.ID >= _idcounter) { _idcounter = line.ID + 1; } } switch (line.Type) { case LineType.Blue: BlueLines++; break; case LineType.Red: RedLines++; break; case LineType.Scenery: SceneryLines++; break; } Debug.Assert( !LineLookup.ContainsKey(line.ID), "Lines occupying the same ID -- really bad"); LineLookup.Add(line.ID, line); // here is where using a linkedlist shines: // we can make the most recent change at the front so if it gets // looked up it's easier and faster to find Lines.AddFirst(line.ID); if (line is StandardLine stl) { AddLineToGrid(stl); } }
public GameLine[] GetSortedLines() { GameLine[] ret = new GameLine[LineLookup.Count]; SortedSet <int> temp = new SortedSet <int>(Lines); int index = 0; // sorted as -2 -1 0 1 2 foreach (var line in temp) { ret[index++] = LineLookup[line]; } return(ret); }
/// <summary> /// Gets lines near the point by radius. /// does not support large distances as it only gets a small number of grid cells /// </summary> /// <returns>a sorted array of lines where 0 is the closest point</returns> public GameLine[] LinesInRadius(TrackWriter trk, Vector2d position, double rad) { SortedList <int, GameLine> lines = new SortedList <int, GameLine>(); var inrect = trk.GetLinesInRect(new DoubleRect(position - new Vector2d(24, 24), new Vector2d(24 * 2, 24 * 2)), false); var circle = Rendering.StaticRenderer.GenerateCircle(position.X, position.Y, rad, 8); var ends = LineEndsInRadius(trk, position, rad); foreach (var line in ends) { lines[line.ID] = line; } foreach (var line in inrect) { if (lines.ContainsKey(line.ID)) { continue; } var angle = Angle.FromLine(line.Position, line.Position2); var rect = Utility.GetThickLine( line.Position, line.Position2, angle, line.Width * 2); if (Utility.PointInRectangle(rect, position)) { lines.Add(line.ID, line); continue; } else { for (int i = 0; i < circle.Length; i++) { if (Utility.PointInRectangle(rect, circle[i])) { lines.Add(line.ID, line); break; } } } } GameLine[] ret = new GameLine[lines.Count]; for (int i = 0; i < ret.Length; i++) { ret[i] = lines.Values[(lines.Count - 1) - i]; } return(lines.Values.ToArray()); }