| 1 | /* |
| 2 | * LegacyClonk |
| 3 | * |
| 4 | * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design) |
| 5 | * Copyright (c) 2017-2021, The LegacyClonk 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 | |
| 17 | /* Dynamic object list */ |
| 18 | |
| 19 | #pragma once |
| 20 | |
| 21 | #include <memory> |
| 22 | #include <vector> |
| 23 | |
| 24 | #include "C4Id.h" |
| 25 | #include "C4Def.h" |
| 26 | #include "C4ObjectInfo.h" |
| 27 | #include "C4Region.h" |
| 28 | |
| 29 | class C4Object; |
| 30 | class C4FacetEx; |
| 31 | |
| 32 | constexpr std::int32_t |
| 33 | C4EnumPointer1 = 1000000000, |
| 34 | C4EnumPointer2 = 1001000000; |
| 35 | |
| 36 | class C4ObjectLink |
| 37 | { |
| 38 | public: |
| 39 | C4Object *Obj; |
| 40 | C4ObjectLink *Prev, *Next; |
| 41 | }; |
| 42 | |
| 43 | class C4ObjectList |
| 44 | { |
| 45 | std::unique_ptr<std::vector<int32_t>> pEnumerated; |
| 46 | |
| 47 | public: |
| 48 | C4ObjectList(); |
| 49 | C4ObjectList(const C4ObjectList &List); |
| 50 | virtual ~C4ObjectList(); |
| 51 | |
| 52 | C4ObjectLink *First, *Last; |
| 53 | int Mass; |
| 54 | |
| 55 | enum SortType { stNone = 0, stMain, stContents, stReverse, }; |
| 56 | |
| 57 | // An iterator which survives if an object is removed from the list |
| 58 | class iterator |
| 59 | { |
| 60 | public: |
| 61 | ~iterator(); |
| 62 | iterator &operator++(); // prefix ++ |
| 63 | iterator(const iterator &iter); |
| 64 | C4Object *operator*(); |
| 65 | C4Object *operator->() { return operator*(); } |
| 66 | bool operator==(const iterator &iter) const; |
| 67 | bool operator==(std::default_sentinel_t) const noexcept; |
| 68 | |
| 69 | iterator &operator=(const iterator &iter); |
| 70 | |
| 71 | private: |
| 72 | explicit iterator(C4ObjectList &List, C4ObjectLink *C4ObjectLink::*const direction = &C4ObjectLink::Next); |
| 73 | iterator(C4ObjectList &List, C4ObjectLink *pLink, C4ObjectLink *C4ObjectLink::*const direction = &C4ObjectLink::Next); |
| 74 | C4ObjectList &List; |
| 75 | C4ObjectLink *pLink; |
| 76 | iterator *Next; |
| 77 | C4ObjectLink *C4ObjectLink::*direction; |
| 78 | |
| 79 | friend class C4ObjectList; |
| 80 | }; |
| 81 | iterator begin(); |
| 82 | const iterator end(); |
| 83 | |
| 84 | iterator BeginLast(); |
| 85 | std::default_sentinel_t EndLast(); |
| 86 | |
| 87 | void SortByCategory(); |
| 88 | void Default(); |
| 89 | void Clear(); |
| 90 | void Enumerate(); |
| 91 | void Denumerate(); |
| 92 | void Copy(const C4ObjectList &rList); |
| 93 | void DrawAll(C4FacetEx &cgo, int iPlayer = -1); // draw all objects, including bg |
| 94 | void DrawIfCategory(C4FacetEx &cgo, int iPlayer, uint32_t dwCat, bool fInvert); // draw all objects that match dwCat (or don't match if fInvert) |
| 95 | void Draw(C4FacetEx &cgo, int iPlayer = -1); // draw all objects |
| 96 | void DrawIDList(C4Facet &cgo, int iSelection, C4DefList &rDefs, int32_t dwCategory, C4RegionList *pRegions = nullptr, int iRegionCom = COM_None, bool fDrawOneCounts = true); |
| 97 | void DrawSelectMark(C4FacetEx &cgo); |
| 98 | void (); |
| 99 | void UpdateGraphics(bool fGraphicsChanged); |
| 100 | void UpdateFaces(bool bUpdateShape); |
| 101 | void SyncClearance(); |
| 102 | void ResetAudibility(); |
| 103 | void UpdateTransferZones(); |
| 104 | void SetOCF(); |
| 105 | void ClearInfo(C4ObjectInfo *pInfo); |
| 106 | |
| 107 | bool Add(C4Object *nObj, SortType eSort, C4ObjectList *pLstSorted = nullptr); |
| 108 | bool Remove(C4Object *pObj); |
| 109 | |
| 110 | bool AssignInfo(); |
| 111 | bool ValidateOwners(); |
| 112 | bool AssignPlrViewRange(); |
| 113 | std::string GetNameList(C4DefList &rDefs, uint32_t dwCategory = C4D_All); |
| 114 | bool IsClear() const; |
| 115 | bool DenumerateRead(); |
| 116 | void CompileFunc(StdCompiler *pComp, bool fSaveRefs = true, bool fSkipPlayerObjects = false); |
| 117 | |
| 118 | int32_t ObjectNumber(C4Object *pObj); |
| 119 | bool IsContained(C4Object *pObj); |
| 120 | int ClearPointers(C4Object *pObj); |
| 121 | int ObjectCount(C4ID id = C4ID_None, int32_t dwCategory = C4D_All) const; |
| 122 | int MassCount(); |
| 123 | int ListIDCount(int32_t dwCategory); |
| 124 | |
| 125 | virtual C4Object *ObjectPointer(int32_t iNumber); |
| 126 | C4Object *SafeObjectPointer(int32_t iNumber); |
| 127 | C4Object *GetObject(int Index = 0); |
| 128 | C4Object *Find(C4ID id, int iOwner = ANY_OWNER, uint32_t dwOCF = OCF_All); |
| 129 | C4Object *FindOther(C4ID id, int iOwner = ANY_OWNER); |
| 130 | |
| 131 | C4ObjectLink *GetLink(C4Object *pObj); |
| 132 | |
| 133 | C4ID GetListID(int32_t dwCategory, int Index); |
| 134 | |
| 135 | bool OrderObjectBefore(C4Object *pObj1, C4Object *pObj2); // order pObj1 before pObj2 |
| 136 | bool OrderObjectAfter(C4Object *pObj1, C4Object *pObj2); // order pObj1 after pObj2 |
| 137 | |
| 138 | bool ShiftContents(C4Object *pNewFirst); // cycle list so pNewFirst is at front |
| 139 | |
| 140 | void DeleteObjects(); // delete all objects and links |
| 141 | |
| 142 | void UpdateScriptPointers(); // update pointers to C4AulScript * |
| 143 | |
| 144 | bool CheckSort(C4ObjectList *pList); // check that all objects of this list appear in the other list in the same order |
| 145 | void CheckCategorySort(); // assertwhether sorting by category is done right |
| 146 | |
| 147 | protected: |
| 148 | virtual void InsertLinkBefore(C4ObjectLink *pLink, C4ObjectLink *pBefore); |
| 149 | virtual void InsertLink(C4ObjectLink *pLink, C4ObjectLink *pAfter); |
| 150 | virtual void RemoveLink(C4ObjectLink *pLnk); |
| 151 | iterator *FirstIter; |
| 152 | iterator *AddIter(iterator *iter); |
| 153 | void RemoveIter(iterator *iter); |
| 154 | |
| 155 | friend class iterator; |
| 156 | friend class C4ObjResort; |
| 157 | }; |
| 158 | |
| 159 | class C4ObjectListChangeListener |
| 160 | { |
| 161 | public: |
| 162 | virtual void OnObjectRemove(C4ObjectList *pList, C4ObjectLink *pLnk) = 0; |
| 163 | virtual void OnObjectAdded(C4ObjectList *pList, C4ObjectLink *pLnk) = 0; |
| 164 | virtual void OnObjectRename(C4ObjectList *pList, C4ObjectLink *pLnk) = 0; |
| 165 | virtual ~C4ObjectListChangeListener() {} |
| 166 | }; |
| 167 | |
| 168 | extern C4ObjectListChangeListener &ObjectListChangeListener; |
| 169 | |
| 170 | class C4NotifyingObjectList : public C4ObjectList |
| 171 | { |
| 172 | public: |
| 173 | C4NotifyingObjectList() {} |
| 174 | C4NotifyingObjectList(const C4NotifyingObjectList &List) : C4ObjectList(List) {} |
| 175 | C4NotifyingObjectList(const C4ObjectList &List) : C4ObjectList(List) {} |
| 176 | virtual ~C4NotifyingObjectList() {} |
| 177 | |
| 178 | protected: |
| 179 | virtual void InsertLinkBefore(C4ObjectLink *pLink, C4ObjectLink *pBefore) override; |
| 180 | virtual void InsertLink(C4ObjectLink *pLink, C4ObjectLink *pAfter) override; |
| 181 | virtual void RemoveLink(C4ObjectLink *pLnk) override; |
| 182 | |
| 183 | friend class C4ObjResort; |
| 184 | }; |
| 185 | |
| 186 | // This iterator is used to return objects of same ID and picture as grouped. |
| 187 | // It's taking advantage of the fact that object lists are sorted by ID. |
| 188 | // Used by functions such as C4ObjectList::DrawIDList, or the menu-filling of |
| 189 | // activation/selling menus |
| 190 | class C4ObjectListIterator |
| 191 | { |
| 192 | private: |
| 193 | C4ObjectList &rList; // iterated list |
| 194 | C4ObjectList::iterator pCurr; // link to last returned object |
| 195 | C4ObjectList::iterator pCurrID; // link to head of link group with same ID |
| 196 | |
| 197 | C4ObjectListIterator(const C4ObjectListIterator &rCopy); // no copy ctor |
| 198 | |
| 199 | public: |
| 200 | C4ObjectListIterator(C4ObjectList &rList) : rList(rList), pCurr(rList.end()), pCurrID(rList.begin()) {} |
| 201 | C4Object *GetNext(int32_t *piCount, uint32_t dwCategory = 0); // get next object; return nullptr if end is reached |
| 202 | }; |
| 203 | |