1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2009-2016, The OpenClonk Team and contributors 6 * 7 * Distributed under the terms of the ISC license; see accompanying file 8 * "COPYING" for details. 9 * 10 * "Clonk" is a registered trademark of Matthes Bender, used with permission. 11 * See accompanying file "TRADEMARK" for details. 12 * 13 * To redistribute this file separately, substitute the full license texts 14 * for the above references. 15 */ 16 #ifndef C4FINDOBJECT_H 17 #define C4FINDOBJECT_H 18 19 #include "lib/C4Rect.h" 20 #include "script/C4Value.h" 21 22 // Condition map 23 enum C4FindObjectCondID 24 { 25 C4FO_Not = 1, 26 C4FO_And = 2, 27 C4FO_Or = 3, 28 C4FO_Exclude = 4, 29 C4FO_InRect = 5, 30 C4FO_AtPoint = 6, 31 C4FO_AtRect = 7, 32 C4FO_OnLine = 8, 33 C4FO_Distance = 9, 34 C4FO_ID = 10, 35 C4FO_OCF = 11, 36 C4FO_Category = 12, 37 C4FO_Action = 13, 38 C4FO_ActionTarget = 14, 39 C4FO_Procedure = 15, 40 C4FO_Container = 16, 41 C4FO_AnyContainer = 17, 42 C4FO_Owner = 18, 43 C4FO_Controller = 19, 44 C4FO_Func = 20, 45 C4FO_Layer = 21, 46 C4FO_InArray = 22, 47 C4FO_Property = 23, 48 C4FO_AnyLayer = 24, 49 C4FO_Cone = 25, 50 // last C4FO must be smaller than C4SO_First. 51 }; 52 53 // Sort map - using same values as C4FindObjectCondID! 54 enum C4SortObjectCondID 55 { 56 C4SO_First = 30, // no sort condition smaller than this 57 C4SO_Reverse = 31, // reverse sort order 58 C4SO_Multiple = 32, // multiple sorts; high priority first; lower priorities if higher prio returned equal 59 C4SO_Distance = 33, // nearest first 60 C4SO_Random = 34, // random first 61 C4SO_Speed = 35, // slowest first 62 C4SO_Mass = 36, // lightest first 63 C4SO_Value = 37, // cheapest first 64 C4SO_Func = 38, // least return values first 65 C4SO_Last = 50 // no sort condition larger than this 66 }; 67 68 // Base class 69 class C4FindObject 70 { 71 friend class C4FindObjectNot; 72 friend class C4FindObjectAnd; 73 friend class C4FindObjectOr; 74 75 class C4SortObject *pSort{nullptr}; 76 public: 77 C4FindObject() = default; 78 virtual ~C4FindObject(); 79 80 static C4FindObject *CreateByValue(const C4Value &Data, C4SortObject **ppSortObj=nullptr, const C4Object *context=nullptr, bool *has_layer_check=nullptr); // createFindObject or SortObject - if ppSortObj==nullptr, SortObject is not allowed 81 82 int32_t Count(const C4ObjectList &Objs); // Counts objects for which the condition is true 83 C4Object *Find(const C4ObjectList &Objs); // Returns first object for which the condition is true 84 C4ValueArray *FindMany(const C4ObjectList &Objs); // Returns all objects for which the condition is true 85 86 int32_t Count(const C4ObjectList &Objs, const C4LSectors &Sct); // Counts objects for which the condition is true 87 C4Object *Find(const C4ObjectList &Objs, const C4LSectors &Sct); // Returns first object for which the condition is true 88 C4ValueArray *FindMany(const C4ObjectList &Objs, const C4LSectors &Sct); // Returns all objects for which the condition is true 89 90 void SetSort(C4SortObject *pToSort); 91 92 protected: 93 // Overridables 94 virtual bool Check(C4Object *pObj) = 0; GetBounds()95 virtual C4Rect *GetBounds() { return nullptr; } UseShapes()96 virtual bool UseShapes() { return false; } IsImpossible()97 virtual bool IsImpossible() { return false; } IsEnsured()98 virtual bool IsEnsured() { return false; } 99 100 private: 101 void CheckObjectStatus(C4ValueArray *pArray); 102 }; 103 104 // Combinators 105 class C4FindObjectNot : public C4FindObject 106 { 107 public: C4FindObjectNot(C4FindObject * pCond)108 C4FindObjectNot(C4FindObject *pCond) 109 : pCond(pCond) { } 110 ~C4FindObjectNot() override; 111 private: 112 C4FindObject *pCond; 113 protected: 114 bool Check(C4Object *pObj) override; IsImpossible()115 bool IsImpossible() override { return pCond->IsEnsured(); } IsEnsured()116 bool IsEnsured() override { return pCond->IsImpossible(); } 117 }; 118 119 class C4FindObjectAnd : public C4FindObject 120 { 121 public: 122 C4FindObjectAnd(int32_t iCnt, C4FindObject **ppConds, bool fFreeArray = true); 123 ~C4FindObjectAnd() override; 124 private: 125 int32_t iCnt; 126 C4FindObject **ppConds; bool fFreeArray; bool fUseShapes; 127 C4Rect Bounds; bool fHasBounds; 128 protected: 129 bool Check(C4Object *pObj) override; GetBounds()130 C4Rect *GetBounds() override { return fHasBounds ? &Bounds : nullptr; } UseShapes()131 bool UseShapes() override { return fUseShapes; } IsEnsured()132 bool IsEnsured() override { return !iCnt; } 133 bool IsImpossible() override; ForgetConditions()134 void ForgetConditions() { ppConds=nullptr; iCnt=0; } 135 }; 136 137 // Special variant of C4FindObjectAnd that does not free its conditions 138 class C4FindObjectAndStatic : public C4FindObjectAnd 139 { 140 public: C4FindObjectAndStatic(int32_t iCnt,C4FindObject ** ppConds)141 C4FindObjectAndStatic(int32_t iCnt, C4FindObject **ppConds) 142 : C4FindObjectAnd(iCnt, ppConds, true) {} ~C4FindObjectAndStatic()143 ~C4FindObjectAndStatic() override {ForgetConditions(); } 144 }; 145 146 class C4FindObjectOr : public C4FindObject 147 { 148 public: 149 C4FindObjectOr(int32_t iCnt, C4FindObject **ppConds); 150 ~C4FindObjectOr() override; 151 private: 152 int32_t iCnt; 153 C4FindObject **ppConds; bool fUseShapes; 154 C4Rect Bounds; bool fHasBounds; 155 protected: 156 bool Check(C4Object *pObj) override; GetBounds()157 C4Rect *GetBounds() override { return fHasBounds ? &Bounds : nullptr; } UseShapes()158 bool UseShapes() override { return fUseShapes; } 159 bool IsEnsured() override; IsImpossible()160 bool IsImpossible() override { return !iCnt; } 161 }; 162 163 // Primitive conditions 164 class C4FindObjectExclude : public C4FindObject 165 { 166 public: C4FindObjectExclude(C4Object * pExclude)167 C4FindObjectExclude(C4Object *pExclude) 168 : pExclude(pExclude) { } 169 private: 170 C4Object *pExclude; 171 protected: 172 bool Check(C4Object *pObj) override; 173 }; 174 175 class C4FindObjectDef : public C4FindObject 176 { 177 public: C4FindObjectDef(C4PropList * def)178 C4FindObjectDef(C4PropList * def) 179 : def(def) { } 180 private: 181 C4PropList * def; 182 protected: 183 bool Check(C4Object *pObj) override; 184 bool IsImpossible() override; 185 }; 186 187 class C4FindObjectInRect : public C4FindObject 188 { 189 public: C4FindObjectInRect(const C4Rect & rect)190 C4FindObjectInRect(const C4Rect &rect) 191 : rect(rect) { } 192 private: 193 C4Rect rect; 194 protected: 195 bool Check(C4Object *pObj) override; GetBounds()196 C4Rect *GetBounds() override { return ▭ } 197 bool IsImpossible() override; 198 }; 199 200 class C4FindObjectAtPoint : public C4FindObject 201 { 202 public: C4FindObjectAtPoint(int32_t x,int32_t y)203 C4FindObjectAtPoint(int32_t x, int32_t y) 204 : bounds(x, y, 1, 1) { } 205 private: 206 C4Rect bounds; 207 protected: 208 bool Check(C4Object *pObj) override; GetBounds()209 C4Rect *GetBounds() override { return &bounds; } UseShapes()210 bool UseShapes() override { return true; } 211 }; 212 213 class C4FindObjectAtRect : public C4FindObject 214 { 215 public: C4FindObjectAtRect(int32_t x,int32_t y,int32_t wdt,int32_t hgt)216 C4FindObjectAtRect(int32_t x, int32_t y, int32_t wdt, int32_t hgt) 217 : bounds(x, y, wdt, hgt) { } 218 private: 219 C4Rect bounds; 220 protected: 221 bool Check(C4Object *pObj) override; GetBounds()222 C4Rect *GetBounds() override { return &bounds; } UseShapes()223 bool UseShapes() override { return true; } 224 }; 225 226 class C4FindObjectOnLine : public C4FindObject 227 { 228 public: C4FindObjectOnLine(int32_t x,int32_t y,int32_t x2,int32_t y2)229 C4FindObjectOnLine(int32_t x, int32_t y, int32_t x2, int32_t y2) 230 : x(x), y(y), x2(x2), y2(y2), bounds(x, y, 1, 1) { bounds.Add(C4Rect(x2, y2, 1,1)); } 231 private: 232 int32_t x, y, x2, y2; 233 C4Rect bounds; 234 protected: 235 bool Check(C4Object *pObj) override; GetBounds()236 C4Rect *GetBounds() override { return &bounds; } UseShapes()237 bool UseShapes() override { return true; } 238 }; 239 240 class C4FindObjectDistance : public C4FindObject 241 { 242 public: C4FindObjectDistance(int32_t x,int32_t y,int32_t r)243 C4FindObjectDistance(int32_t x, int32_t y, int32_t r) 244 : x(x), y(y), r2(r*r), bounds(x-r, y-r, 2*r+1, 2*r+1) { } 245 private: 246 int32_t x, y, r2; 247 C4Rect bounds; 248 protected: 249 bool Check(C4Object *pObj) override; GetBounds()250 C4Rect *GetBounds() override { return &bounds; } 251 }; 252 253 class C4FindObjectCone : public C4FindObject 254 { 255 public: 256 C4FindObjectCone(int32_t x, int32_t y, int32_t r, int32_t angle, int32_t width, int32_t prec = 1) x(x)257 : x(x), y(y), r2(r * r), cone_angle(angle % (360 * prec)), cone_width(width), prec_angle(prec), bounds(x - r, y - r, 2 * r + 1, 2 * r + 1) { } 258 private: 259 int32_t x, y, r2, cone_angle, cone_width, prec_angle; 260 C4Rect bounds; 261 protected: 262 bool Check(C4Object *pObj) override; GetBounds()263 C4Rect *GetBounds() override { return &bounds; } 264 }; 265 266 class C4FindObjectOCF : public C4FindObject 267 { 268 public: C4FindObjectOCF(int32_t ocf)269 C4FindObjectOCF(int32_t ocf) 270 : ocf(ocf) { } 271 private: 272 int32_t ocf; 273 protected: 274 bool Check(C4Object *pObj) override; 275 bool IsImpossible() override; 276 }; 277 278 class C4FindObjectCategory : public C4FindObject 279 { 280 public: C4FindObjectCategory(int32_t iCategory)281 C4FindObjectCategory(int32_t iCategory) 282 : iCategory(iCategory) { } 283 private: 284 int32_t iCategory; 285 protected: 286 bool Check(C4Object *pObj) override; 287 bool IsEnsured() override; 288 }; 289 290 class C4FindObjectAction : public C4FindObject 291 { 292 public: C4FindObjectAction(const char * szAction)293 C4FindObjectAction(const char *szAction) 294 : szAction(szAction) { } 295 private: 296 const char *szAction; 297 protected: 298 bool Check(C4Object *pObj) override; 299 }; 300 301 class C4FindObjectActionTarget : public C4FindObject 302 { 303 public: C4FindObjectActionTarget(C4Object * pActionTarget,int index)304 C4FindObjectActionTarget(C4Object *pActionTarget, int index) 305 : pActionTarget(pActionTarget), index(index) { } 306 private: 307 C4Object *pActionTarget; 308 int index; 309 protected: 310 bool Check(C4Object *pObj) override; 311 }; 312 313 class C4FindObjectProcedure : public C4FindObject 314 { 315 public: C4FindObjectProcedure(C4String * procedure)316 C4FindObjectProcedure(C4String * procedure) 317 : procedure(procedure) { /* no need to incref, the pointer is never dereferenced */ } 318 private: 319 C4String * procedure; 320 protected: 321 bool Check(C4Object *pObj) override; 322 bool IsImpossible() override; 323 }; 324 325 class C4FindObjectContainer : public C4FindObject 326 { 327 public: C4FindObjectContainer(C4Object * pContainer)328 C4FindObjectContainer(C4Object *pContainer) 329 : pContainer(pContainer) { } 330 private: 331 C4Object *pContainer; 332 protected: 333 bool Check(C4Object *pObj) override; 334 }; 335 336 class C4FindObjectAnyContainer : public C4FindObject 337 { 338 public: 339 C4FindObjectAnyContainer() = default; 340 protected: 341 bool Check(C4Object *pObj) override; 342 }; 343 344 class C4FindObjectOwner : public C4FindObject 345 { 346 public: C4FindObjectOwner(int32_t iOwner)347 C4FindObjectOwner(int32_t iOwner) 348 : iOwner(iOwner) { } 349 private: 350 int32_t iOwner; 351 protected: 352 bool Check(C4Object *pObj) override; 353 bool IsImpossible() override; 354 }; 355 356 class C4FindObjectController : public C4FindObject 357 { 358 public: C4FindObjectController(int32_t controller)359 C4FindObjectController(int32_t controller) 360 : controller(controller) { } 361 private: 362 int32_t controller; 363 protected: 364 bool Check(C4Object *pObj) override; 365 bool IsImpossible() override; 366 }; 367 368 class C4FindObjectFunc : public C4FindObject 369 { 370 public: C4FindObjectFunc(C4String * Name)371 C4FindObjectFunc(C4String * Name): Name(Name) { } 372 void SetPar(int i, const C4Value &val); 373 private: 374 C4String * Name; 375 C4AulParSet Pars; 376 protected: 377 bool Check(C4Object *pObj) override; 378 bool IsImpossible() override; 379 }; 380 381 class C4FindObjectProperty : public C4FindObject 382 { 383 public: C4FindObjectProperty(C4String * Name)384 C4FindObjectProperty(C4String * Name) : Name(Name) { } 385 private: 386 C4String * Name; 387 protected: 388 bool Check(C4Object *pObj) override; 389 bool IsImpossible() override; 390 }; 391 392 class C4FindObjectLayer : public C4FindObject 393 { 394 public: C4FindObjectLayer(C4Object * pLayer)395 C4FindObjectLayer(C4Object *pLayer) : pLayer(pLayer) {} 396 private: 397 C4Object *pLayer; 398 protected: 399 bool Check(C4Object *pObj) override; 400 bool IsImpossible() override; 401 }; 402 403 class C4FindObjectInArray : public C4FindObject 404 { 405 public: C4FindObjectInArray(C4ValueArray * pArray)406 C4FindObjectInArray(C4ValueArray *pArray) : pArray(pArray) {} 407 private: 408 C4ValueArray *pArray; 409 protected: 410 bool Check(C4Object *pObj) override; 411 bool IsImpossible() override; 412 }; 413 414 // result sorting 415 class C4SortObject 416 { 417 public: 418 C4SortObject() = default; 419 virtual ~C4SortObject() = default; 420 421 public: 422 // Overridables 423 virtual int32_t Compare(C4Object *pObj1, C4Object *pObj2) = 0; // return value <0 if obj1 is to be sorted before obj2 424 PrepareCache(const C4ValueArray * pObjs)425 virtual bool PrepareCache(const C4ValueArray *pObjs) { return false; } CompareCache(int32_t iObj1,int32_t iObj2,C4Object * pObj1,C4Object * pObj2)426 virtual int32_t CompareCache(int32_t iObj1, int32_t iObj2, C4Object *pObj1, C4Object *pObj2) { return Compare(pObj1, pObj2); } 427 428 public: 429 static C4SortObject *CreateByValue(const C4Value &Data, const C4Object *context=nullptr); 430 static C4SortObject *CreateByValue(int32_t iType, const C4ValueArray &Data, const C4Object *context=nullptr); 431 432 void SortObjects(C4ValueArray *pArray); 433 }; 434 435 class C4SortObjectByValue : public C4SortObject 436 { 437 public: 438 C4SortObjectByValue(); 439 ~C4SortObjectByValue() override; 440 441 private: 442 int32_t *pVals{nullptr}; 443 int32_t iSize{0}; 444 445 public: 446 // Overridables 447 int32_t Compare(C4Object *pObj1, C4Object *pObj2) override; 448 virtual int32_t CompareGetValue(C4Object *pOf) = 0; 449 450 bool PrepareCache(const C4ValueArray *pObjs) override; 451 int32_t CompareCache(int32_t iObj1, int32_t iObj2, C4Object *pObj1, C4Object *pObj2) override; 452 453 }; 454 455 class C4SortObjectReverse : public C4SortObject // reverse sort 456 { 457 public: C4SortObjectReverse(C4SortObject * pSort)458 C4SortObjectReverse(C4SortObject *pSort) 459 : C4SortObject(), pSort(pSort) {} 460 ~C4SortObjectReverse() override; 461 private: 462 C4SortObject *pSort; 463 464 protected: 465 int32_t Compare(C4Object *pObj1, C4Object *pObj2) override; 466 467 bool PrepareCache(const C4ValueArray *pObjs) override; 468 int32_t CompareCache(int32_t iObj1, int32_t iObj2, C4Object *pObj1, C4Object *pObj2) override; 469 }; 470 471 class C4SortObjectMultiple : public C4SortObject // apply next sort if previous compares to equality 472 { 473 public: 474 C4SortObjectMultiple(int32_t iCnt, C4SortObject **ppSorts, bool fFreeArray = true) C4SortObject()475 : C4SortObject(), fFreeArray(fFreeArray), iCnt(iCnt), ppSorts(ppSorts) {} 476 ~C4SortObjectMultiple() override; 477 private: 478 bool fFreeArray; 479 int32_t iCnt; 480 C4SortObject **ppSorts; 481 482 protected: 483 int32_t Compare(C4Object *pObj1, C4Object *pObj2) override; 484 485 bool PrepareCache(const C4ValueArray *pObjs) override; 486 int32_t CompareCache(int32_t iObj1, int32_t iObj2, C4Object *pObj1, C4Object *pObj2) override; 487 }; 488 489 class C4SortObjectDistance : public C4SortObjectByValue // sort by distance from point x/y 490 { 491 public: C4SortObjectDistance(int iX,int iY)492 C4SortObjectDistance(int iX, int iY) 493 : C4SortObjectByValue(), iX(iX), iY(iY) {} 494 private: 495 int iX, iY; 496 497 protected: 498 int32_t CompareGetValue(C4Object *pFor) override; 499 }; 500 501 class C4SortObjectRandom : public C4SortObjectByValue // randomize order 502 { 503 public: C4SortObjectRandom()504 C4SortObjectRandom() : C4SortObjectByValue() {} 505 506 protected: 507 int32_t CompareGetValue(C4Object *pFor) override; 508 }; 509 510 class C4SortObjectSpeed : public C4SortObjectByValue // sort by object xdir/ydir 511 { 512 public: C4SortObjectSpeed()513 C4SortObjectSpeed() : C4SortObjectByValue() {} 514 515 protected: 516 int32_t CompareGetValue(C4Object *pFor) override; 517 }; 518 519 class C4SortObjectMass : public C4SortObjectByValue // sort by mass 520 { 521 public: C4SortObjectMass()522 C4SortObjectMass() : C4SortObjectByValue() {} 523 524 protected: 525 int32_t CompareGetValue(C4Object *pFor) override; 526 }; 527 528 class C4SortObjectValue : public C4SortObjectByValue // sort by value 529 { 530 public: C4SortObjectValue()531 C4SortObjectValue() : C4SortObjectByValue() {} 532 533 protected: 534 int32_t CompareGetValue(C4Object *pFor) override; 535 }; 536 537 class C4SortObjectFunc : public C4SortObjectByValue // sort by script function 538 { 539 public: C4SortObjectFunc(C4String * Name)540 C4SortObjectFunc(C4String * Name): Name(Name) { } 541 void SetPar(int i, const C4Value &val); 542 private: 543 C4String * Name; 544 C4AulParSet Pars; 545 protected: 546 int32_t CompareGetValue(C4Object *pFor) override; 547 }; 548 549 #endif 550