Skip to content

Instantly share code, notes, and snippets.

@leoetlino
Created October 31, 2020 22:46
Show Gist options
  • Save leoetlino/e6c8be64e6074523d52ded262a682f54 to your computer and use it in GitHub Desktop.
Save leoetlino/e6c8be64e6074523d52ded262a682f54 to your computer and use it in GitHub Desktop.
/**
* @param dest Destination flag array
* @param src Source flag array
* @param records Copy records (only used if add_records is true)
* @param counts Boolean flag counts per category (only used if T = bool)
* @param record_copies Whether copies should be recorded
* @param ignore_temp_flags Whether temporary flags (i.e. flags that aren't saved)
* should be ignored
* @param find_existing_record See addFlagCopyRecord.
* @param is_array Whether the flag arrays are associated with an array-type flag (e.g. bool array)
*/
template <typename T>
void copyFlags(sead::PtrArray<FlagBase>& dest, const sead::PtrArray<FlagBase>& src,
sead::ObjArray<TriggerParam::FlagCopyRecord>& records,
sead::SafeArray<s32, 15>& counts, bool record_copies, bool ignore_temp_flags,
bool find_existing_record, bool is_array) {
// This function only handles two cases:
//
// 1. If both the source and destination have the same number of flags, we assume that
// both arrays store the same flags in the exact same order.
//
// 2. If the source has fewer flags than the destination, it is assumed that src is a subset of
// dest (i.e. every flag that is in src is also in dest) and src forms a subsequence of dest.
// Any flag in dest that isn't in src will be reset to its initial value.
const auto update_records = [&](Flag<T>* flag, s32 i) {
s32 category;
if constexpr (std::is_same<T, bool>())
category = flag->getCategory();
if (record_copies)
addFlagCopyRecord<T>(records, flag, is_array ? i : -1, find_existing_record);
if constexpr (std::is_same<T, bool>()) {
if (category > 0) {
if (flag->getValue())
++counts[category - 1];
else if (counts[category - 1] > 0)
--counts[category - 1];
}
}
};
const auto dest_size = dest.size();
const auto src_size = src.size();
if (dest_size == src_size) {
for (s32 i = 0; i < dest_size; ++i) {
if (!dest[i])
continue;
if (ignore_temp_flags && !dest[i]->isSave())
continue;
if (record_copies && dest[i]->isSave())
continue;
if (!src[i]) {
if (!dest[i]->isSave())
dest[i]->resetToInitialValue();
} else {
auto* flag = static_cast<Flag<T>*>(dest[i]);
auto* flag_src = static_cast<Flag<T>*>(src[i]);
flag->setValue(flag_src->getValue());
update_records(flag, i);
}
}
} else if (src_size < dest_size) {
s32 j = 0;
for (s32 i = 0; i < dest_size; ++i) {
if (ignore_temp_flags && !dest[i]->isSave())
continue;
if (record_copies && dest[i]->isSave())
continue;
if (j >= src_size || src[j]->getHash() != dest[i]->getHash()) {
if (!dest[i]->isSave())
dest[i]->resetToInitialValue();
} else if (src[j]->getHash() == dest[i]->getHash()) {
auto* flag = static_cast<Flag<T>*>(dest[i]);
auto* flag_src = static_cast<Flag<T>*>(src[j]);
flag->setValue(flag_src->getValue());
update_records(flag, i);
++j;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment