From ff5f5c50bd2ce931a62b2eb1b0aed97c0fa370c5 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Sun, 18 Mar 2018 00:40:38 +0100 Subject: Update to newest version DTCallback: Add fast callbacks (only Object/DefinitionCallback() is possible) and restructure CallA() for hopefully better performance DTCallback: Fix all custom calls to allow overriding in Definition- and Object-context DTFilterObjects: new addition DTMenuCompatibility: add Menu_Entry compatibility version due to the new Menu_Entry-API DTObjectSerializing: small progress, still WIP DTPlayers: Fix constant enum definitions (thanks to the preprocessor's precalculator) DTQuickSort: Add custom callback args DTScopedVars: Fix all custom calls to allow overriding in Definition- and Object-context DTScopedVars: CustomScopedVar-implementations must now return another less custom ScopedVar instead of a reference (due to _inherited()) DTTransform: disable MirrorZ DTTransform: fix Matrix3x3Multiply and thus PreTransform DTTransform: fix whitespace DTTransform: update comments DTUTility: Fix indentation and whitespace DTUtility: Add GetShape, InRect and GetPlayerByID DTCallback, DTObjectSerializing: Rely on the preprocessor's precalculator --- DTFilterObjects.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 DTFilterObjects.c (limited to 'DTFilterObjects.c') diff --git a/DTFilterObjects.c b/DTFilterObjects.c new file mode 100644 index 0000000..77db745 --- /dev/null +++ b/DTFilterObjects.c @@ -0,0 +1,318 @@ +#strict 2 + +// see C4FindObject.h +static const C4SO_First = 100; +static const C4SO_Last = 200; + +global func CheckObjectFilter(array filter, object obj) +{ + obj = obj || this; + + if(filter[0] == C4FO_Action) + { + return obj->GetAction() == filter[1]; + } + else if(filter[0] == C4FO_ActionTarget) + { + return obj->GetActionTarget(filter[2]) == filter[1]; + } + else if(filter[0] == C4FO_And) + { + return CheckObject(filter, obj, 1); + } + else if(filter[0] == C4FO_AnyContainer) + { + return obj->Contained(); + } + else if(filter[0] == C4FO_AtPoint) + { + var x = filter[1], y = filter[2]; + var shape = GetShape(obj); + shape[0] += obj->GetX(); + shape[1] += obj->GetY(); + + return InRect([x, y], shape); + } + else if(filter[0] == C4FO_AtRect) + { + var shape = GetShape(obj); + shape[0] += obj->GetX(); + shape[1] += obj->GetY(); + + return shape[0] + shape[2] > filter[1] && shape[0] < filter[1] + filter[3] && shape[1] + shape[3] > filter[2] && shape[1] < filter[2] + filter[4]; + } + else if(filter[0] == C4FO_Category) + { + return obj->GetCategory() & filter[1]; + } + else if(filter[0] == C4FO_Container) + { + return obj->Contained() == filter[1]; + } + else if(filter[0] == C4FO_Controller) + { + return obj->GetController() == filter[1]; + } + else if(filter[0] == C4FO_Distance) + { + return ((obj->GetX() - filter[1])**2 + (obj->GetY() - filter[2])**2) <= filter[3]**2; + } + else if(filter[0] == C4FO_Exclude) + { + return obj != filter[1]; + } + else if(filter[0] == C4FO_Func) + { + var args = CreateArray(GetLength(filter) - 2); + for(var i = 2; i < GetLength(filter); ++i) + { + args[i - 2] = filter[i]; + } + + return obj->CallA(filter[1], args, true); + } + else if(filter[0] == C4FO_ID) + { + return obj->GetID() == filter[1]; + } + else if(filter[0] == C4FO_InRect) + { + return InRect([obj->GetX(), obj->GetY()], [filter[1], filter[2], filter[3], filter[4]]); + } + else if(filter[0] == C4FO_Layer) + { + return obj->GetObjectLayer() == filter[1]; + } + else if(filter[0] == C4FO_Not) + { + return !CheckObject([filter[1]], obj); + } + else if(filter[0] == C4FO_OCF) + { + return obj->GetOCF() & filter[1]; + } + else if(filter[0] == C4FO_OnLine) + { + var shape = GetShape(obj); + shape[0] += obj->GetX(); + shape[1] += obj->GetY(); + + var x = filter[1], y = filter[2]; + var x2 = filter[3], y2 = filter[4]; + + + // shape is at the beginning or end of the line + if(InRect([x, y], shape) || InRect([x2, y2], shape)) + { + return true; + } + + // shape is completely left or above the line + if((x < shape[0] && x2 < shape[0]) || (y < shape[1] && y2 < shape[1])) + { + return false; + } + + // shape is completely right or below the line + if((x >= shape[0] + shape[2] && x2 >= shape[0] + shape[2]) || (y >= shape[1] + shape[3] && y2 >= shape[1] + shape[3])) + { + return false; + } + + // the line is actually a point and is neither left/right nor above/below, so it must be on that point + if (x == x2 || y == y2) + { + return true; + } + + // Check intersection left/right + var xI; + if(x < shape[0]) + { + xI = shape[0]; + } + else + { + xI = shape[0] + shape[2]; + } + + var yI = y + (y2 - y) * (xI - x) / (x2 - x); + if(yI >= shape[1] && yI < shape[1] + shape[3]) + { + return true; + } + + // Check intersection up/down + if(y < shape[1]) + { + yI = shape[1]; + } + else + { + yI = shape[1] + shape[3]; + } + + xI = x + (x2 - x) * (yI - y) / (y2 - y); + return xI >= shape[0] && xI < shape[0] + shape[2]; + } + else if(filter[0] == C4FO_Or) + { + for(var i = 1; i < GetLength(filter); ++i) + { + var orFilter = filter[i]; + if(!orFilter) + { + continue; + } + if(CheckObjectFilter(orFilter, obj)) + { + return true; + } + } + return false; + } + else if(filter[0] == C4FO_Owner) + { + return obj->GetOwner() == filter[1]; + } + else + { + return true; + } +} + +global func CheckObject(array filters, object obj, int filtersOffset) +{ + obj = obj || this; + + for(var i = filtersOffset; i < GetLength(filters); ++i) + { + var filter = filters[i]; + if(!filter) + { + continue; + } + if(!CheckObjectFilter(filter, obj)) + { + return false; + } + } + return true; +} + +global func CompareObjects(object a, object b, array sorting) +{ + if(sorting[0] == C4SO_Reverse) + { + return CompareObjects(b, a, sorting[1]); + } + else if(sorting[0] == C4SO_Multiple) + { + return SortObjectsCallback(a, b, sorting, 1); + } + else if(sorting[0] == C4SO_Distance) + { + return ((a->GetX() - sorting[1])**2 + (a->GetY() - sorting[2])**2) - ((b->GetX() - sorting[1])**2 + (b->GetY() - sorting[2])**2); + } + else if(sorting[0] == C4SO_Random) + { + return Random65536 - Random(65536); + } + else if(sorting[0] == C4SO_Speed) + { + return (GetXDir(a, 65536)**2 + GetYDir(b, 65536)**2) - (GetXDir(b, 65536)**2 + GetYDir(b, 65536)**2); + } + else if(sorting[0] == C4SO_Mass) + { + return GetMass(a) - GetMass(b); + } + else if(sorting[0] == C4SO_Value) + { + return GetValue(a) - GetValue(b); + } + else if(sorting[0] == C4SO_Func) + { + var args = CreateArray(GetLength(sorting) - 2); + for(var i = 2; i < GetLength(sorting); ++i) + { + args[i - 2] = sorting[i]; + } + return a->CallA(sorting[1], args, true) - b->CallA(sorting[1], args, true); + } + + return 0; +} + +global func SortObjectsCallback(object a, object b, array sortings, int offset) +{ + for(var i = offset; i < GetLength(sortings); ++i) + { + var ret = CompareObjects(a, b, sortings[i]); + if(ret != 0) + { + return ret; + } + } + return 0; +} + +global func SortObjects(array& objects, array sortings) +{ + QSort(objects, GlobalCallback("SortObjectsCallback"), sortings); +} + +global func FilterObjects(array objects, array filtersSortings, int limit) +{ + var filters = [], sortings = []; + + for(var filterSorting in filtersSortings) + { + if(!filterSorting) + { + continue; + } + + if(Inside(filterSorting[0], C4SO_First, C4SO_Last)) + { + ArrayAppend(sortings, filterSorting); + } + else + { + ArrayAppend(filters, filterSorting); + } + } + + var realLimit = limit; + if(GetLength(sortings) > 0) + { + realLimit = 0; + } + + var ret = []; + for(var obj in objects) + { + if(!obj) + { + continue; + } + + if(CheckObject(filters, obj)) + { + ArrayAppend(ret, obj); + + if(realLimit && realLimit <= GetLength(ret)) + { + return ret; + } + } + } + + SortObjects(ret, sortings); + + if(GetLength(sortings) > 0 && limit) + { + SetLength(ret, limit); + } + + return ret; +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf