/// <summary> /// Unlinks the specified child, providing no way to ensure they remain delinked. /// </summary> internal static void _SimpleDelink(LinkedDriftoid Parent, LinkedDriftoid Child) { Parent._LinkedChildren.Remove(Child); Child._LinkedParent = null; Parent.OnChildDelink(Child); Child.OnParentDelink(Parent); }
/// <summary> /// Unlinks the specified child. /// </summary> internal static void _Delink(LinkedDriftoid Parent, LinkedDriftoid Child) { _SimpleDelink(Parent, Child); // Apply a small impluse to ensure they stay delinked Vector dif = Parent.Position - Child.Position; dif = dif * (1.0 / dif.Length); Parent._ApplyImpulse(dif); Child._ApplyImpulse(-dif); }
/// <summary> /// Tries linking two driftoids. /// </summary> internal static void _Link(LinkedDriftoid A, LinkedDriftoid B) { int ind; if (!A.IsAncestor(B) && !B.IsAncestor(A)) { if (A._LinkedParent == null) { if (B._CanLink(A, out ind)) { if (B._LinkedParent == null) { int dummy; if (A._CanLink(B, out dummy)) { return; } } B._Link(A, ind); return; } } if (B._LinkedParent == null) { if (A._CanLink(B, out ind)) { A._Link(B, ind); } } } }
/// <summary> /// Called when this is added as a child of another driftoid. /// </summary> public virtual void OnParentLink(LinkedDriftoid Parent) { }
/// <summary> /// Corrects (repositions participants) the link between a parent and child driftoid. /// </summary> internal static void _CorrectLink(LinkedDriftoid Parent, LinkedDriftoid Child, int Iter, Vector Difference, double Distance) { // Is there a problem if (Math.Abs(Distance - Parent.Radius - Child.Radius) > 0.001) { // Equivalent to another problem... Driftoid._CollisionResponse(Parent, Child, Difference, Distance, 1.0); } }
/// <summary> /// Spawns the specified driftoid, out of nowhere. This should not be called during an update. /// </summary> public void Spawn(LinkedDriftoid Driftoid) { this._Driftoids.Add(Driftoid); }
/// <summary> /// Called when this acquires a new child driftoid. /// </summary> public virtual void OnChildLink(int Index, LinkedDriftoid Child) { }
/// <summary> /// Gets if a link from the parent (which is a descendant of this driftoid) to the specified child is allowed. /// </summary> public virtual bool AllowLink(int Index, LinkedDriftoid Parent, LinkedDriftoid Child) { if (this._LinkedParent != null) { return this._LinkedParent.AllowLink(Index, Parent, Child); } return false; }
/// <summary> /// Gets if a link to the specified parent as a child is allowed. /// </summary> public virtual bool AllowParentLink(LinkedDriftoid Parent) { return true; }
/// <summary> /// Draws a "linker" between two linked driftoids. Driftoids and view should already be set up. /// </summary> public static void DrawLinker(LinkedDriftoid Parent, LinkedDriftoid Child) { _LinkerKey lk = new _LinkerKey() { ChildRadius = Child.Radius, ChildBorderWidth = Child.BorderWidth }; _LinkerTexture lt; if (!_LinkerTextures.TryGetValue(lk, out lt)) { _LinkerTextures[lk] = lt = _CreateTexture(lk); } Vector dif = Parent.Position - Child.Position; Texture.Bind2D(lt.Texture.ID); GL.PushMatrix(); GL.Translate(Child.Position.X, Child.Position.Y, 0.0); GL.Rotate(dif.Angle * 180 / Math.PI, 0.0, 0.0, 1.0); GL.Translate(-lt.ChildCenterOffset, 0.0, 0.0); GL.Scale(lt.Size.X / 2.0, lt.Size.Y / 2.0, 1.0); GL.Translate(1.0, 0.0, 0.0); GL.Begin(BeginMode.Quads); GL.Vertex2(-1.0f, -1.0f); GL.TexCoord2(0f, 0f); GL.Vertex2(-1.0f, 1.0f); GL.TexCoord2(1f, 0f); GL.Vertex2(1.0f, 1.0f); GL.TexCoord2(1f, 1f); GL.Vertex2(1.0f, -1.0f); GL.TexCoord2(0f, 1f); GL.End(); GL.PopMatrix(); }
/// <summary> /// Gets a visual for a linker between to linked driftoids. /// </summary> public static Visual GetLinkerVisual(LinkedDriftoid Parent, LinkedDriftoid Child) { return new _LinkerVisual() { Parent = Parent, Child = Child }; }
public override bool AllowLink(int Index, LinkedDriftoid Parent, LinkedDriftoid Child) { return true; }
public Structure(LinkedDriftoid Driftoid) { this._Driftoid = Driftoid; }
/// <summary> /// Indicates that a player is trying to manually delink a driftoid from its parent. /// </summary> public void TryDelink(Player Player, LinkedDriftoid Target) { if (Target.LinkedParent != null && Target.Reaction == null) { if (this.HasLinkControl(Player, Target)) { LinkedDriftoid._Delink(Target.LinkedParent, Target); } } }
/// <summary> /// Gets if a link to the specified child is possible. Returns the index of the candidate. /// </summary> internal bool _CanLink(LinkedDriftoid Child, out int Index) { Index = 0; Vector pos = this.Position; double tarangle = (Child.Position - pos).Angle; if (this._LinkedParent != null) { double lowangle = (this._LinkedParent.Position - pos).Angle; foreach (LinkedDriftoid ld in this._LinkedChildren) { double highangle = (ld.Position - pos).Angle; if (Vector.AngleBetween(tarangle, lowangle, highangle)) { break; } lowangle = highangle; Index++; } } else { if (this._LinkedChildren.Count == 0) { Index = 0; } else { if (this._LinkedChildren.Count == 1) { Index = 1; } else { Index = 0; double lowangle = (this._LinkedChildren[0].Position - pos).Angle; for (int t = 1; t < this._LinkedChildren.Count; t++) { double highangle = (this._LinkedChildren[t].Position - pos).Angle; if (Vector.AngleBetween(tarangle, lowangle, highangle)) { break; } lowangle = highangle; Index++; } } } } return Child.AllowParentLink(this) && this.AllowLink(Index, this, Child); }
/// <summary> /// Called when a child is delinked from this driftoid. /// </summary> public virtual void OnChildDelink(LinkedDriftoid Child) { }
/// <summary> /// Links a child driftoid to this driftoid. /// </summary> private void _Link(LinkedDriftoid Child, int Index) { // Make link this._LinkedChildren.Add(null); for (int t = this._LinkedChildren.Count - 1; t > Index; t--) { this._LinkedChildren[t] = this._LinkedChildren[t - 1]; } this._LinkedChildren[Index] = Child; Child._LinkedParent = this; // Events this.OnChildLink(Index, Child); Child.OnParentLink(this); }
/// <summary> /// Gets if a player can control the links associated with the target. /// </summary> public bool HasLinkControl(Player Player, LinkedDriftoid Target) { LinkedDriftoid cur = Target; while (cur != null) { NucleusDriftoid ndr = cur as NucleusDriftoid; if (ndr != null) { if (ndr.Owner == Player) { return true; } } cur = cur.LinkedParent; } return false; }