13 const std::map<std::size_t, std::size_t> &tile_pal_assignments,
17 std::vector<IndirectLink> links;
19 for (std::size_t group_idx = 0; group_idx < shape_groups.size(); ++group_idx) {
20 const auto &group = shape_groups.at(group_idx);
23 struct ResolvedMember {
24 std::size_t member_idx;
25 std::size_t hw_pal_index;
26 std::map<ShapeMask, Rgba32> colors;
28 std::vector<ResolvedMember> resolved;
30 for (std::size_t m = 0; m < group.members.size(); ++m) {
31 const auto &member = group.members.at(m);
33 if (!tile_pal_assignments.contains(member.tile_index)) {
36 std::size_t
hw_index = tile_pal_assignments.at(member.tile_index);
37 resolved.push_back(ResolvedMember{m,
hw_index, member.colors});
40 if (resolved.size() < 2) {
45 std::set<std::size_t> distinct_pals;
46 for (
const auto &rm : resolved) {
47 distinct_pals.insert(rm.hw_pal_index);
49 if (distinct_pals.size() < 2) {
63 std::size_t best_ref_index = 0;
64 std::size_t best_ref_conflicts = std::numeric_limits<std::size_t>::max();
66 for (std::size_t candidate_ref = 0; candidate_ref < resolved.size(); ++candidate_ref) {
67 const auto &candidate = resolved.at(candidate_ref);
68 const auto &candidate_pal = base_pals.at(candidate.hw_pal_index).value();
71 std::map<ShapeMask, std::size_t> candidate_mask_to_slot;
72 for (
const auto &[mask, color] : candidate.colors) {
74 if (!candidate_pal.is_wildcard(slot) && candidate_pal.at(slot) == color) {
75 candidate_mask_to_slot[mask] = slot;
82 std::size_t conflicts = 0;
83 for (std::size_t other = 0; other < resolved.size(); ++other) {
84 if (other == candidate_ref || resolved.at(other).hw_pal_index == candidate.hw_pal_index) {
87 const auto &other_member = resolved.at(other);
88 if (!prefilled_pals.at(other_member.hw_pal_index).has_value()) {
91 const auto &prefilled = prefilled_pals.at(other_member.hw_pal_index).value();
93 for (
const auto &[mask, other_color] : other_member.colors) {
94 if (!candidate_mask_to_slot.contains(mask)) {
97 std::size_t target_slot = candidate_mask_to_slot.at(mask);
98 if (!prefilled.is_wildcard(target_slot)) {
104 if (conflicts < best_ref_conflicts) {
105 best_ref_conflicts = conflicts;
106 best_ref_index = candidate_ref;
110 const auto &ref = resolved.at(best_ref_index);
113 for (std::size_t r = 0; r < resolved.size(); ++r) {
114 if (r == best_ref_index) {
117 const auto &other = resolved.at(r);
118 if (other.hw_pal_index == ref.hw_pal_index) {
122 for (
const auto &[mask, other_color] : other.colors) {
124 if (!ref.colors.contains(mask)) {
127 const auto &ref_color = ref.colors.at(mask);
132 .source_color = other_color,
133 .ref_pal = ref.hw_pal_index,
134 .ref_color = ref_color,
135 .source_group_index = group_idx,
A generic palette container for colors that support transparency checking.
constexpr std::size_t num_pals
constexpr std::size_t max_size
std::vector< IndirectLink > build_indirect_links(const std::vector< ShapeGroup< Rgba32 > > &shape_groups, const std::map< std::size_t, std::size_t > &tile_pal_assignments, const std::array< std::optional< Palette< Rgba32, pal::max_size > >, pal::num_pals > &base_pals, const std::array< std::optional< Palette< Rgba32, pal::max_size > >, pal::num_pals > &prefilled_pals)
Builds Indirect links from shape groups and pre-computed palette assignments.
Instruction linking a source color to a reference color in another palette.
std::size_t source_pal
The palette index containing the color to be linked.
A group of tiles that share the same canonical shape but have different color assignments.