protected GenFragmentGenerator(GenDataDef genDataDef, GenWriter writer, Fragment fragment, GenObject genObject) { _genDataDef = genDataDef; _writer = writer; _fragment = fragment; GenObject = genObject; }
public void RefreshProfile(GenDataBase genDataBase, GenObject genObject) { var selectedItem = ProfileNavigatorTreeView.SelectedNode; var dataProfile = GenDataEditorViewModel.Data.Profile; dataProfile.Fragment = ProfileEditorTreeViewBuilder.GetNodeData(selectedItem); var text = dataProfile.GetNodeProfileText(); // Don't change to prevent unnecessary rendering and side effects if (text != ProfileTextBox.Text) { var start = ProfileTextBox.SelectionStart; ProfileTextBox.Clear(); ProfileTextBox.Text = text; ProfileTextBox.SelectionStart = start; } text = dataProfile.GetNodeExpansionText(genDataBase, genObject); // Don't change to prevent unnecessary rendering and side effects if (text != ProfileExpansionTextBox.Text) { var start = ProfileExpansionTextBox.SelectionStart; ProfileExpansionTextBox.Clear(); ProfileExpansionTextBox.Text = text; ProfileExpansionTextBox.SelectionStart = start; } }
public GenSegmentGenerator(GenDataDef genDataDef, GenWriter genWriter, GenObject genObject, Fragment fragment) : base(genDataDef, genWriter, genObject, fragment) { Segment = (Segment)fragment; GenCardinality = Segment.GenCardinality; Navigator = new SegmentNavigator(this); }
public void GenLookupContextTest() { var d = SetUpLookupContextData(); var f = d.GenDataDef; var r = new GenProfileFragment(new GenProfileParams(GenData.GenDataDef)); var b = new GenBlock(new GenFragmentParams(f, r)); var p0 = new GenPlaceholderFragment(new GenPlaceholderFragmentParams(f, b, f.GetId("Parent.Name"))); var t0 = new GenTextFragment(new GenTextFragmentParams(f, b, ",")); b.Body.Add(p0); b.Body.Add(t0); var g = new GenLookup(new GenLookupParams(f, b, "Lookup.Name=Child.Lookup")); var p1 = new GenPlaceholderFragment(new GenPlaceholderFragmentParams(f, g, f.GetId("Lookup.Name"))); var t1 = new GenTextFragment(new GenTextFragmentParams(f, g, ",")); Assert.IsFalse(g.NoMatch); b.Body.Add(g); g.Body.Add(p1); g.Body.Add(t1); var parent = GenObject.GetContext(d.Root, "Parent"); var child = GetFirstObjectOfSubClass(parent, "Child"); b.GenObject = child; VerifyFragment(d, b, "GenBlock", FragmentType.Block, "Block", "`{`Parent.Name`,`%Lookup.Name=Child.Lookup:`Lookup.Name`,`]`]", "Parent,Valid,", false, null, r.Profile.GenDataBase.GenDataDef); child = GetLastObjectInSubClass(child); b.GenObject = child; VerifyFragment(d, b, "GenBlock", FragmentType.Block, "Block", "`{`Parent.Name`,`%Lookup.Name=Child.Lookup:`Lookup.Name`,`]`]", "Parent,", false, null, r.Profile.GenDataBase.GenDataDef); }
public static string ExpandSecondary(GenDataDef genDataDef, GenObject genObject, Fragment fragment) { if (fragment is ContainerFragment) { return(Create(genDataDef, genObject, fragment).ExpandSecondary()); } return(""); }
protected static GenObject GetLastObjectInSubClass(GenObject genObject) { if (genObject.ParentSubClass.Count == 0) { return(null); } return(genObject.ParentSubClass[genObject.ParentSubClass.Count - 1]); }
public void VerifyParentChildReferenceGetValue() { var dataChild = SetUpParentChildData("Child", "Grandchild", "Grandchild"); var dataParent = SetUpParentChildReferenceData("Parent", "Child", "Child", "Child", dataChild); var genObject = GenObject.GetContext(dataParent.Root, "GrandChild"); var id = dataParent.GenDataDef.GetId("Parent", "Name"); Assert.AreEqual("Parent", genObject.GetValue(id)); }
/// <summary> /// A constraint used to link two objects together, and push or pull them until they are a specified distance apart. /// Each link point is offset to the center point of its connected object by default. /// </summary> /// <param name="pointA">The first object to use as a connection point.</param> /// <param name="pointB">The second object to use as a connection point.</param> public GenLink(GenObject pointA, GenObject pointB) { Stiffness = 1f; TearDistance = 0f; PointA = pointA; PointB = pointB; _restingDistance = Vector2.Distance(PointA.OriginPosition, PointB.OriginPosition); }
protected static GenObject GetNextObjectInSubClass(GenObject genObject) { var i = genObject.ParentSubClass.IndexOf(genObject); if (i > genObject.ParentSubClass.Count) { return(null); } return(genObject.ParentSubClass[i + 1]); }
/// <summary> /// Set the subclass reference. /// </summary> /// <param name="parent"></param> /// <param name="subClassName">The childe class name.</param> /// <param name="reference">The reference path.</param> private static void SetSubClassReference(GenObject parent, string subClassName, string reference) { var subClassIndex = parent.Definition.SubClasses.IndexOf(subClassName); var sub = parent.SubClass[subClassIndex] as SubClassReference; if (sub != null) { sub.Reference = reference; } }
public static void DelegateTest <U>() { IGen <object> obj = new GenObject(); ThreadStart d = new ThreadStart(obj.Target <U>); d(); Test.Eval(Test.Xcounter == 1); Test.Xcounter = 0; }
public void TestObjectContextOfSiblingWithInheritance() { var dataFile = GetTestDataFileName("InheritanceDataSaveTest"); var d = PopulateInheritanceData(dataFile); var container = GetFirstObject(d); var @virtual1 = GetFirstObjectOfSubClass(container, "Abstract"); var containerContext = GenObject.GetContext(container, "Abstract"); Assert.AreSame(@virtual1, containerContext); }
public void ContextNoReferencePropertyExistsNoReferenceTest() { var f = GenDataDef.CreateMinimal(); var d = new GenDataBase(f); SetUpData(d); var genObject = GenObject.GetContext(d.Root, "Class"); var id = f.GetId("Class.Reference"); Assert.AreEqual("", genObject.GetValue(id)); }
public static GenObject CreateDefinitionSubClass(GenObject @class, string name, string reference, string relationship) { var subClass = new GenObject(@class, @class.SubClass[0], 2); SetAttribute(subClass, 0, name); SetAttribute(subClass, 1, reference); SetAttribute(subClass, 2, relationship); @class.SubClass[0].Add(subClass); return(subClass); }
private static void SetAttribute(GenObject genObject, int index, string value) { if (genObject.Attributes.Count == index) { genObject.Attributes.Add(value); } else { genObject.Attributes[index] = value; } }
private MuTruncatedGen(GenObject o, double[] range, double muMean, double sigma) { SGNFnAParam A = o.A.Clone(); A.MuMean = muMean; A.S = sigma; A.S2 = sigma * sigma; Icdf icdf = new Icdf(o, A, range); this.Mu = icdf.Bidon(); }
public void TestObjectContextOfChild() { var d = SetUpParentChildData("Parent", "Child", "FirstChild"); var parent = GetFirstObject(d); var child = GetFirstObjectOfSubClass(parent, "Child"); var parentContext = GenObject.GetContext(parent, "Child"); Assert.AreSame(child, parentContext); parentContext = GenObject.GetContext(parent, "CHILD"); // Case independent search Assert.AreSame(child, parentContext); }
public void ContextWithReferenceTests() { var dataChild = SetUpParentChildData("Child", "Grandchild", "Grandchild"); var dataParent = SetUpParentChildReferenceData("Parent", "Child", "Child", "Child", dataChild); for (var i = 1; i < dataParent.GenDataDef.Classes.Count; i++) { var genObject = GenObject.GetContext(dataParent.Root, dataParent.GenDataDef.Classes[i].Name); Assert.IsNotNull(genObject, i + ": " + dataParent.GenDataDef.Classes[i].Name); Assert.AreEqual(genObject.ParentSubClass.Definition.SubClass.RefClassId, genObject.ClassId); } }
public void TestObjectContextOfAReferenceObjectFromParent() { var dataChild = SetUpParentChildData("Child", "Grandchild", "Grandchild"); var dataParent = SetUpParentChildReferenceData("Parent", "Child", "Child", "Child", dataChild); var parent = GetFirstObject(dataParent); var grandchild = GetFirstObjectOfSubClass(GetFirstObject(dataChild), "GrandChild"); Assert.IsNotNull(grandchild); var granddhildContext = GenObject.GetContext(parent, "Grandchild"); Assert.AreSame(grandchild, granddhildContext); }
protected static void CheckOrder(GenDataBase d1, string order, string action) { var d = d1; var id = d.GenDataDef.GetId("SubClass.Name"); var s0 = GenObject.GetContext(d.Root, "SubClass"); var s1 = GetNextObjectInSubClass(s0); var s2 = GetNextObjectInSubClass(s1); Assert.AreEqual("SubClass" + order[0], s0.GetValue(id), action + " first item"); Assert.AreEqual("SubClass" + order[1], s1.GetValue(id), action + " second item"); Assert.AreEqual("SubClass" + order[2], s2.GetValue(id), action + " third item"); }
public static int Main() { Outer.IGen <int> IGenInt = new GenInt(); IGenInt._Init(new int()); Eval(IGenInt.InstVerify(typeof(int))); Outer.IGen <double> IGenDouble = new GenDouble(); IGenDouble._Init(new double()); Eval(IGenDouble.InstVerify(typeof(double))); Outer.IGen <string> IGenString = new GenString(); IGenString._Init("string"); Eval(IGenString.InstVerify(typeof(string))); Outer.IGen <object> IGenObject = new GenObject(); IGenObject._Init(new object()); Eval(IGenObject.InstVerify(typeof(object))); Outer.IGen <Guid> IGenGuid = new GenGuid(); IGenGuid._Init(new Guid()); Eval(IGenGuid.InstVerify(typeof(Guid))); Outer.IGen <RefX1 <int> > IGenConstructedReference = new GenConstructedReference(); IGenConstructedReference._Init(new RefX1 <int>()); Eval(IGenConstructedReference.InstVerify(typeof(RefX1 <int>))); Outer.IGen <ValX1 <string> > IGenConstructedValue = new GenConstructedValue(); IGenConstructedValue._Init(new ValX1 <string>()); Eval(IGenConstructedValue.InstVerify(typeof(ValX1 <string>))); Outer.IGen <int[]> IGen1DIntArray = new Gen1DIntArray(); IGen1DIntArray._Init(new int[1]); Eval(IGen1DIntArray.InstVerify(typeof(int[]))); Outer.IGen <string[, ]> IGen2DStringArray = new Gen2DStringArray(); IGen2DStringArray._Init(new string[1, 1]); Eval(IGen2DStringArray.InstVerify(typeof(string[, ]))); Outer.IGen <object[][]> IGenJaggedObjectArray = new GenJaggedObjectArray(); IGenJaggedObjectArray._Init(new object[1][]); Eval(IGenJaggedObjectArray.InstVerify(typeof(object[][]))); if (result) { Console.WriteLine("Test Passed"); return(100); } else { Console.WriteLine("Test Failed"); return(1); } }
public void ContextNoFirstPropertyExistsSecondTest() { var f = GenDataDef.CreateMinimal(); var d = new GenDataBase(f); SetUpData(d); CreateGenObject(d.Root, "Class", "Class0"); var genObject = GetNextObjectInSubClass(GenObject.GetContext(d.Root, "Class")); var id = f.GetId("Class.First"); Assert.AreEqual("", genObject.GetValue(id)); }
public static GenObject CreateDefinitionClass(GenObject root, string name, string title, string inheritance, GenDataBase d) { var @class = new GenObject(root, root.SubClass[0], 1); SetAttribute(@class, 0, name); SetAttribute(@class, 1, title); SetAttribute(@class, 2, inheritance); @class.SubClass.Add(new GenSubClass(d, @class, 2, null)); @class.SubClass.Add(new GenSubClass(d, @class, 3, null)); root.SubClass[0].Add(@class); return(@class); }
public void ContextEmptyFirstPropertyExistsTest() { var f = GenDataDef.CreateMinimal(); f.AddClassInstanceProperty(1, "First"); var d = new GenDataBase(f); SetUpData(d); var genObject = GenObject.GetContext(d.Root, "Class"); var id = f.GetId("Class.First"); Assert.AreEqual("", genObject.GetValue(id)); }
public void ContextReferencePropertyExistsWithValueTest() { var f = GenDataDef.CreateMinimal(); var idx = f.AddClassInstanceProperty(1, "Reference"); var d = new GenDataBase(f); SetUpData(d); var id = f.GetId("Class.Reference"); var genObject = GenObject.GetContext(d.Root, "Class"); genObject.Attributes[idx] = "Reference value"; Assert.AreEqual("Reference value", genObject.GetValue(id)); }
public static void ThreadPoolTest() { ManualResetEvent evt = new ManualResetEvent(false); IGen <object> obj = new GenObject(); TimerCallback tcb = new TimerCallback(obj.Target); Timer timer = new Timer(tcb, evt, Test_thread15.delay, Test_thread15.period); evt.WaitOne(); timer.Dispose(); Test_thread15.Eval(Test_thread15.Xcounter >= Test_thread15.nThreads); Test_thread15.Xcounter = 0; }
public void VerifySetUpParentChildDataMethod() { var d = SetUpParentChildData("Parent", "Child", "Child"); var f = d.GenDataDef; Assert.AreEqual(3, f.Classes.Count); Assert.AreEqual("Parent", f.GetClassName(1)); Assert.AreEqual("Child", f.GetClassName(2)); Assert.AreEqual(1, f.GetClassSubClasses(1).Count); Assert.AreEqual(2, f.GetClassSubClasses(1)[0].SubClass.ClassId); Assert.AreEqual("", f.GetClassSubClasses(1)[0].Reference); Assert.AreEqual("Parent", GenObject.GetContext(d.Root, "Parent").Attributes[0]); Assert.AreEqual("Child", GenObject.GetContext(d.Root, "Child").Attributes[0]); }
protected static GenObject GetFirstObjectOfSubClass(GenObject genObject, string subClassName) { Contract.Requires(genObject != null, "The object cannot be null"); Contract.Requires(genObject.Definition != null, "The object definition is required"); var index = genObject.Definition.IndexOfSubClass(subClassName); if (index == -1) { throw new ArgumentException("Class is not a subclass", subClassName); } var subClass = genObject.GetSubClass(subClassName); return(subClass.Count == 0 ? null : subClass[0]); }
/// <summary> /// Initializes a new instance of the GenObjectViewModel class. /// </summary> /// <param name="genObject">The <see cref="GenObject"/> being edited.</param> /// <param name="definition">The class definition of the object being edited.</param> /// <param name="isReadOnly">Is this data readonly?</param> public GenObjectViewModel(GenObject genObject, GenNamedApplicationBase definition, bool isReadOnly) { IsReadOnly = isReadOnly; IgnorePropertyValidation = true; Definition = definition; GenAttributes = new GenAttributes(genObject.GenDataBase.GenDataDef, genObject.ClassId) { GenObject = genObject }; GenObject = genObject; Changed = false; IsNew = false; }
private static void CreateDefinitionProperty(GenObject @class, string name, string title, string dataType, string @default = "", string lookupType = "", string lookupDependence = "", string lookupTable = "") { var property = new GenObject(@class, @class.SubClass[1], 3); SetAttribute(property, 0, name); SetAttribute(property, 1, title); SetAttribute(property, 2, dataType); SetAttribute(property, 3, @default); SetAttribute(property, 4, lookupType); SetAttribute(property, 5, lookupDependence); SetAttribute(property, 6, lookupTable); @class.SubClass[1].Add(property); }
public string GetNodeExpansionText(GenDataBase genData, GenObject genObject) { GenObject = genObject; if (Fragment == null) { return(""); } var context = GenObject.GetContext(genObject ?? genData.Root, Fragment.ClassName()); if (context == null) { return(""); } return(GenFragmentExpander.Expand(genData.GenDataDef, context, Fragment)); }
/// <summary> /// Creates a playable sound instance managed by a <c>GenSound</c> object. /// </summary> /// <param name="sound">The <c>GenSound</c> object that this sound instance is handled by.</param> public GenSoundInstance(GenSound sound) { _soundParent = sound; _sound = _soundParent.Sound; SoundInstance = _soundParent.Sound.CreateInstance(); SoundInstance.IsLooped = _soundParent.IsLooped; SoundInstance.Volume = _soundParent.Volume; SoundInstance.Pitch = _soundParent.Pitch; SoundInstance.Pan = _soundParent.Pan; _fadeTimer = new GenTimer(0f, null); Follow = _soundParent.Follow; // Call UpdateSound initially to correct the volume value. UpdateSound(); }
/// <summary> /// Checks for overlap between the movements bounds of two objects. /// </summary> /// <param name="objectA">The first object to check for an overlap.</param> /// <param name="objectB">The second object to check for an overlap.</param> /// <param name="callback">The delegate method that will be invoked if an overlap occurs.</param> /// <returns>True if an overlap occurs, false if not.</returns> public static bool Overlap(GenObject objectA, GenObject objectB, CollideEvent callback) { // Check if both objects are alive to avoid unwanted overlap checks that may be called by a quadtree. if ((objectA.Exists && objectA.Active) && (objectB.Exists && objectB.Active)) { if (objectA.MoveBounds.Intersects(objectB.MoveBounds)) { if (callback != null) { _collideEventArgs.ObjectA = objectA; _collideEventArgs.ObjectB = objectB; _collideEventArgs.TouchingA = GenObject.Direction.None; _collideEventArgs.TouchingB = GenObject.Direction.None; callback(_collideEventArgs); } return true; } } return false; }
/// <summary> /// Make a link constraint connecting two object points. /// </summary> /// <param name="pointA">The first object to use as a connection point.</param> /// <param name="pointB">The second object to use as a connection point.</param> public void MakeLink(GenObject pointA, GenObject pointB) { Add(pointA); Add(pointB); Links.Add(new GenLink(pointA, pointB)); }
/// <summary> /// A particle emitter that emits particles from a point, /// </summary> /// <param name="x">The x position of the top-left corner of the emitter.</param> /// <param name="y">The y position of the top-left corner of the emitter.</param> public GenEmitter(float x, float y) { _position = new Vector2(x, y); _bounds = new GenAABB(x, y, 0f, 0f); _boundingRect = Rectangle.Empty; MinParticleSpeedX = -100; MaxParticleSpeedX = 100; MinParticleSpeedY = -100; MaxParticleSpeedY = 100; MinRotation = 0; MaxRotation = 0; MinRotationSpeed = 0; MaxRotationSpeed = 0; Colors = new List<Color>(); StartAlpha = 1f; EndAlpha = 1f; StartScale = 1f; EndScale = 1f; Explode = true; EmitQuantity = 10; _emitTimer = new GenTimer(0.1f, EmitParticles); _emitTimer.IsLooping = true; InheritVelocity = false; Parent = null; ParentOffset = Vector2.Zero; }
/// <summary> /// Applies 2D positional adjustments to the sound instance using a source and receivers (cameras) of the sound. /// The volume, pan, and pitch values are averaged when using multiple cameras depending on their distances from the source. /// </summary> /// <param name="source">The source of the sound.</param> /// <param name="cameras">A list of the receivers (cameras) of the sound.</param> public void Apply2D(GenObject source, List<GenCamera> cameras) { if ((cameras != null) && (cameras.Count > 0)) { Vector2 distance = source.CenterPosition - cameras[0].CenterPosition; if (cameras.Count == 1) { float distanceFade = MathHelper.Clamp((GenSound.DistanceScale - distance.Length()) / GenSound.DistanceScale, 0f, 1f); SoundInstance.Volume = ((_soundParent == null) ? _volume : _soundParent.Volume) * distanceFade; SoundInstance.Pan = MathHelper.Clamp(distance.X / GenSound.DistanceScale, -1f, 1f) * -cameras[0].Up.Y; SoundInstance.Pitch = GenSound.GetDopplerShift(Follow.Velocity, cameras[0].Velocity, distance, GenSound.DopplerFactor); } else { GenCamera workingCamera = cameras[0]; // Get the distance from the sound source to the center of the first camera, and set it as the initial minimum distance. Vector2 distanceMin = distance; float distanceMinLength = distanceMin.Length(); // Iterate through each remaining camera, checking for the one closest to the sound source. for (int i = 1; i < cameras.Count; i++) { Vector2 newDistance = source.CenterPosition - cameras[i].CenterPosition; float newDistanceLength = newDistance.Length(); // If the current camera is closest to the sound source, set it as the working camera and minimum distance. if (newDistanceLength < distanceMinLength) { workingCamera = cameras[i]; distanceMin = newDistance; distanceMinLength = newDistanceLength; } } float cameraFactor = 0f; float cameraFactorSum = 0f; Vector2 distanceSum = Vector2.Zero; Vector2 velocitySum = Vector2.Zero; Vector2 upSum = Vector2.Zero; Vector2 cameraDistance = Vector2.Zero; // Iterate through each camera, calculating their influences on the sound instance depending on their distances from the source. // The closest camera will have the most influence. foreach (GenCamera camera in cameras) { if (camera == workingCamera) { cameraFactorSum += 1f; distanceSum += distanceMin; velocitySum += workingCamera.Velocity; upSum += workingCamera.Up; } else { cameraDistance = source.CenterPosition - camera.CenterPosition; cameraFactor = 1f - (cameraDistance.Length() * GenSound.InverseDistanceScale); if (cameraFactor > 0) { cameraFactorSum += cameraFactor; distanceSum += cameraDistance * cameraFactor; velocitySum += camera.Velocity * cameraFactor; upSum += camera.Up * cameraFactor; } } } // Inverse the camera factor sum to reduce division calculations. float inverseCameraFactorSum = 1f / cameraFactorSum; Vector2 averageDistance = distanceSum * inverseCameraFactorSum; float distanceFade = MathHelper.Clamp((GenSound.DistanceScale - distanceMin.Length()) * GenSound.InverseDistanceScale, 0f, 1f); SoundInstance.Volume = ((_soundParent == null) ? _volume : _soundParent.Volume) * distanceFade; SoundInstance.Pan = MathHelper.Clamp(averageDistance.X * GenSound.InverseDistanceScale, -1f, 1f) * -(upSum * inverseCameraFactorSum).Y; SoundInstance.Pitch = GenSound.GetDopplerShift(Follow.Velocity, (velocitySum * inverseCameraFactorSum), averageDistance, GenSound.DopplerFactor); } } }
/// <summary> /// Applies collision detection and response against two objects that may overlap. /// </summary> /// <param name="objectA">The first object to check for a collision.</param> /// <param name="objectB">The second object to check for a collision.</param> /// <param name="callback">The delegate method that will be invoked if a collision occurs.</param> /// <param name="collidableEdges">A bit field of flags determining which edges of the second object are collidable.</param> /// <returns>True if a collision occurs, false if not.</returns> public static bool Collide(GenObject objectA, GenObject objectB, CollideEvent callback, GenObject.Direction collidableEdges = GenObject.Direction.Any) { // Do not check for collisions if the objects are the same. if (objectA == objectB) return false; // Do not check for collisions if either object is not solid, or if both objects are immovable. if ((!objectA.Solid || !objectB.Solid) || (objectA.Immovable && objectB.Immovable)) return false; // If the movement bounding boxes of each object are overlapping, check for a collision. if (Overlap(objectA, objectB, callback)) { // Get the normal direction of the collision from bounding box A to B along the least penetrating axis. // Return no collision if the surface normal is projected towards a non-collidable edge of bounding box B. _distance = objectA.Bounds.GetDistanceAABB(objectB.Bounds); // The greatest absolute distance value between the two bounding boxes is along the axis of least penetration. if (_distance.X > _distance.Y) { if (objectA.Bounds.MidpointX > objectB.Bounds.MidpointX) { // The collision normal is pointing from the left edge of bounding box A. _collisionNormal.X = -1f; _collisionNormal.Y = 0f; if ((collidableEdges & GenObject.Direction.Right) == 0) return false; } else { // The collision normal is pointing from the right edge of bounding box A. _collisionNormal.X = 1f; _collisionNormal.Y = 0f; if ((collidableEdges & GenObject.Direction.Left) == 0) return false; } } else { if (objectA.Bounds.MidpointY > objectB.Bounds.MidpointY) { // The collision normal is pointing from the top edge of bounding box A. _collisionNormal.X = 0f; _collisionNormal.Y = -1f; if ((collidableEdges & GenObject.Direction.Down) == 0) return false; } else { // The collision normal is pointing from the bottom edge of bounding box A. _collisionNormal.X = 0f; _collisionNormal.Y = 1f; if ((collidableEdges & GenObject.Direction.Up) == 0) return false; } } float distance = Math.Max(_distance.X, _distance.Y); float remove; // Apply an alternative collision response against tiles for pixel-perfect accuracy. if (objectB is GenTile) { // Get the amount of normal velocity to remove from the object so that it just touches along the collision surface of the tile. remove = Vector2.Dot(-objectA.Velocity, _collisionNormal) + Math.Max(distance, 0f) * GenG.InverseTimeStep; // If the amount of velocity to remove is positive, the object will separate itself from the tile. if (remove >= 0) return false; if (_collisionNormal.X != 0) { objectA.X = (_collisionNormal.X == 1) ? objectB.X - objectA.Bounds.Width : objectB.Bounds.Right; objectA.Velocity.X = 0f; } else { objectA.Y = (_collisionNormal.Y == 1) ? objectB.Y - objectA.Bounds.Height : objectB.Bounds.Bottom; objectA.Velocity.Y = 0f; } } else { // Get the relative velocity along the collision normal. float relativeNormalVelocity = Vector2.Dot(objectB.Velocity - objectA.Velocity, _collisionNormal); // Get the amount of relative normal velocity to remove so that the bounding boxes are just touching along the collision surface. remove = relativeNormalVelocity + distance * GenG.InverseTimeStep; // If the amount of velocity to remove is positive, the objects will separate themselves. if (remove >= 0) return false; float impulse = remove / (objectA.InverseMass + objectB.InverseMass); if (!objectA.Immovable) objectA.Velocity += impulse * _collisionNormal * objectA.InverseMass; if (!objectB.Immovable) objectB.Velocity -= impulse * _collisionNormal * objectB.InverseMass; } // Use a bit field of flags to provide the direction that each object is colliding in during the current collision. GenObject.Direction touchingA = GenObject.Direction.None; GenObject.Direction touchingB = GenObject.Direction.None; if (_collisionNormal.X != 0) { if (_collisionNormal.X == 1) { objectA.Touching |= GenObject.Direction.Right; objectB.Touching |= GenObject.Direction.Left; touchingA |= GenObject.Direction.Right; touchingB |= GenObject.Direction.Left; } else { objectA.Touching |= GenObject.Direction.Left; objectB.Touching |= GenObject.Direction.Right; touchingA |= GenObject.Direction.Left; touchingB |= GenObject.Direction.Right; } } else { if (_collisionNormal.Y == 1) { objectA.Touching |= GenObject.Direction.Down; objectB.Touching |= GenObject.Direction.Up; touchingA |= GenObject.Direction.Down; touchingB |= GenObject.Direction.Up; if (objectB.IsPlatform) { if (objectA.Acceleration.X == 0) objectA.Platform = objectB; } } else { objectA.Touching |= GenObject.Direction.Up; objectB.Touching |= GenObject.Direction.Down; touchingA |= GenObject.Direction.Up; touchingB |= GenObject.Direction.Down; if (objectA.IsPlatform) { if (objectB.Acceleration.X == 0) objectB.Platform = objectA; } } } if (callback != null) { _collideEventArgs.ObjectA = objectA; _collideEventArgs.ObjectB = objectB; _collideEventArgs.TouchingA = touchingA; _collideEventArgs.TouchingB = touchingB; callback(_collideEventArgs); } return true; } return false; }