1#pragma once
2
3#include "container/seadOffsetList.h"
4#include "container/seadPtrArray.h"
5#include "controller/seadController.h"
6#include "framework/seadCalculateTask.h"
7#include "framework/seadTaskMgr.h"
8#include "framework/seadTaskParameter.h"
9#include "heap/seadDisposer.h"
10#include "prim/seadRuntimeTypeInfo.h"
11
12namespace sead
13{
14class ControlDevice;
15class Controller;
16class ControllerAddon;
17
18class ControllerMgr : public CalculateTask
19{
20 SEAD_TASK_SINGLETON(ControllerMgr)
21 SEAD_RTTI_OVERRIDE(ControllerMgr, CalculateTask)
22
23private:
24 class ConstructArg : public TaskConstructArg
25 {
26 public:
27 ConstructArg() : TaskConstructArg(), mHeapArray() { heap_array = &mHeapArray; }
28
29 private:
30 HeapArray mHeapArray;
31 };
32
33public:
34 struct Parameter : public TaskParameter
35 {
36 SEAD_RTTI_OVERRIDE(Parameter, TaskParameter)
37
38 public:
39 s32 controllerMax;
40 IDelegate1<ControllerMgr*>* proc;
41 };
42
43public:
44 ControllerMgr();
45 explicit ControllerMgr(const TaskConstructArg& arg);
46 ~ControllerMgr() override;
47
48 void prepare() override;
49 void calc() override;
50
51 void initialize(s32 controller_max, Heap* heap);
52 void finalize();
53
54 void initializeDefault(Heap* heap);
55 void finalizeDefault();
56
57 // TODO: Add/remove devices & controllers
58
59 Controller* getControllerByOrder(ControllerDefine::ControllerId id, s32 index) const;
60 ControlDevice* getControlDevice(ControllerDefine::DeviceId id) const;
61 ControllerAddon* getControllerAddon(s32 index, ControllerDefine::AddonId id) const;
62 ControllerAddon* getControllerAddonByOrder(s32 controller_index,
63 ControllerDefine::AddonId addon_id,
64 int addon_index) const;
65
66 template <typename T>
67 T getControllerByOrderAs(s32 index) const;
68 template <typename T>
69 T getControlDeviceAs() const;
70 template <typename T>
71 T getControllerAddonAs(s32 index) const;
72
73 s32 findControllerPort(const Controller* controller) const;
74
75 DelegateThread* getFramework() const;
76
77 Controller* getController(int port) { return mControllers[port]; }
78
79private:
80 OffsetList<ControlDevice> mDevices;
81 PtrArray<Controller> mControllers;
82};
83#ifdef cafe
84static_assert(sizeof(ControllerMgr) == 0xE8, "sead::ControllerMgr size mismatch");
85#endif // cafe
86
87template <typename T>
88T ControllerMgr::getControllerByOrderAs(s32 index) const
89{
90 for (PtrArray<Controller>::iterator it = mControllers.begin(); it != mControllers.end(); ++it)
91 {
92 T controller = DynamicCast<typename std::remove_pointer<T>::type>(&(*it));
93 if (controller)
94 {
95 if (index == 0)
96 return controller;
97
98 index--;
99 }
100 }
101
102 return nullptr;
103}
104
105template <typename T>
106T ControllerMgr::getControlDeviceAs() const
107{
108 for (OffsetList<ControlDevice>::iterator it = mDevices.begin(); it != mDevices.end(); ++it)
109 {
110 T device = DynamicCast<typename std::remove_pointer<T>::type>(&(*it));
111 if (device)
112 return device;
113 }
114
115 return nullptr;
116}
117
118template <typename T>
119T ControllerMgr::getControllerAddonAs(s32 index) const
120{
121 Controller* controller = mControllers.at(pos: index);
122 if (controller)
123 return controller->getAddonAs<T>();
124
125 return nullptr;
126}
127
128} // namespace sead
129