summaryrefslogtreecommitdiff
path: root/src/KingSystem/Resource/Actor/resResourceActorLink.cpp
blob: d941d417bc50a42999674f624cd83a6adcb3979b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "KingSystem/Resource/Actor/resResourceActorLink.h"
#include <codec/seadHashCRC32.h>
#include <heap/seadHeapMgr.h>

namespace ksys::res {

ActorLink::ActorLink() : ParamIO("xml", 0) {
    const auto init_user = [this](auto& param, const char* key, const char* default_ = "Dummy") {
        param.init(default_, key, "", &mUsers.obj);
    };
    init_user(mUsers.profile, "ProfileUser");
    init_user(mUsers.actor_capture, "ActorCaptureUser");
    init_user(mUsers.as, "ASUser", "");
    init_user(mUsers.model, "ModelUser", "");
    init_user(mUsers.anim, "AnimUser", "");
    init_user(mUsers.ai_program, "AIProgramUser", "");
    init_user(mUsers.gparam, "GParamUser", "");
    init_user(mUsers.damage_param, "DamageParamUser");
    init_user(mUsers.rg_config_list, "RgConfigListUser");
    init_user(mUsers.rg_blend_weight, "RgBlendWeightUser");
    init_user(mUsers.awareness, "AwarenessUser");
    init_user(mUsers.elink, "ElinkUser");
    init_user(mUsers.slink, "SlinkUser");
    init_user(mUsers.xlink, "XlinkUser");
    init_user(mUsers.attention, "AttentionUser");
    init_user(mUsers.physics, "PhysicsUser");
    init_user(mUsers.chemical, "ChemicalUser");
    init_user(mUsers.drop_table, "DropTableUser");
    init_user(mUsers.shop_data, "ShopDataUser");
    init_user(mUsers.recipe, "RecipeUser");
    init_user(mUsers.lod, "LODUser");
    init_user(mUsers.ai_schedule, "AIScheduleUser");
    init_user(mUsers.bone_control, "BoneControlUser");
    init_user(mUsers.life_condition, "LifeConditionUser");
    init_user(mUsers.umii, "UMiiUser");
    init_user(mUsers.animation_info, "AnimationInfo");

    mActorScale.init(1.0, "ActorScale", "", &mUsers.obj);
    mActorNameJpn.init("不正な名前", "ActorNameJpn", "ActorNameJpn", &mUsers.obj);
    mPriority.init("", "Priority", "Priority", &mUsers.obj);

    addObj(&mUsers.obj, "LinkTarget");
}

bool ActorLink::parse_(u8* data, size_t, sead::Heap* heap) {
    if (!data)
        return true;

    const agl::utl::ResParameterArchive archive{data};
    const auto root = archive.getRootList();

    const s32 tags_idx = root.searchObjIndex(agl::utl::ParameterBase::calcHash("Tags"));
    // NON_MATCHING: getResParameter (redundant uxtw; i and res increment order)
    const auto parse_tags = [&] {
        if (tags_idx == -1)
            return;

        const auto obj = root.getResParameterObj(tags_idx);
        if (!obj.ptr())
            return;

        const auto num_tags = obj.getNum();
        if (num_tags == 0)
            return;

        mHeap = heap;
        mTags.allocBufferAssert(num_tags, heap);

        for (s32 i = 0; i != num_tags; ++i) {
            const char* tag = obj.getResParameter(i).getData<char>();
            mTags[i] = sead::HashCRC32::calcStringHash(tag);
        }

        if (num_tags > 1)
            mTags.heapSort(0, num_tags - 1);
    };
    parse_tags();

    applyResParameterArchive(agl::utl::ResParameterArchive{data});
    return true;
}

void ActorLink::finalize_() {
    if (!mTags.isBufferReady())
        return;

    if (!mHeap)
        return;

    sead::ScopedCurrentHeapSetter setter{mHeap};
    mTags.freeBuffer();
}

// NON_MATCHING: operands are swapped for an equality comparison in binarySearch
bool ActorLink::hasTag(const char* tag_name) const {
    return mTags.size() >= 1 && mTags.binarySearch(sead::HashCRC32::calcStringHash(tag_name)) != -1;
}

bool ActorLink::hasTag(u32 tag) const {
    return mTags.size() >= 1 && mTags.binarySearch(tag) != -1;
}

}  // namespace ksys::res