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
29class C4Object;
30class C4FacetEx;
31
32constexpr std::int32_t
33 C4EnumPointer1 = 1000000000,
34 C4EnumPointer2 = 1001000000;
35
36class C4ObjectLink
37{
38public:
39 C4Object *Obj;
40 C4ObjectLink *Prev, *Next;
41};
42
43class C4ObjectList
44{
45 std::unique_ptr<std::vector<int32_t>> pEnumerated;
46
47public:
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 CloseMenus();
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
147protected:
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
159class C4ObjectListChangeListener
160{
161public:
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
168extern C4ObjectListChangeListener &ObjectListChangeListener;
169
170class C4NotifyingObjectList : public C4ObjectList
171{
172public:
173 C4NotifyingObjectList() {}
174 C4NotifyingObjectList(const C4NotifyingObjectList &List) : C4ObjectList(List) {}
175 C4NotifyingObjectList(const C4ObjectList &List) : C4ObjectList(List) {}
176 virtual ~C4NotifyingObjectList() {}
177
178protected:
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
190class C4ObjectListIterator
191{
192private:
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
199public:
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