mirror of
https://github.com/zeldaret/botw
synced 2026-09-01 17:30:00 -04:00
Switch to subrepos
git subrepo clone https://github.com/open-ead/sead lib/sead subrepo: subdir: "lib/sead" merged: "1b66e825d" upstream: origin: "https://github.com/open-ead/sead" branch: "master" commit: "1b66e825d" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo" commit: "2f68596" git subrepo clone (merge) https://github.com/open-ead/nnheaders lib/NintendoSDK subrepo: subdir: "lib/NintendoSDK" merged: "9ee21399f" upstream: origin: "https://github.com/open-ead/nnheaders" branch: "master" commit: "9ee21399f" git-subrepo: version: "0.4.3" origin: "ssh://git@github.com/ingydotnet/git-subrepo" commit: "2f68596" git subrepo clone https://github.com/open-ead/agl lib/agl subrepo: subdir: "lib/agl" merged: "7c063271b" upstream: origin: "https://github.com/open-ead/agl" branch: "master" commit: "7c063271b" git-subrepo: version: "0.4.3" origin: "ssh://git@github.com/ingydotnet/git-subrepo" commit: "2f68596" git subrepo clone https://github.com/open-ead/EventFlow lib/EventFlow subrepo: subdir: "lib/EventFlow" merged: "c35d21b34" upstream: origin: "https://github.com/open-ead/EventFlow" branch: "master" commit: "c35d21b34" git-subrepo: version: "0.4.3" origin: "ssh://git@github.com/ingydotnet/git-subrepo" commit: "2f68596"
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/Param.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/IntrusiveList.h>
|
||||
#include <utility>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
class FlowchartContext;
|
||||
class FlowchartContextNode;
|
||||
class FlowchartObj;
|
||||
struct ResClip;
|
||||
struct ResEvent;
|
||||
struct ResOneshot;
|
||||
class TimelineObj;
|
||||
class VariablePack;
|
||||
|
||||
ORE_VALUED_ENUM(TriggerType, kFlowchart = 0, kClipEnter = 1, kClipLeave = 2, kOneshot = 3,
|
||||
kNormal = 0, kEnter = 1, kLeave = 2)
|
||||
|
||||
class ActionDoneHandler {
|
||||
public:
|
||||
ActionDoneHandler() = default;
|
||||
ActionDoneHandler(FlowchartObj* obj, FlowchartContext* context, int node_idx);
|
||||
explicit ActionDoneHandler(TimelineObj* obj) : m_is_flowchart(false) { m_timeline_obj = obj; }
|
||||
~ActionDoneHandler() { m_list_node.Erase(); }
|
||||
|
||||
ActionDoneHandler(const ActionDoneHandler&) = delete;
|
||||
auto operator=(const ActionDoneHandler&) = delete;
|
||||
|
||||
ActionDoneHandler(ActionDoneHandler&& other) noexcept { *this = std::move(other); }
|
||||
|
||||
ActionDoneHandler& operator=(ActionDoneHandler&& other) noexcept {
|
||||
m_context = other.m_context;
|
||||
m_node_idx = other.m_node_idx;
|
||||
m_obj = other.m_obj;
|
||||
m_node_counter = other.m_node_counter;
|
||||
m_handled = other.m_handled;
|
||||
m_is_flowchart = other.m_is_flowchart;
|
||||
m_list_node = std::move(other.m_list_node);
|
||||
|
||||
other.m_context = nullptr;
|
||||
other.m_node_idx = -1;
|
||||
other.m_node_counter = -1;
|
||||
other.m_obj = nullptr;
|
||||
other.m_handled = false;
|
||||
other.m_is_flowchart = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlowchartContextNode* GetContextNode();
|
||||
void InvokeFromFlowchartImpl();
|
||||
void InvokeFromTimelineImpl();
|
||||
bool IsWaitingJoin();
|
||||
bool CancelWaiting();
|
||||
|
||||
void Reset() {
|
||||
m_context = nullptr;
|
||||
m_obj = nullptr;
|
||||
m_node_idx = -1;
|
||||
m_node_counter = -1;
|
||||
m_handled = false;
|
||||
m_is_flowchart = true;
|
||||
}
|
||||
|
||||
static constexpr size_t GetListNodeOffset() { return offsetof(ActionDoneHandler, m_list_node); }
|
||||
|
||||
private:
|
||||
friend class FlowchartContext;
|
||||
|
||||
ore::IntrusiveListNode m_list_node;
|
||||
FlowchartContext* m_context = nullptr;
|
||||
int m_node_idx = -1;
|
||||
int m_node_counter = -1;
|
||||
union {
|
||||
FlowchartObj* m_obj = nullptr;
|
||||
TimelineObj* m_timeline_obj;
|
||||
};
|
||||
bool m_handled = false;
|
||||
bool m_is_flowchart = true;
|
||||
};
|
||||
|
||||
struct ActionArg {
|
||||
ActionArg(FlowchartContext* context, int node_idx, void* actor_user_data_,
|
||||
void* action_user_data_, VariablePack* variable_pack_, const ResEvent* event_)
|
||||
: param_accessor(context, node_idx), actor_user_data(actor_user_data_),
|
||||
action_user_data(action_user_data_), flowchart_ctx(context),
|
||||
variable_pack(variable_pack_), res(event_), timeline_time_delta(0.0),
|
||||
trigger_type(TriggerType::kFlowchart) {}
|
||||
|
||||
ActionArg(const ResClip* clip, void* actor_user_data_, void* action_user_data_,
|
||||
float timeline_time_delta_, TriggerType::Type type, const ore::ResMetaData* params)
|
||||
: param_accessor(params), actor_user_data(actor_user_data_),
|
||||
action_user_data(action_user_data_), res(clip), timeline_time_delta(timeline_time_delta_),
|
||||
trigger_type(type) {}
|
||||
|
||||
ActionArg(const ResOneshot* oneshot, void* actor_user_data_, void* action_user_data_,
|
||||
float timeline_time_delta_, const ore::ResMetaData* params)
|
||||
: param_accessor(params), actor_user_data(actor_user_data_),
|
||||
action_user_data(action_user_data_), res(oneshot),
|
||||
timeline_time_delta(timeline_time_delta_), trigger_type(TriggerType::kOneshot) {
|
||||
res.oneshot = oneshot;
|
||||
}
|
||||
|
||||
ParamAccessor param_accessor;
|
||||
void* actor_user_data = nullptr;
|
||||
void* action_user_data = nullptr;
|
||||
FlowchartContext* flowchart_ctx = nullptr;
|
||||
VariablePack* variable_pack = nullptr;
|
||||
union Res {
|
||||
explicit Res(const ResEvent* e) : event(e) {}
|
||||
explicit Res(const ResClip* c) : clip(c) {}
|
||||
explicit Res(const ResOneshot* o) : oneshot(o) {}
|
||||
|
||||
const ResEvent* event;
|
||||
const ResClip* clip;
|
||||
const ResOneshot* oneshot;
|
||||
} res;
|
||||
float timeline_time_delta{};
|
||||
TriggerType::Type trigger_type{};
|
||||
};
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/Allocator.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct AllocateArg {
|
||||
void* (*alloc)(size_t size, size_t alignment, void* userdata);
|
||||
void (*free)(void* ptr, void* userdata);
|
||||
void* alloc_userdata;
|
||||
void* free_userdata;
|
||||
};
|
||||
|
||||
class EvflAllocator : public ore::Allocator {
|
||||
public:
|
||||
EvflAllocator() = default;
|
||||
explicit EvflAllocator(AllocateArg arg) : m_arg(arg) {}
|
||||
|
||||
void* AllocImpl(size_t size, size_t alignment) override {
|
||||
return m_arg.alloc(size, alignment, m_arg.alloc_userdata);
|
||||
}
|
||||
|
||||
void FreeImpl(void* ptr) override { m_arg.free(ptr, m_arg.free_userdata); }
|
||||
|
||||
AllocateArg GetArg() const { return m_arg; }
|
||||
|
||||
private:
|
||||
AllocateArg m_arg;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,208 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/EvflAllocator.h>
|
||||
#include <evfl/ResActor.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/Buffer.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/IntrusiveList.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <ore/StringView.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
class Allocator;
|
||||
class BitArray;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
class MetaDataPack;
|
||||
struct ResEntryPoint;
|
||||
struct ResEvent;
|
||||
struct ResFlowchart;
|
||||
class VariablePack;
|
||||
|
||||
ORE_ENUM(SubFlowCallbackType, kEnter, kLeave)
|
||||
|
||||
class FlowchartObj {
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
Builder(const ResFlowchart* flowchart, ore::BitArray* visited_entry_points)
|
||||
: m_flowchart(flowchart), m_entry_points_mask(visited_entry_points) {}
|
||||
|
||||
bool Build(FlowchartObj* obj, ore::Allocator* allocator,
|
||||
ore::IterRange<const ResFlowchart* const*> flowcharts);
|
||||
|
||||
private:
|
||||
const ResFlowchart* m_flowchart{};
|
||||
ore::BitArray* m_entry_points_mask{};
|
||||
ActBinder::Builder m_act_binder_builder{};
|
||||
};
|
||||
|
||||
#ifdef MATCHING_HACK_NX_CLANG
|
||||
[[gnu::always_inline]]
|
||||
#endif
|
||||
~FlowchartObj() = default;
|
||||
|
||||
const ResFlowchart* GetFlowchart() const { return m_flowchart; }
|
||||
const ActBinder& GetActBinder() const { return m_act_binder; }
|
||||
ActBinder& GetActBinder() { return m_act_binder; }
|
||||
|
||||
private:
|
||||
const ResFlowchart* m_flowchart{};
|
||||
ActBinder m_act_binder;
|
||||
};
|
||||
|
||||
class FlowchartContextNode {
|
||||
public:
|
||||
ORE_ENUM(State, kInvalid, kFree, kNotInvoked, kInvoked, kDone, kWaiting)
|
||||
|
||||
FlowchartContextNode() { Reset(); }
|
||||
|
||||
bool IsInvalidOrFree() const { return m_state == State::kInvalid || m_state == State::kFree; }
|
||||
FlowchartObj* GetObj() const { return m_obj; }
|
||||
VariablePack* GetVariablePack() const { return m_variable_pack; }
|
||||
int GetNodeCounter() const { return m_node_counter; }
|
||||
u16 GetEventIdx() const { return m_event_idx; }
|
||||
u16 GetNextNodeIdx() const { return m_next_node_idx; }
|
||||
State::Type GetState() const { return m_state; }
|
||||
|
||||
void Reset() {
|
||||
m_node_counter = -1;
|
||||
m_obj = nullptr;
|
||||
m_event_idx = -1;
|
||||
m_next_node_idx = -1;
|
||||
m_idx = -1;
|
||||
m_state = State::kInvalid;
|
||||
m_variable_pack = nullptr;
|
||||
m_owns_variable_pack = false;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ActionDoneHandler;
|
||||
friend class FlowchartContext;
|
||||
|
||||
FlowchartObj* m_obj;
|
||||
VariablePack* m_variable_pack;
|
||||
int m_node_counter;
|
||||
u16 m_event_idx;
|
||||
u16 m_next_node_idx;
|
||||
u16 m_idx;
|
||||
ore::SizedEnum<State::Type, u8> m_state;
|
||||
bool m_owns_variable_pack;
|
||||
};
|
||||
|
||||
class FlowchartContext {
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
using FlowchartRange = ore::IterRange<const ResFlowchart* const*>;
|
||||
ORE_ENUM(BuildResultType, kSuccess, kInvalidOperation, kResFlowchartNotFound, kEntryPointNotFound)
|
||||
|
||||
struct BuildResult {
|
||||
BuildResultType::Type result;
|
||||
/// Indicates which flowchart was required yet couldn't be found.
|
||||
ore::StringView missing_flowchart_name{};
|
||||
/// Indicates which entry point was required yet couldn't be found.
|
||||
ore::StringView missing_entry_point_name{};
|
||||
};
|
||||
|
||||
Builder() = default;
|
||||
explicit Builder(FlowchartRange flowcharts, int flowchart_idx = 0)
|
||||
: m_flowcharts(flowcharts), m_flowchart_idx(flowchart_idx) {}
|
||||
|
||||
bool SetEntryPoint(const ore::StringView& flowchart_name,
|
||||
const ore::StringView& entry_point_name);
|
||||
bool SetEntryPoint(BuildResult* result, const ore::StringView& flowchart_name,
|
||||
const ore::StringView& entry_point_name);
|
||||
|
||||
bool Build(FlowchartContext* context, AllocateArg allocate_arg);
|
||||
bool Build(BuildResult* result, FlowchartContext* context, AllocateArg allocate_arg);
|
||||
|
||||
private:
|
||||
bool BuildImpl(BuildResult* result, FlowchartRange flowcharts, FlowchartContext* context,
|
||||
AllocateArg allocate_arg, ore::Buffer flowchart_obj_buffer);
|
||||
|
||||
FlowchartRange m_flowcharts{};
|
||||
int m_flowchart_idx = 0;
|
||||
int m_entry_point_idx = -1;
|
||||
};
|
||||
|
||||
FlowchartContext();
|
||||
~FlowchartContext() {
|
||||
Dispose();
|
||||
m_objs.DestructElements();
|
||||
}
|
||||
|
||||
FlowchartContext(const FlowchartContext&) = delete;
|
||||
auto operator=(const FlowchartContext&) = delete;
|
||||
|
||||
void Start(MetaDataPack* pack);
|
||||
int AllocNode();
|
||||
void AllocVariablePack(FlowchartContextNode& node, const ResEntryPoint& entry_point);
|
||||
void ProcessContext();
|
||||
FlowchartObj* FindFlowchartObj(ore::StringView name);
|
||||
const FlowchartObj* FindFlowchartObj(ore::StringView name) const;
|
||||
void UnbindAll();
|
||||
void Clear();
|
||||
void FreeVariablePack(FlowchartContextNode& node);
|
||||
void CopyVariablePack(FlowchartContextNode& src, FlowchartContextNode& dst);
|
||||
bool ProcessContextNode(int node_idx);
|
||||
ActorBinding* TrackBackArgumentActor(int node_idx, const ore::StringView& name);
|
||||
bool IsUsing(const ResFlowchart* flowchart) const;
|
||||
bool IsPlaying(const ResFlowchart* flowchart) const;
|
||||
const ore::Array<ActorBinding>* GetUsedResActors(ore::StringView flowchart_name) const;
|
||||
|
||||
FlowchartContextNode& GetNode(int idx) { return m_nodes[idx]; }
|
||||
const FlowchartContextNode& GetNode(int idx) const { return m_nodes[idx]; }
|
||||
MetaDataPack* GetMetaDataPack() const { return m_metadata_pack; }
|
||||
ore::Array<FlowchartObj>& GetObjs() { return m_objs; }
|
||||
const ore::Array<FlowchartObj>& GetObjs() const { return m_objs; }
|
||||
|
||||
private:
|
||||
void Dispose() {
|
||||
m_obj_idx = -1;
|
||||
m_active_entry_point_idx = -1;
|
||||
m_metadata_pack = nullptr;
|
||||
m_objs.Clear(&m_allocator);
|
||||
for (auto& node : m_nodes)
|
||||
FreeVariablePack(node);
|
||||
m_nodes.Reset();
|
||||
}
|
||||
|
||||
void UpdateNodeCounter(int node_idx) {
|
||||
auto& node = GetNode(node_idx);
|
||||
node.m_node_counter = ++s_GlobalCounter;
|
||||
}
|
||||
|
||||
void CallSubFlowCallback(const ResFlowchart* flowchart, const ResEvent* event,
|
||||
SubFlowCallbackType::Type type) {
|
||||
#ifdef EVFL_VER_LABO
|
||||
if (m_on_sub_flow_callback)
|
||||
m_on_sub_flow_callback(this, flowchart, event, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int s_GlobalCounter;
|
||||
|
||||
EvflAllocator m_allocator;
|
||||
ore::Array<FlowchartObj> m_objs;
|
||||
ore::DynArrayList<FlowchartContextNode> m_nodes;
|
||||
ore::IntrusiveList<ActionDoneHandler> m_handlers;
|
||||
#ifdef EVFL_VER_LABO
|
||||
void (*m_on_sub_flow_callback)(FlowchartContext* context, const ResFlowchart* flowchart,
|
||||
const ResEvent* event, SubFlowCallbackType::Type type) = nullptr;
|
||||
#endif
|
||||
MetaDataPack* m_metadata_pack = nullptr;
|
||||
void* _78 = nullptr;
|
||||
int m_next_node_idx = 0;
|
||||
int m_num_allocated_nodes = 0;
|
||||
int m_obj_idx = -1;
|
||||
int m_active_entry_point_idx = -1;
|
||||
bool m_is_processing = false;
|
||||
u8 _91 = 0;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,208 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/EvflAllocator.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/Buffer.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <ore/ResMetaData.h>
|
||||
#include <ore/StringView.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
struct ResDic;
|
||||
struct ResMetaData;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
class FlowchartContext;
|
||||
class FlowchartObj;
|
||||
struct ResEntryPoint;
|
||||
|
||||
class MetaDataPack {
|
||||
public:
|
||||
ORE_ENUM(DataType, kInt, kBool, kFloat, kString, kWString)
|
||||
|
||||
struct Entry {
|
||||
union Value {
|
||||
bool b;
|
||||
int i;
|
||||
float f;
|
||||
const char* str;
|
||||
const wchar_t* wstr;
|
||||
};
|
||||
|
||||
bool IsKey(const ore::StringView& other) const { return ore::StringView(key) == other; }
|
||||
|
||||
const char* key;
|
||||
Value value;
|
||||
DataType::Type type;
|
||||
};
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
void CalcMemSize();
|
||||
bool Build(MetaDataPack* pack, ore::Buffer buffer);
|
||||
void SetNumEntries(int num) { m_num_entries = num; }
|
||||
int GetRequiredSize() const { return m_required_size; }
|
||||
|
||||
private:
|
||||
int m_num_entries = 16;
|
||||
int m_required_size = 0;
|
||||
int m_alignment_real = 16;
|
||||
int m_entries_byte_size = 0;
|
||||
int m_alignment = 16;
|
||||
int _14 = 0;
|
||||
int m_buffer_offset = -1;
|
||||
};
|
||||
|
||||
void AddInt(const char* key, int value);
|
||||
void AddBool(const char* key, bool value);
|
||||
void AddFloat(const char* key, float value);
|
||||
void AddStringPtr(const char* key, const char* value);
|
||||
void AddWStringPtr(const char* key, const wchar_t* value);
|
||||
|
||||
bool FindInt(int* value, const ore::StringView& key) const;
|
||||
bool FindBool(bool* value, const ore::StringView& key) const;
|
||||
bool FindFloat(float* value, const ore::StringView& key) const;
|
||||
bool FindString(ore::StringView* value, const ore::StringView& key) const;
|
||||
bool FindWString(ore::WStringView* value, const ore::StringView& key) const;
|
||||
|
||||
ore::ResMetaData::DataType::Type GetType(const ore::StringView& key) const;
|
||||
|
||||
private:
|
||||
Entry* Find(const ore::StringView& key) const;
|
||||
Entry& AddEntry() { return m_entries[m_entries_num++]; }
|
||||
|
||||
ore::Array<Entry> GetEntries() const { return {m_entries, m_entries_num}; }
|
||||
|
||||
ore::Buffer m_buffer{};
|
||||
Entry* m_entries{};
|
||||
int m_entries_num{};
|
||||
int m_entries_capacity{};
|
||||
};
|
||||
|
||||
class VariablePack {
|
||||
public:
|
||||
using VariableType = ore::ResMetaData::DataType::Type;
|
||||
|
||||
struct Entry {
|
||||
union Value {
|
||||
void* dummy;
|
||||
int i;
|
||||
float f;
|
||||
ore::DynArrayList<int>* int_array;
|
||||
ore::DynArrayList<float>* float_array;
|
||||
};
|
||||
|
||||
Value value;
|
||||
VariableType type;
|
||||
};
|
||||
|
||||
VariablePack();
|
||||
~VariablePack();
|
||||
VariablePack(const VariablePack&) = delete;
|
||||
auto operator=(const VariablePack&) = delete;
|
||||
|
||||
void Init(AllocateArg arg, const ResEntryPoint* entry_point);
|
||||
|
||||
Entry* GetVariableEntry(const ore::StringView& name);
|
||||
const Entry* GetVariableEntry(const ore::StringView& name) const;
|
||||
VariableType GetVariableType(const ore::StringView& name) const;
|
||||
ore::StringView GetVariableName(int idx) const;
|
||||
int GetVariableCount() const;
|
||||
|
||||
bool Contains(const ore::StringView& name) const;
|
||||
|
||||
bool FindInt(int* value, const ore::StringView& name) const;
|
||||
bool FindBool(bool* value, const ore::StringView& name) const;
|
||||
bool FindFloat(float* value, const ore::StringView& name) const;
|
||||
bool FindIntList(ore::DynArrayList<int>** value, const ore::StringView& name) const;
|
||||
bool FindFloatList(ore::DynArrayList<float>** value, const ore::StringView& name) const;
|
||||
|
||||
int GetInt(const ore::StringView& name) const;
|
||||
bool GetBool(const ore::StringView& name) const;
|
||||
float GetFloat(const ore::StringView& name) const;
|
||||
ore::DynArrayList<int>* GetIntList(const ore::StringView& name) const;
|
||||
ore::DynArrayList<float>* GetFloatList(const ore::StringView& name) const;
|
||||
|
||||
void SetInt(const ore::StringView& name, int value);
|
||||
void SetFloat(const ore::StringView& name, float value);
|
||||
void SetBool(const ore::StringView& name, bool value);
|
||||
|
||||
private:
|
||||
void Dispose();
|
||||
ore::Allocator* GetAllocator() { return &m_allocator; }
|
||||
|
||||
const ore::ResDic* m_names = nullptr;
|
||||
ore::Array<Entry> m_variables;
|
||||
EvflAllocator m_allocator;
|
||||
};
|
||||
|
||||
class ParamAccessor {
|
||||
public:
|
||||
using Type = ore::ResMetaData::DataType::Type;
|
||||
using IntRange = ore::IterRange<const int*>;
|
||||
using FloatRange = ore::IterRange<const float*>;
|
||||
using StringRange = ore::IterRange<const ore::BinTPtr<ore::BinString>*>;
|
||||
using WStringRange = ore::IterRange<const ore::BinTPtr<ore::BinWString>*>;
|
||||
|
||||
explicit ParamAccessor(const ore::ResMetaData* metadata);
|
||||
explicit ParamAccessor(const FlowchartContext* context, int node_idx);
|
||||
|
||||
const ore::ResMetaData* GetFrontResMetaData() const;
|
||||
int GetParamCount() const;
|
||||
ore::StringView GetParamName(int idx) const;
|
||||
Type GetParamType(int idx) const;
|
||||
|
||||
/// @param out_metadata Must be nonnull.
|
||||
/// @param out_metadata_pack Must be nonnull.
|
||||
/// @param out_variable_pack Must be nonnull.
|
||||
/// @param out_obj May be null.
|
||||
/// @param argument Name of the argument to search for.
|
||||
ore::StringView TrackBackArgument(const ore::ResMetaData** out_metadata,
|
||||
const MetaDataPack** out_metadata_pack,
|
||||
const VariablePack** out_variable_pack,
|
||||
FlowchartObj** out_obj,
|
||||
const ore::StringView& argument) const;
|
||||
|
||||
int GetInt(int idx) const;
|
||||
bool FindInt(int* value, const ore::StringView& name) const;
|
||||
|
||||
bool GetBool(int idx) const;
|
||||
bool FindBool(bool* value, const ore::StringView& name) const;
|
||||
|
||||
float GetFloat(int idx) const;
|
||||
bool FindFloat(float* value, const ore::StringView& name) const;
|
||||
|
||||
ore::StringView GetString(int idx) const;
|
||||
bool FindString(ore::StringView* value, const ore::StringView& name) const;
|
||||
|
||||
ore::WStringView GetWString(int idx) const;
|
||||
bool FindWString(ore::WStringView* value, const ore::StringView& name) const;
|
||||
|
||||
IntRange GetIntArray(int idx) const;
|
||||
bool FindIntArray(IntRange* value, const ore::StringView& name) const;
|
||||
|
||||
FloatRange GetFloatArray(int idx) const;
|
||||
bool FindFloatArray(FloatRange* value, const ore::StringView& name) const;
|
||||
|
||||
StringRange GetStringArray(int idx) const;
|
||||
bool FindStringArray(StringRange* value, const ore::StringView& name) const;
|
||||
|
||||
WStringRange GetWStringArray(int idx) const;
|
||||
bool FindWStringArray(WStringRange* value, const ore::StringView& name) const;
|
||||
|
||||
bool FindActorIdentifier(ore::StringView* actor_name, ore::StringView* actor_sub_name,
|
||||
const ore::StringView& name) const;
|
||||
|
||||
private:
|
||||
const ore::ResMetaData* m_metadata = nullptr;
|
||||
const FlowchartContext* m_context = nullptr;
|
||||
int m_node_idx = -1;
|
||||
u32 m_node_counter = -1;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/Param.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
class FlowchartContext;
|
||||
struct ResEvent;
|
||||
class VariablePack;
|
||||
|
||||
ORE_ENUM(QueryValueType, kBool, kInt, kFloat, kString, kConst)
|
||||
|
||||
struct QueryArg {
|
||||
QueryArg(FlowchartContext* context, int node_idx, void* actor_user_data_,
|
||||
void* query_user_data_, const ResEvent* event_, VariablePack* variable_pack_)
|
||||
: actor_user_data(actor_user_data_), query_user_data(query_user_data_), main_event(event_),
|
||||
flowchart_ctx(context), variable_pack(variable_pack_), param_accessor(context, node_idx) {
|
||||
}
|
||||
|
||||
void* actor_user_data;
|
||||
void* query_user_data;
|
||||
const ResEvent* main_event;
|
||||
FlowchartContext* flowchart_ctx;
|
||||
VariablePack* variable_pack;
|
||||
ParamAccessor param_accessor;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,187 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <utility>
|
||||
|
||||
namespace ore {
|
||||
struct ResEndian;
|
||||
struct ResMetaData;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ActionArg;
|
||||
class ActionDoneHandler;
|
||||
class FlowchartContext;
|
||||
class FlowchartContextNode;
|
||||
class FlowchartObj;
|
||||
struct QueryArg;
|
||||
|
||||
struct ResAction {
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
};
|
||||
|
||||
struct ResQuery {
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
};
|
||||
|
||||
struct ResActor {
|
||||
bool HasArgumentName() const { return !argument_name.Get()->empty(); }
|
||||
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::BinTPtr<ore::BinString> secondary_name;
|
||||
ore::BinTPtr<ore::BinString> argument_name;
|
||||
ore::BinTPtr<ResAction> actions;
|
||||
ore::BinTPtr<ResQuery> queries;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
u16 num_actions;
|
||||
u16 num_queries;
|
||||
/// Entry point index for assicated entry point (0xffff if none)
|
||||
u16 entry_point_idx;
|
||||
// TODO: Cut number? This is set to 1 for flowcharts but other values have been seen
|
||||
// for timeline actors.
|
||||
u8 cut_number;
|
||||
};
|
||||
|
||||
using ActionHandler = void (*)(const ActionArg& arg, ActionDoneHandler done_handler);
|
||||
using QueryHandler = int (*)(const QueryArg& arg);
|
||||
|
||||
class ActorBinding {
|
||||
public:
|
||||
struct Action {
|
||||
ActionHandler handler{};
|
||||
void* user_data{};
|
||||
const ResAction* res_action{};
|
||||
};
|
||||
|
||||
struct Query {
|
||||
QueryHandler handler{};
|
||||
void* user_data{};
|
||||
const ResQuery* res_query{};
|
||||
};
|
||||
|
||||
ActorBinding() = default;
|
||||
|
||||
void Register(const ResAction* action);
|
||||
void Register(const ResQuery* query);
|
||||
|
||||
// Similar to std::find_if. Returns m_actions.end() if the specified action is not found.
|
||||
Action* GetAction(const ore::StringView& name);
|
||||
const Action* GetAction(const ore::StringView& name) const;
|
||||
Query* GetQuery(const ore::StringView& name);
|
||||
const Query* GetQuery(const ore::StringView& name) const;
|
||||
|
||||
ore::DynArrayList<Action>& GetActions() { return m_actions; }
|
||||
ore::DynArrayList<Query>& GetQueries() { return m_queries; }
|
||||
const ore::DynArrayList<Action>& GetActions() const { return m_actions; }
|
||||
const ore::DynArrayList<Query>& GetQueries() const { return m_queries; }
|
||||
auto ActionsEnd() const { return m_actions.end(); }
|
||||
auto QueriesEnd() const { return m_queries.end(); }
|
||||
|
||||
auto GetActor() const { return m_actor; }
|
||||
|
||||
void* GetUserData() const { return m_user_data; }
|
||||
void SetUserData(void* user_data) { m_user_data = user_data; }
|
||||
|
||||
bool IsInitialized() const { return m_initialized; }
|
||||
bool IsUsed() const { return m_is_used; }
|
||||
void SetInitialized(bool initialized) { m_initialized = initialized; }
|
||||
void SetIsUsed(bool used) { m_is_used = used; }
|
||||
|
||||
void UnbindAll() {
|
||||
m_user_data = nullptr;
|
||||
m_initialized = false;
|
||||
for (auto it = m_actions.begin(); it != m_actions.end(); ++it) {
|
||||
it->handler = nullptr;
|
||||
it->user_data = nullptr;
|
||||
}
|
||||
for (auto it = m_queries.begin(); it != m_queries.end(); ++it) {
|
||||
it->handler = nullptr;
|
||||
it->user_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ActBinder;
|
||||
|
||||
ore::DynArrayList<Action> m_actions{};
|
||||
ore::DynArrayList<Query> m_queries{};
|
||||
void* m_user_data{};
|
||||
const ResActor* m_actor{};
|
||||
bool m_initialized{};
|
||||
bool m_is_used{};
|
||||
};
|
||||
|
||||
class ActBinder {
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
bool Build(evfl::ActBinder* binder, ore::Allocator* allocator,
|
||||
ore::IterRange<const ResActor*> actors);
|
||||
};
|
||||
|
||||
ActBinder() = default;
|
||||
ActBinder(const ActBinder&) = delete;
|
||||
auto operator=(const ActBinder&) = delete;
|
||||
|
||||
#ifdef MATCHING_HACK_NX_CLANG
|
||||
[[gnu::always_inline]]
|
||||
#endif
|
||||
~ActBinder() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
u32 GetEventUsedActorCount() const { return m_event_used_actor_count; }
|
||||
const ore::Array<ActorBinding>* GetUsedResActors() const;
|
||||
|
||||
ore::Array<ActorBinding>& GetBindings() { return m_bindings; }
|
||||
const ore::Array<ActorBinding>& GetBindings() const { return m_bindings; }
|
||||
void IncrementNumActors() { ++m_event_used_actor_count; }
|
||||
void SetIsUsed() { m_is_used = true; }
|
||||
bool IsUsed() const { return m_is_used; }
|
||||
|
||||
void RegisterAction(int actor_idx, const evfl::ResAction* action) {
|
||||
auto& binding = GetBindings()[actor_idx];
|
||||
if (!binding.IsUsed() && binding.GetActor()->argument_name.Get()->empty()) {
|
||||
IncrementNumActors();
|
||||
binding.SetIsUsed(true);
|
||||
}
|
||||
binding.Register(action);
|
||||
}
|
||||
|
||||
void RegisterQuery(int actor_idx, const evfl::ResQuery* query) {
|
||||
auto& binding = GetBindings()[actor_idx];
|
||||
if (!binding.IsUsed() && binding.GetActor()->argument_name.Get()->empty()) {
|
||||
IncrementNumActors();
|
||||
binding.SetIsUsed(true);
|
||||
}
|
||||
binding.Register(query);
|
||||
}
|
||||
|
||||
void UnbindAll() {
|
||||
for (auto it = m_bindings.begin(); it != m_bindings.end(); ++it)
|
||||
it->UnbindAll();
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
m_event_used_actor_count = 0;
|
||||
if (auto* data = m_bindings.data()) {
|
||||
m_bindings.ClearWithoutFreeing();
|
||||
m_allocator->Free(data);
|
||||
}
|
||||
m_allocator = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_event_used_actor_count{};
|
||||
ore::Allocator* m_allocator{};
|
||||
ore::SelfDestructingArray<ActorBinding> m_bindings{};
|
||||
bool m_is_used{};
|
||||
};
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResActor* actor);
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
struct ResDic;
|
||||
struct ResEndian;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ResFlowchart;
|
||||
struct ResTimeline;
|
||||
|
||||
struct ResEventFlowFile {
|
||||
/// data must be a pointer to a buffer of size >= 0x20.
|
||||
static bool IsValid(void* data);
|
||||
/// data must be a valid ResEventFlowFile.
|
||||
static ResEventFlowFile* ResCast(void* data);
|
||||
|
||||
void Relocate();
|
||||
void Unrelocate();
|
||||
|
||||
ore::BinaryFileHeader header;
|
||||
u16 num_flowcharts;
|
||||
u16 num_timelines;
|
||||
ore::BinTPtr<ore::BinTPtr<ResFlowchart>> flowcharts;
|
||||
ore::BinTPtr<ore::ResDic> flowchart_names;
|
||||
ore::BinTPtr<ore::BinTPtr<ResTimeline>> timelines;
|
||||
ore::BinTPtr<ore::ResDic> timeline_names;
|
||||
};
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResEventFlowFile* file);
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,136 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/ResDic.h>
|
||||
#include <ore/ResMetaData.h>
|
||||
#include <ore/StringView.h>
|
||||
|
||||
namespace ore {
|
||||
struct ResEndian;
|
||||
}
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ResActor;
|
||||
|
||||
struct ResCase {
|
||||
u32 value;
|
||||
u16 event_idx;
|
||||
};
|
||||
|
||||
struct ResEvent {
|
||||
ORE_ENUM(EventType, kAction, kSwitch, kFork, kJoin, kSubFlow)
|
||||
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::SizedEnum<EventType::Type, u8> type;
|
||||
|
||||
union {
|
||||
// Action, Join, Sub flow
|
||||
u16 next_event_idx;
|
||||
// Switch
|
||||
u16 num_cases;
|
||||
// Fork
|
||||
u16 num_forks;
|
||||
};
|
||||
|
||||
union {
|
||||
// Action, Switch
|
||||
u16 actor_idx;
|
||||
// Fork
|
||||
u16 join_event_idx;
|
||||
};
|
||||
|
||||
union {
|
||||
// Action
|
||||
u16 actor_action_idx;
|
||||
// Switch
|
||||
u16 actor_query_idx;
|
||||
};
|
||||
|
||||
union {
|
||||
// Action, Switch, Sub flow
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
// Fork
|
||||
ore::BinTPtr<u16> fork_event_indices;
|
||||
};
|
||||
|
||||
union {
|
||||
// Switch
|
||||
ore::BinTPtr<ResCase> cases;
|
||||
// Sub flow
|
||||
ore::BinTPtr<ore::BinString> sub_flow_flowchart;
|
||||
};
|
||||
|
||||
union {
|
||||
// Sub flow
|
||||
ore::BinTPtr<ore::BinString> sub_flow_entry_point;
|
||||
};
|
||||
};
|
||||
|
||||
struct ResVariableDef {
|
||||
union Value {
|
||||
// Also used for booleans. Anything that is != 0 is treated as true.
|
||||
int i;
|
||||
float f;
|
||||
ore::BinTPtr<int> int_array;
|
||||
ore::BinTPtr<float> float_array;
|
||||
};
|
||||
|
||||
Value value;
|
||||
u16 num;
|
||||
ore::SizedEnum<ore::ResMetaData::DataType::Type, u8> type;
|
||||
};
|
||||
|
||||
struct ResEntryPoint {
|
||||
ore::BinTPtr<u16> sub_flow_event_indices;
|
||||
ore::BinTPtr<ore::ResDic> variable_defs_names;
|
||||
ore::BinTPtr<ResVariableDef> variable_defs;
|
||||
u16 num_sub_flow_event_indices;
|
||||
u16 num_variable_defs;
|
||||
u16 main_event_idx;
|
||||
};
|
||||
|
||||
struct ResFlowchart {
|
||||
int CountEvent(ResEvent::EventType::Type type) const;
|
||||
|
||||
const ResEntryPoint* GetEntryPoint(const ore::StringView& entry_point_name) const {
|
||||
const int idx = entry_point_names.Get()->FindIndex(entry_point_name);
|
||||
if (idx == -1)
|
||||
return nullptr;
|
||||
|
||||
return entry_points.Get() + idx;
|
||||
}
|
||||
|
||||
ore::StringView GetEntryPointName(int idx) const {
|
||||
return entry_point_names.Get()->GetEntries()[1 + idx].GetKey();
|
||||
}
|
||||
|
||||
/// 'EVFL'
|
||||
u32 magic;
|
||||
/// String pool offset (relative to this structure)
|
||||
u32 string_pool_offset;
|
||||
u32 reserved_8;
|
||||
u32 reserved_c;
|
||||
u16 num_actors;
|
||||
u16 num_actions;
|
||||
u16 num_queries;
|
||||
u16 num_events;
|
||||
u16 num_entry_points;
|
||||
u16 reserved_1a;
|
||||
u16 reserved_1c;
|
||||
u16 reserved_1e;
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::BinTPtr<ResActor> actors;
|
||||
ore::BinTPtr<ResEvent> events;
|
||||
ore::BinTPtr<ore::ResDic> entry_point_names;
|
||||
ore::BinTPtr<ResEntryPoint> entry_points;
|
||||
};
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResCase* case_);
|
||||
void SwapEndian(ore::ResEndian* endian, ResEvent* event);
|
||||
void SwapEndian(ore::ResEndian* endian, ResEntryPoint* entry);
|
||||
void SwapEndian(ore::ResEndian* endian, ResVariableDef* def);
|
||||
void SwapEndian(ore::ResEndian* endian, ResFlowchart* flowchart);
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
struct ResEndian;
|
||||
struct ResMetaData;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ResActor;
|
||||
|
||||
struct ResTrigger {
|
||||
u16 clip_index;
|
||||
u8 trigger_type;
|
||||
};
|
||||
|
||||
struct ResCut {
|
||||
float start_time;
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
};
|
||||
|
||||
struct ResClip {
|
||||
float start_time;
|
||||
float duration;
|
||||
u16 actor_index;
|
||||
u16 actor_action_index;
|
||||
u8 _c;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
};
|
||||
|
||||
struct ResOneshot {
|
||||
float time;
|
||||
u16 actor_index;
|
||||
u16 actor_action_index;
|
||||
u32 _8;
|
||||
u32 _c;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
};
|
||||
|
||||
struct ResSubtimeline {
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
};
|
||||
|
||||
struct ResTimeline {
|
||||
/// 'TLIN'
|
||||
u32 magic;
|
||||
/// String pool offset (relative to this structure)
|
||||
int string_pool_offset;
|
||||
u32 reserved_8;
|
||||
u32 reserved_c;
|
||||
float duration;
|
||||
u16 num_actors;
|
||||
u16 num_actions;
|
||||
u16 num_clips;
|
||||
u16 num_oneshots;
|
||||
u16 num_subtimelines;
|
||||
u16 num_cuts;
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::BinTPtr<ResActor> actors;
|
||||
ore::BinTPtr<ResClip> clips;
|
||||
ore::BinTPtr<ResOneshot> oneshots;
|
||||
ore::BinTPtr<ResTrigger> triggers;
|
||||
ore::BinTPtr<ResSubtimeline> subtimelines;
|
||||
ore::BinTPtr<ResCut> cuts;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
};
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResTrigger* trigger);
|
||||
void SwapEndian(ore::ResEndian* endian, ResCut* cut);
|
||||
void SwapEndian(ore::ResEndian* endian, ResClip* clip);
|
||||
void SwapEndian(ore::ResEndian* endian, ResOneshot* oneshot);
|
||||
void SwapEndian(ore::ResEndian* endian, ResSubtimeline* subtimeline);
|
||||
void SwapEndian(ore::ResEndian* endian, ResTimeline* timeline);
|
||||
|
||||
} // namespace evfl
|
||||
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/EvflAllocator.h>
|
||||
#include <evfl/ResActor.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ResTimeline;
|
||||
|
||||
ORE_ENUM(TimelineState, kNotStarted, kPlaying, kStop, kPause)
|
||||
|
||||
class TimelineObj {
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
explicit Builder(const ResTimeline* timeline) : m_timeline(timeline) {}
|
||||
|
||||
bool Build(TimelineObj* obj, AllocateArg allocate_arg);
|
||||
|
||||
private:
|
||||
const ResTimeline* m_timeline = nullptr;
|
||||
ActBinder::Builder m_act_binder_builder;
|
||||
};
|
||||
|
||||
TimelineObj();
|
||||
|
||||
void Calc();
|
||||
void Reset();
|
||||
void SetState(TimelineState::Type state);
|
||||
void Start(float start_time);
|
||||
void JumpTimeTo(float time);
|
||||
void AdvanceTimeTo(float time);
|
||||
bool RegisterSubtimeline(TimelineObj* obj);
|
||||
|
||||
ActBinder& GetActBinder() { return m_act_binder; }
|
||||
const ActBinder& GetActBinder() const { return m_act_binder; }
|
||||
const ore::Array<TimelineObj*>& GetSubTimelines() const { return m_sub_timelines; }
|
||||
const ResTimeline* GetTimeline() const { return m_timeline; }
|
||||
float GetTime() const { return m_time; }
|
||||
float GetNewTime() const { return m_new_time; }
|
||||
int GetLastTriggerIdx() const { return m_last_trigger_idx; }
|
||||
int GetLastOneshotIdx() const { return m_last_oneshot_idx; }
|
||||
int GetPlayCounter() const { return m_play_counter; }
|
||||
bool IsStarted() const { return m_started; }
|
||||
bool IsJumpedTime() const { return m_jumped_time; }
|
||||
TimelineState::Type GetState() const { return m_state; }
|
||||
|
||||
private:
|
||||
void CalcImpl();
|
||||
void JumpTimeToImpl(float time);
|
||||
void AdvanceTimeToImpl(float time);
|
||||
|
||||
static int s_GlobalPlayCounter;
|
||||
|
||||
void Finalize() {
|
||||
m_timeline = nullptr;
|
||||
m_act_binder.Reset();
|
||||
m_sub_timelines.Clear(&m_allocator);
|
||||
}
|
||||
|
||||
EvflAllocator m_allocator;
|
||||
ore::Array<TimelineObj*> m_sub_timelines;
|
||||
const ResTimeline* m_timeline{};
|
||||
ActBinder m_act_binder{};
|
||||
float m_time{};
|
||||
float m_new_time{};
|
||||
int m_last_trigger_idx = -1;
|
||||
int m_last_oneshot_idx = -1;
|
||||
int m_play_counter = 0;
|
||||
bool m_started = false;
|
||||
bool m_jumped_time = false;
|
||||
ore::SizedEnum<TimelineState::Type, u8> m_state = TimelineState::kNotStarted;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
||||
Reference in New Issue
Block a user