1#include "Library/Area/AreaObjDirector.h"
2
3#include "Library/Area/AreaInitInfo.h"
4#include "Library/Area/AreaObj.h"
5#include "Library/Area/AreaObjFactory.h"
6#include "Library/Area/AreaObjGroup.h"
7#include "Library/Area/AreaObjMtxConnecter.h"
8#include "Library/Placement/PlacementFunction.h"
9#include "Library/Placement/PlacementInfo.h"
10
11namespace al {
12
13AreaObjDirector::AreaObjDirector() = default;
14
15void AreaObjDirector::init(const AreaObjFactory* factory) {
16 mFactory = factory;
17 mMtxConnecterHolder = new AreaObjMtxConnecterHolder(0x100);
18 s32 nFactoryEntries = mFactory->getNumFactoryEntries();
19 mAreaGroups = new AreaObjGroup*[nFactoryEntries];
20
21 for (s32 i = 0; i < nFactoryEntries; i++)
22 mAreaGroups[i] = nullptr;
23}
24
25void AreaObjDirector::endInit() {}
26
27void AreaObjDirector::update() {
28 if (mMtxConnecterHolder)
29 mMtxConnecterHolder->update();
30}
31
32void AreaObjDirector::placement(const AreaInitInfo& initInfo) {
33 createAreaObjGroup(initInfo);
34 createAreaObjGroupBuffer();
35 placementAreaObj(initInfo);
36}
37
38void AreaObjDirector::placement(const AreaInitInfo* initInfoArray, s32 initInfoCount) {
39 for (s32 i = 0; i < initInfoCount; i++)
40 createAreaObjGroup(initInfo: initInfoArray[i]);
41
42 createAreaObjGroupBuffer();
43
44 for (s32 i = 0; i < initInfoCount; i++)
45 placementAreaObj(initInfo: initInfoArray[i]);
46}
47
48void AreaObjDirector::createAreaObjGroup(const AreaInitInfo& initInfo) {
49 PlacementInfo placementInfo(initInfo);
50
51 s32 pInfoCount = getCountPlacementInfo(placementInfo);
52 for (s32 i = 0; i < pInfoCount; i++) {
53 PlacementInfo placementInfo2;
54 tryGetPlacementInfoByIndex(outPlacementInfo: &placementInfo2, placementInfo, index: i);
55 const char* pInfoName = nullptr;
56 tryGetObjectName(name: &pInfoName, placementInfo: placementInfo2);
57
58 AreaCreatorFunction creatorFunc = nullptr;
59 s32 entryIndex = mFactory->getEntryIndex(creationPtr: &creatorFunc, entryName: pInfoName);
60
61 if (!creatorFunc)
62 continue;
63 if (!mAreaGroups[entryIndex]) {
64 s32 size = mFactory->tryFindAddBufferSize(bufferName: pInfoName);
65 mAreaGroups[entryIndex] = new AreaObjGroup(pInfoName, size);
66 }
67
68 mAreaGroups[entryIndex]->incrementCount();
69 }
70}
71
72void AreaObjDirector::createAreaObjGroupBuffer() {
73 for (s32 i = 0; i < mFactory->getAreaGroupCount(); i++) {
74 const AreaGroupInfo& addBuffer = mFactory->getAreaGroupInfo()[i];
75 AreaCreatorFunction creatorFunc = nullptr;
76 s32 entryIndex = mFactory->getEntryIndex(creationPtr: &creatorFunc, entryName: addBuffer.name);
77 if (!mAreaGroups[entryIndex])
78 mAreaGroups[entryIndex] = new AreaObjGroup(addBuffer.name, addBuffer.size);
79 }
80
81 s32 areaGroupCount = 0;
82 s32 nEntries = mFactory->getNumFactoryEntries();
83 for (s32 i = 0; i < nEntries; i++) {
84 if (mAreaGroups[i] == nullptr)
85 continue;
86 mAreaGroups[i]->createBuffer();
87 areaGroupCount++;
88
89 for (s32 areaGroupIndex = i; areaGroupIndex > 0; areaGroupIndex--) {
90 AreaObjGroup* prevAreaObjGroup = mAreaGroups[areaGroupIndex - 1];
91 if (prevAreaObjGroup) {
92 if (strcmp(mAreaGroups[areaGroupIndex]->getName(), prevAreaObjGroup->getName()) >
93 -1)
94 break;
95 }
96 mAreaGroups[areaGroupIndex - 1] = mAreaGroups[areaGroupIndex];
97 mAreaGroups[areaGroupIndex] = prevAreaObjGroup;
98 }
99 }
100 mAreaGroupCount = areaGroupCount;
101}
102
103void AreaObjDirector::placementAreaObj(const AreaInitInfo& initInfo) {
104 PlacementInfo pInfo(initInfo);
105 s32 pInfoCount = getCountPlacementInfo(placementInfo: pInfo);
106 for (s32 j = 0; j < pInfoCount; j++) {
107 PlacementInfo pInfo2;
108 tryGetPlacementInfoByIndex(outPlacementInfo: &pInfo2, placementInfo: pInfo, index: j);
109 const char* pInfoName = nullptr;
110 tryGetObjectName(name: &pInfoName, placementInfo: pInfo2);
111
112 AreaCreatorFunction creatorFunc = nullptr;
113 mFactory->getEntryIndex(creationPtr: &creatorFunc, entryName: pInfoName);
114 if (creatorFunc == nullptr)
115 continue;
116
117 const char* displayName;
118 getDisplayName(name: &displayName, placementInfo: pInfo2);
119 AreaObj* areaObj = creatorFunc(displayName);
120 AreaInitInfo initInfo2(pInfo2, initInfo);
121 areaObj->init(info: initInfo2);
122
123 AreaObjGroup* areaGroup = getAreaObjGroup(name: pInfoName);
124
125 areaGroup->registerAreaObj(newAreaObj: areaObj);
126 mMtxConnecterHolder->tryAddArea(areaObj, placementInfo: pInfo2);
127 }
128}
129
130AreaObjGroup* AreaObjDirector::getAreaObjGroup(const char* name) const {
131 s32 lower = 0;
132 s32 upper = mAreaGroupCount;
133 while (lower < upper) {
134 s32 i = (lower + upper) / 2;
135 s32 equalString = strcmp(name, mAreaGroups[i]->getName());
136 if (equalString == 0)
137 return mAreaGroups[i];
138 else if (equalString > 0)
139 lower = i + 1;
140 else
141 upper = i;
142 }
143 return nullptr;
144}
145
146bool AreaObjDirector::isExistAreaGroup(const char* name) const {
147 return getAreaObjGroup(name) != nullptr;
148}
149
150AreaObj* AreaObjDirector::getInVolumeAreaObj(const char* name, const sead::Vector3f& position) {
151 AreaObjGroup* areaGroup = getAreaObjGroup(name);
152 if (!areaGroup)
153 return nullptr;
154 return areaGroup->getInVolumeAreaObj(position);
155}
156
157AreaObjMtxConnecterHolder* AreaObjDirector::getMtxConnecterHolder() const {
158 return mMtxConnecterHolder;
159}
160
161} // namespace al
162