mirror of https://github.com/zeldaret/botw.git
ksys/evt: Add ResourceTimeline
This commit is contained in:
parent
92388bad74
commit
357ef77879
|
@ -75821,14 +75821,14 @@
|
|||
0x0000007100dc6210,j__ZdlPv_889,4,_ZN4ksys3res20EventFlowActorBinderD0Ev
|
||||
0x0000007100dc6214,j__ZdlPv_890,4,_ZN4ksys3res21EventFlowActionBinderD0Ev
|
||||
0x0000007100dc6218,j__ZdlPv_891,4,_ZN4ksys3res20EventFlowQueryBinderD0Ev
|
||||
0x0000007100dc621c,ResourceTimeline::ctor,136,
|
||||
0x0000007100dc62a4,sub_7100DC62A4,180,
|
||||
0x0000007100dc6358,sub_7100DC6358,176,
|
||||
0x0000007100dc6408,ResourceTimeline::loadBfevtm,584,
|
||||
0x0000007100dc6650,ResourceTimeline::x,348,
|
||||
0x0000007100dc67ac,ResourceTimeline::initTimelineObj,1132,
|
||||
0x0000007100dc6c18,sub_7100DC6C18,100,
|
||||
0x0000007100dc6c7c,sub_7100DC6C7C,420,
|
||||
0x0000007100dc621c,ResourceTimeline::ctor,136,_ZN4ksys3evt16ResourceTimelineC1Ev
|
||||
0x0000007100dc62a4,sub_7100DC62A4,180,_ZN4ksys3evt16ResourceTimelineD1Ev
|
||||
0x0000007100dc6358,sub_7100DC6358,176,_ZN4ksys3evt16ResourceTimelineD0Ev
|
||||
0x0000007100dc6408,ResourceTimeline::loadBfevtm,584,_ZN4ksys3evt16ResourceTimeline13loadEventFlowEPN4sead4HeapERKN2al9ByamlIterEPNS_3res6HandleE
|
||||
0x0000007100dc6650,ResourceTimeline::x,348,_ZN4ksys3evt16ResourceTimeline10finishLoadEv
|
||||
0x0000007100dc67ac,ResourceTimeline::initTimelineObj,1132,_ZN4ksys3evt16ResourceTimeline13setUpBindingsEPNS0_13ActorBindingsEPN4sead4HeapE?
|
||||
0x0000007100dc6c18,sub_7100DC6C18,100,_ZN4ksys3evt16ResourceTimeline13buildTimelineEPN4evfl11TimelineObjEiPN4sead4HeapE
|
||||
0x0000007100dc6c7c,sub_7100DC6C7C,420,_ZN4ksys3evt16bindActorActionsERN4evfl11TimelineObjENS_3res21EventFlowActionBinderE
|
||||
0x0000007100dc6e20,EventBgmInfo::ctor,340,
|
||||
0x0000007100dc6f74,sub_7100DC6F74,268,
|
||||
0x0000007100dc7080,sub_7100DC7080,256,
|
||||
|
|
Can't render this file because it is too large.
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
Subproject commit 1bb352ff3e27137c6345f2f9ca71994da3a7abfc
|
||||
Subproject commit c35d21b34397bec6dd3c67a649fc66b68839341e
|
|
@ -21,4 +21,6 @@ target_sources(uking PRIVATE
|
|||
evtOrderParam.h
|
||||
evtResourceFlowchart.cpp
|
||||
evtResourceFlowchart.h
|
||||
evtResourceTimeline.cpp
|
||||
evtResourceTimeline.h
|
||||
)
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
#include "KingSystem/Event/evtResourceTimeline.h"
|
||||
#include <evfl/ResEventFlowFile.h>
|
||||
#include <evfl/ResTimeline.h>
|
||||
#include <evfl/TimelineObj.h>
|
||||
#include "KingSystem/Event/evtActorBindings.h"
|
||||
#include "KingSystem/Event/evtEventResource.h"
|
||||
#include "KingSystem/Resource/Event/resEventFlowBinder.h"
|
||||
#include "KingSystem/Resource/Event/resResourceEventFlow.h"
|
||||
#include "KingSystem/Resource/resLoadRequest.h"
|
||||
#include "KingSystem/Utils/Byaml/Byaml.h"
|
||||
|
||||
namespace ksys::evt {
|
||||
|
||||
ResourceTimeline::ResourceTimeline() {
|
||||
mLoadFailed = false;
|
||||
}
|
||||
|
||||
ResourceTimeline::~ResourceTimeline() {
|
||||
for (int i = 0; i < mTimelines.size(); ++i)
|
||||
mTimelines[i].handle.requestUnload2();
|
||||
|
||||
mTimelines.freeBuffer();
|
||||
}
|
||||
|
||||
void ResourceTimeline::loadEventFlow(sead::Heap* heap, const al::ByamlIter& event_info,
|
||||
res::Handle* pack_handle) {
|
||||
al::ByamlIter sub_timelines;
|
||||
int num_sub_timelines = 0;
|
||||
if (event_info.tryGetIterByKey(&sub_timelines, "sub_timelines"))
|
||||
num_sub_timelines = sub_timelines.getSize();
|
||||
|
||||
res::LoadRequest request;
|
||||
request.mRequester = "ResourceTimeline";
|
||||
request.mPackHandle = pack_handle;
|
||||
request._22 = true;
|
||||
|
||||
mTimelines.allocBufferAssert(1 + num_sub_timelines, heap);
|
||||
|
||||
for (int i = 0; i < mTimelines.size(); ++i)
|
||||
mTimelines[i].loaded = false;
|
||||
|
||||
// Load the main flowchart.
|
||||
sead::FormatFixedSafeString<128> path("EventFlow/%s.bfevtm", mName.cstr());
|
||||
mTimelines[0].handle.requestLoad(path, &request);
|
||||
|
||||
// Load any subfiles.
|
||||
for (int i = 0; i < num_sub_timelines; ++i) {
|
||||
al::ByamlIter sub_entry;
|
||||
sub_timelines.tryGetIterByIndex(&sub_entry, i);
|
||||
const char* sub_timeline_name;
|
||||
sub_entry.tryGetStringByKey(&sub_timeline_name, "name");
|
||||
|
||||
sead::FormatFixedSafeString<128> sub_path("EventFlow/%s.bfevtm", sub_timeline_name);
|
||||
mTimelines[i + 1].handle.requestLoad(sub_path, &request);
|
||||
}
|
||||
}
|
||||
|
||||
bool ResourceTimeline::finishLoad() {
|
||||
bool ready = true;
|
||||
|
||||
for (int i = 0; i < mTimelines.size(); ++i) {
|
||||
auto& timeline = mTimelines[i];
|
||||
if (timeline.loaded)
|
||||
continue;
|
||||
|
||||
if (timeline.handle.isReadyOrNeedsParse())
|
||||
timeline.handle.parseResource(nullptr);
|
||||
|
||||
if (timeline.handle.isSuccess()) {
|
||||
auto* evfl_res = sead::DynamicCast<res::EventTimeline>(timeline.handle.getResource());
|
||||
if (evfl_res) {
|
||||
timeline.res_event_flow_file = evfl_res->getRes();
|
||||
timeline.res_timeline = timeline.res_event_flow_file->timelines.Get()->Get();
|
||||
timeline.loaded = true;
|
||||
}
|
||||
} else if (timeline.handle.checkLoadStatus()) {
|
||||
timeline.loaded = true;
|
||||
mLoadFailed = true;
|
||||
}
|
||||
|
||||
if (!timeline.loaded)
|
||||
ready = false;
|
||||
}
|
||||
|
||||
return ready;
|
||||
}
|
||||
|
||||
long bindActorActions(evfl::TimelineObj& obj, res::EventFlowActionBinder binder) {
|
||||
auto* res_timeline = obj.GetTimeline();
|
||||
|
||||
ore::Array<const evfl::ResActor> actors{res_timeline->actors.Get(), res_timeline->num_actors};
|
||||
for (int actor_idx = 0; actor_idx < actors.size(); ++actor_idx) {
|
||||
ore::Array<const evfl::ResAction> actions{actors[actor_idx].actions.Get(),
|
||||
actors[actor_idx].num_actions};
|
||||
for (int i = 0; i < actions.size(); ++i)
|
||||
obj.GetActBinder().RegisterAction(actor_idx, &actions[i]);
|
||||
}
|
||||
|
||||
u8 ok;
|
||||
u8 failed;
|
||||
auto binder_ = binder;
|
||||
|
||||
ok = false;
|
||||
failed = false;
|
||||
|
||||
auto& evfl_bindings = obj.GetActBinder().GetBindings();
|
||||
for (auto b = evfl_bindings.begin(); b != evfl_bindings.end(); ++b) {
|
||||
if (!b->IsUsed() || !b->IsInitialized())
|
||||
continue;
|
||||
|
||||
const auto* actor = b->GetActor();
|
||||
for (auto a = b->GetActions().begin(); a != b->GetActions().end(); ++a) {
|
||||
binder_.bind(a, a->res_action, actor, static_cast<ActorBinding*>(b->GetUserData()));
|
||||
(a->handler ? ok : failed) = true;
|
||||
}
|
||||
}
|
||||
|
||||
return int(ok) | (int(failed) << 8);
|
||||
}
|
||||
|
||||
// NON_MATCHING: minor reordering for the buildTimeline loop
|
||||
bool ResourceTimeline::setUpBindings(ActorBindings* bindings, sead::Heap* heap) {
|
||||
sead::Buffer<evfl::TimelineObj> timeline_objs;
|
||||
timeline_objs.allocBufferAssert(mTimelines.size(), heap);
|
||||
|
||||
[&] {
|
||||
for (int i = 0; i < mTimelines.size(); ++i)
|
||||
buildTimeline(&timeline_objs[i], i, heap);
|
||||
}();
|
||||
|
||||
// Bind actors. (For an explanation of why binding is done twice, see ResourceFlowchart.)
|
||||
const auto bind_actors = [&] {
|
||||
for (int i = 0; i < mTimelines.size(); ++i) {
|
||||
auto& obj = timeline_objs[i];
|
||||
res::EventFlowActorBinder binder(bindings, heap);
|
||||
bool ok = false;
|
||||
bool failed = false;
|
||||
|
||||
auto& evfl_bindings = obj.GetActBinder().GetBindings();
|
||||
for (auto it = evfl_bindings.begin(); it != evfl_bindings.end(); ++it) {
|
||||
if (it->IsUsed() && !it->IsInitialized()) {
|
||||
binder.bind(it, it->GetActor());
|
||||
(it->IsInitialized() ? ok : failed) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
bind_actors();
|
||||
bindings->allocBindings(heap);
|
||||
bind_actors();
|
||||
|
||||
// Bind actions.
|
||||
for (int i = 0; i < mTimelines.size(); ++i)
|
||||
bindActorActions(timeline_objs[i], res::EventFlowActionBinder(bindings, heap));
|
||||
bindings->allocBindingsActions(heap);
|
||||
for (int i = 0; i < mTimelines.size(); ++i)
|
||||
bindActorActions(timeline_objs[i], res::EventFlowActionBinder(bindings, heap));
|
||||
|
||||
for (int i = 0; i < mTimelines.size(); ++i)
|
||||
timeline_objs[i].GetActBinder().UnbindAll();
|
||||
|
||||
timeline_objs.freeBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResourceTimeline::buildTimeline(evfl::TimelineObj* obj, int idx, sead::Heap* heap) {
|
||||
auto& timeline = mTimelines[idx];
|
||||
evfl::TimelineObj::Builder builder(timeline.res_timeline);
|
||||
return builder.Build(obj, makeEvflAllocateArg(heap));
|
||||
}
|
||||
|
||||
} // namespace ksys::evt
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <container/seadBuffer.h>
|
||||
#include <prim/seadSafeString.h>
|
||||
#include "KingSystem/Resource/resHandle.h"
|
||||
|
||||
namespace al {
|
||||
class ByamlIter;
|
||||
}
|
||||
|
||||
namespace evfl {
|
||||
struct ResEventFlowFile;
|
||||
struct ResTimeline;
|
||||
class TimelineObj;
|
||||
} // namespace evfl
|
||||
|
||||
namespace ksys::evt {
|
||||
|
||||
class ActorBindings;
|
||||
|
||||
class ResourceTimeline {
|
||||
public:
|
||||
ResourceTimeline();
|
||||
virtual ~ResourceTimeline();
|
||||
|
||||
/// Loads event timeline resource files asynchronously.
|
||||
void loadEventFlow(sead::Heap* heap, const al::ByamlIter& event_info, res::Handle* pack_handle);
|
||||
|
||||
/// @return true if the load completed (succeeded or failed), false if it is still ongoing.
|
||||
bool finishLoad();
|
||||
|
||||
/// @return whether at least one actor was bound.
|
||||
bool setUpBindings(ActorBindings* bindings, sead::Heap* heap);
|
||||
|
||||
/// @return whether the build was successful.
|
||||
bool buildTimeline(evfl::TimelineObj* obj, int idx, sead::Heap* heap);
|
||||
|
||||
private:
|
||||
struct Res {
|
||||
res::Handle handle;
|
||||
const evfl::ResEventFlowFile* res_event_flow_file;
|
||||
const evfl::ResTimeline* res_timeline;
|
||||
bool loaded;
|
||||
};
|
||||
|
||||
sead::Buffer<Res> mTimelines;
|
||||
bool mLoadFailed;
|
||||
sead::FixedSafeString<64> mName;
|
||||
};
|
||||
|
||||
} // namespace ksys::evt
|
Loading…
Reference in New Issue