ksys/act: Add Queries

This commit is contained in:
Léo Lam
2020-12-21 16:41:28 +01:00
parent 64b93c984e
commit b1470e45fa
8 changed files with 245 additions and 35 deletions
@@ -35,6 +35,8 @@ target_sources(uking PRIVATE
actAiParam.h
actAiQuery.cpp
actAiQuery.h
actAiQueries.cpp
actAiQueries.h
actAiRoot.cpp
actAiRoot.h
actAttention.cpp
@@ -70,4 +72,6 @@ target_sources(uking PRIVATE
aiDummyAi.h
behaviorDummyBehavior.cpp
behaviorDummyBehavior.h
queryDummyQuery.cpp
queryDummyQuery.h
)
+143
View File
@@ -0,0 +1,143 @@
#include "KingSystem/ActorSystem/actAiQueries.h"
#include <codec/seadHashCRC32.h>
#include "KingSystem/ActorSystem/actActor.h"
#include "KingSystem/ActorSystem/actActorParam.h"
#include "KingSystem/ActorSystem/actAiQuery.h"
#include "KingSystem/ActorSystem/queryDummyQuery.h"
#include "KingSystem/Resource/resResourceAIProgram.h"
namespace ksys::act::ai {
Queries::Queries() = default;
Queries::~Queries() {
finalize();
}
void Queries::finalize() {
for (s32 i = 0; i < mClasses.size(); ++i) {
if (mClasses[i]) {
delete mClasses[i];
mClasses[i] = nullptr;
}
}
mOnPreDeleteCbs.freeBuffer();
mUpdateForPreDeleteCbs.freeBuffer();
mClasses.freeBuffer();
}
bool Queries::init(Actor* actor, sead::Heap* heap) {
const auto* aiprog = actor->getParam()->getRes().mAIProgram;
const auto num_Queries = aiprog->getQueries().size();
if (num_Queries == 0)
return true;
if (!mClasses.tryAllocBuffer(num_Queries, heap))
return false;
for (s32 i = 0, n = mClasses.size(); i != n; ++i)
mClasses(i) = nullptr;
auto it_class = mClasses.begin();
const auto it_class_end = mClasses.end();
Query::InitArg arg;
arg.actor = actor;
s32 predelete_cb_num = 0;
s32 update_cb_num = 0;
for (; it_class != it_class_end; ++it_class) {
arg.def_idx = it_class.getIndex();
const char* name = aiprog->getQueries()[it_class.getIndex()].mClassName;
auto* factory = getFactory(name);
if (factory)
*it_class = factory->create_fn(arg, heap);
else
*it_class = new (heap) DummyQuery(arg);
if (!*it_class)
return false;
update_cb_num += (*it_class)->hasUpdateForPreDeleteCb();
predelete_cb_num += (*it_class)->hasPreDeleteCb();
}
// Allocate the callback lists.
if (predelete_cb_num != 0) {
if (!mOnPreDeleteCbs.tryAllocBuffer(predelete_cb_num, heap))
return false;
for (s32 i = 0; i < predelete_cb_num; ++i)
mOnPreDeleteCbs(i) = nullptr;
}
if (update_cb_num != 0) {
if (!mUpdateForPreDeleteCbs.tryAllocBuffer(update_cb_num, heap))
return false;
for (s32 i = 0; i < update_cb_num; ++i)
mUpdateForPreDeleteCbs(i) = nullptr;
}
// Initialize each class.
s32 idx_cb1 = 0, idx_cb2 = 0;
for (auto it = mClasses.begin(), end = mClasses.end(); it != end; ++it) {
if (!(*it)->init(heap))
return false;
if ((*it)->hasUpdateForPreDeleteCb()) {
mUpdateForPreDeleteCbs[idx_cb2] = *it;
++idx_cb2;
}
if ((*it)->hasPreDeleteCb()) {
mOnPreDeleteCbs[idx_cb1] = *it;
++idx_cb1;
}
}
return true;
}
bool Queries::updateForPreDelete() const {
bool ok = true;
for (auto* cb : mUpdateForPreDeleteCbs) {
if (cb)
ok &= cb->updateForPreDelete();
}
return ok;
}
void Queries::onPreDelete() const {
for (auto* cb : mOnPreDeleteCbs) {
if (cb)
cb->onPreDelete();
}
}
Query* Queries::getQuery(const sead::SafeString& name) const {
for (auto* query : mClasses) {
if (name == query->getName())
return query;
}
return nullptr;
}
QueryFactory* Queries::getFactory(const sead::SafeString& name) {
const u32 name_hash = sead::HashCRC32::calcStringHash(name);
const s32 idx = sFactories.binarySearch(
name_hash, +[](const QueryFactory& factory, const u32& hash) {
if (factory.hash < hash)
return -1;
if (factory.hash > hash)
return 1;
return 0;
});
if (idx < 0)
return nullptr;
return sFactories.get(idx);
}
void Queries::setFactories(int count, QueryFactory* factories) {
sFactories.setBuffer(count, factories);
}
} // namespace ksys::act::ai
+41
View File
@@ -0,0 +1,41 @@
#pragma once
#include <container/seadBuffer.h>
#include <prim/seadSafeString.h>
namespace ksys::act {
class Actor;
}
namespace ksys::act::ai {
class Query;
struct QueryFactory;
class Queries {
public:
Queries();
~Queries();
void finalize();
bool init(Actor* actor, sead::Heap* heap);
bool updateForPreDelete() const;
void onPreDelete() const;
const sead::Buffer<Query*>& getClasses() const { return mClasses; }
Query* getQuery(const sead::SafeString& name) const;
static QueryFactory* getFactory(const sead::SafeString& name);
static void setFactories(int count, QueryFactory* factories);
private:
static inline sead::Buffer<QueryFactory> sFactories;
sead::Buffer<Query*> mClasses;
// Non-owning buffer.
sead::Buffer<Query*> mOnPreDeleteCbs;
// Non-owning buffer.
sead::Buffer<Query*> mUpdateForPreDeleteCbs;
};
} // namespace ksys::act::ai
+8 -16
View File
@@ -51,15 +51,15 @@ public:
bool getAITreeVariable(sead::SafeString** value, const sead::SafeString& param) const;
bool getAITreeVariable(void** value, const sead::SafeString& param) const;
virtual bool m4() { return false; }
virtual bool m5() { return false; }
virtual bool hasPreDeleteCb() { return false; }
virtual bool hasUpdateForPreDeleteCb() { return false; }
virtual void m6() {}
virtual bool init_(sead::Heap* heap) { return true; }
virtual void loadParams() {}
virtual int doQuery() { return 0; }
virtual void m10() {}
virtual bool m11() { return true; }
virtual void m12() {}
virtual bool updateForPreDelete() { return true; }
virtual void onPreDelete() {}
protected:
res::AIProgram* getAIProg() const;
@@ -80,18 +80,10 @@ protected:
};
KSYS_CHECK_SIZE_NX150(Query, 0x20);
class Queries {
public:
Queries();
~Queries();
void finalize();
sead::Buffer<Query*> classes;
// TODO: rename
sead::Buffer<Query*> x;
// TODO: rename
sead::Buffer<Query*> y;
struct QueryFactory {
using CreateFn = Query* (*)(const Query::InitArg& arg, sead::Heap* heap);
u32 hash;
CreateFn create_fn;
};
} // namespace ksys::act::ai
+1
View File
@@ -5,6 +5,7 @@
#include "KingSystem/ActorSystem/actAiAi.h"
#include "KingSystem/ActorSystem/actAiBehavior.h"
#include "KingSystem/ActorSystem/actAiParam.h"
#include "KingSystem/ActorSystem/actAiQueries.h"
#include "KingSystem/ActorSystem/actAiQuery.h"
#include "KingSystem/Utils/Types.h"
@@ -0,0 +1,13 @@
#include "KingSystem/ActorSystem/queryDummyQuery.h"
namespace ksys::act::ai {
DummyQuery::DummyQuery(const Query::InitArg& arg) : Query(arg) {}
bool DummyQuery::init_(sead::Heap* heap) {
return true;
}
void DummyQuery::loadParams() {}
} // namespace ksys::act::ai
@@ -0,0 +1,16 @@
#pragma once
#include "KingSystem/ActorSystem/actAiQuery.h"
namespace ksys::act::ai {
class DummyQuery : public Query {
SEAD_RTTI_OVERRIDE(DummyQuery, Query)
public:
explicit DummyQuery(const InitArg& arg);
bool init_(sead::Heap* heap) override;
void loadParams() override;
};
} // namespace ksys::act::ai