13 const std::map<std::size_t, std::size_t> &tile_palette_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_palette_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_palette_assignments.contains(member.tile_index)) {
36 std::size_t
hw_index = tile_palette_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_palettes;
46 for (
const auto &rm : resolved) {
47 distinct_palettes.insert(rm.hw_palette_index);
49 if (distinct_palettes.size() < 2) {
61 std::size_t best_ref_index = 0;
62 std::size_t best_ref_conflicts = std::numeric_limits<std::size_t>::max();
64 for (std::size_t candidate_ref = 0; candidate_ref < resolved.size(); ++candidate_ref) {
65 const auto &candidate = resolved.at(candidate_ref);
66 const auto &candidate_palette = base_palettes.at(candidate.hw_palette_index).value();
69 std::map<ShapeMask, std::size_t> candidate_mask_to_slot;
70 for (
const auto &[mask, color] : candidate.colors) {
72 if (!candidate_palette.is_wildcard(slot) && candidate_palette.at(slot) == color) {
73 candidate_mask_to_slot[mask] = slot;
80 std::size_t conflicts = 0;
81 for (std::size_t other = 0; other < resolved.size(); ++other) {
82 if (other == candidate_ref || resolved.at(other).hw_palette_index == candidate.hw_palette_index) {
85 const auto &other_member = resolved.at(other);
86 if (!prefilled_palettes.at(other_member.hw_palette_index).has_value()) {
89 const auto &prefilled = prefilled_palettes.at(other_member.hw_palette_index).value();
91 for (
const auto &[mask, other_color] : other_member.colors) {
92 if (!candidate_mask_to_slot.contains(mask)) {
95 std::size_t target_slot = candidate_mask_to_slot.at(mask);
96 if (!prefilled.is_wildcard(target_slot)) {
102 if (conflicts < best_ref_conflicts) {
103 best_ref_conflicts = conflicts;
104 best_ref_index = candidate_ref;
108 const auto &ref = resolved.at(best_ref_index);
111 for (std::size_t r = 0; r < resolved.size(); ++r) {
112 if (r == best_ref_index) {
115 const auto &other = resolved.at(r);
116 if (other.hw_palette_index == ref.hw_palette_index) {
120 for (
const auto &[mask, other_color] : other.colors) {
122 if (!ref.colors.contains(mask)) {
125 const auto &ref_color = ref.colors.at(mask);
130 .source_color = other_color,
131 .ref_palette = ref.hw_palette_index,
132 .ref_color = ref_color,
133 .source_group_index = group_idx,
A generic palette container for colors that support transparency checking.
constexpr std::size_t max_size
constexpr std::size_t num_palettes
std::vector< IndirectLink > build_indirect_links(const std::vector< ShapeGroup< Rgba32 > > &shape_groups, const std::map< std::size_t, std::size_t > &tile_palette_assignments, const std::array< std::optional< Palette< Rgba32, palette::max_size > >, palette::num_palettes > &base_palettes, const std::array< std::optional< Palette< Rgba32, palette::max_size > >, palette::num_palettes > &prefilled_palettes)
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_palette
The palette index containing the color to be linked.
A group of tiles that share the same canonical shape but have different color assignments.