Skip to content

Commit

Permalink
InputCommon: add support for overlaying host textures onto the final …
Browse files Browse the repository at this point in the history
…texture instead of overwriting
  • Loading branch information
iwubcode committed Oct 9, 2021
1 parent 8502649 commit e59cda7
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 11 deletions.
40 changes: 30 additions & 10 deletions Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ bool Configuration::ApplyEmulatedEntry(const Configuration::HostEntries& host_en
section->Get(entry.m_key, &host_key);
return ApplyEmulatedSingleEntry(
host_entries, std::vector<std::string>{host_key}, entry.m_tag,
entry.m_region, image_to_write, preserve_aspect_ratio);
entry.m_region, entry.m_copy_type, image_to_write,
preserve_aspect_ratio);
},
[&, this](const Data::EmulatedMultiEntry& entry) {
return ApplyEmulatedMultiEntry(host_entries, entry, section,
Expand All @@ -218,7 +219,8 @@ bool Configuration::ApplyEmulatedEntry(const Configuration::HostEntries& host_en
bool Configuration::ApplyEmulatedSingleEntry(const Configuration::HostEntries& host_entries,
const std::vector<std::string> keys,
const std::optional<std::string> tag,
const Rect& region, ImagePixelData& image_to_write,
const Rect& region, Data::CopyType copy_type,
ImagePixelData& image_to_write,
bool preserve_aspect_ratio) const
{
for (auto& host_entry : host_entries)
Expand All @@ -243,8 +245,16 @@ bool Configuration::ApplyEmulatedSingleEntry(const Configuration::HostEntries& h
Resize(ResizeMode::Nearest, *host_key_image, region.GetWidth(), region.GetHeight());
}

CopyImageRegion(pixel_data, image_to_write, Rect{0, 0, region.GetWidth(), region.GetHeight()},
region);
if (copy_type == DynamicInputTextures::Data::CopyType::Overwrite)
{
CopyImageRegion(pixel_data, image_to_write,
Rect{0, 0, region.GetWidth(), region.GetHeight()}, region);
}
else
{
OverlayImageRegion(pixel_data, image_to_write,
Rect{0, 0, region.GetWidth(), region.GetHeight()}, region);
}

return true;
}
Expand All @@ -270,8 +280,8 @@ bool Configuration::ApplyEmulatedMultiEntry(const Configuration::HostEntries& ho
host_keys.push_back(host_key);
}
if (ApplyEmulatedSingleEntry(host_entries, host_keys, emulated_entry.m_combined_tag,
emulated_entry.m_combined_region, image_to_write,
preserve_aspect_ratio))
emulated_entry.m_combined_region, emulated_entry.m_copy_type,
image_to_write, preserve_aspect_ratio))
{
return true;
}
Expand All @@ -287,10 +297,20 @@ bool Configuration::ApplyEmulatedMultiEntry(const Configuration::HostEntries& ho

if (apply)
{
CopyImageRegion(temporary_pixel_data, image_to_write,
Rect{0, 0, emulated_entry.m_combined_region.GetWidth(),
emulated_entry.m_combined_region.GetHeight()},
emulated_entry.m_combined_region);
if (emulated_entry.m_copy_type == DynamicInputTextures::Data::CopyType::Overwrite)
{
CopyImageRegion(temporary_pixel_data, image_to_write,
Rect{0, 0, emulated_entry.m_combined_region.GetWidth(),
emulated_entry.m_combined_region.GetHeight()},
emulated_entry.m_combined_region);
}
else
{
OverlayImageRegion(temporary_pixel_data, image_to_write,
Rect{0, 0, emulated_entry.m_combined_region.GetWidth(),
emulated_entry.m_combined_region.GetHeight()},
emulated_entry.m_combined_region);
}
}

return apply;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Configuration
bool preserve_aspect_ratio) const;
bool ApplyEmulatedSingleEntry(const HostEntries& host_entries,
const std::vector<std::string> keys,
const std::optional<std::string> tag, const Rect& region,
const std::optional<std::string> tag, const Rect& region, Data::CopyType copy_type,
ImagePixelData& image_to_write, bool preserve_aspect_ratio) const;
bool ApplyEmulatedMultiEntry(const HostEntries& host_entries,
const Data::EmulatedMultiEntry& emulated_entry,
Expand Down
8 changes: 8 additions & 0 deletions Source/Core/InputCommon/DynamicInputTextures/DITData.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,25 @@ struct Data
struct EmulatedMultiEntry;
using EmulatedEntry = std::variant<EmulatedSingleEntry, EmulatedMultiEntry>;

enum class CopyType
{
Overwrite,
Overlay
};

struct EmulatedSingleEntry
{
std::string m_key;
std::optional<std::string> m_tag;
Rect m_region;
CopyType m_copy_type = CopyType::Overwrite;
};

struct EmulatedMultiEntry
{
std::string m_combined_tag;
Rect m_combined_region;
CopyType m_copy_type = CopyType::Overwrite;

std::vector<EmulatedEntry> m_sub_entries;
};
Expand Down
23 changes: 23 additions & 0 deletions Source/Core/InputCommon/DynamicInputTextures/DITSpecification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,29 @@ std::optional<Data::EmulatedEntry> GetEmulatedEntry(const picojson::object& entr
entry.m_key = *entry_key;
entry.m_tag = GetJsonValueFromMap<std::string>(entry_obj, "tag", json_file, false);

const auto copy_type =
GetJsonValueFromMap<std::string>(entry_obj, "copy_type", json_file, false);
if (copy_type)
{
const auto& copy_type_str = *copy_type;
if (copy_type_str == "overwrite")
{
entry.m_copy_type = DynamicInputTextures::Data::CopyType::Overwrite;
}
else if (copy_type_str == "overlay")
{
entry.m_copy_type = DynamicInputTextures::Data::CopyType::Overlay;
}
else
{
ERROR_LOG_FMT(VIDEO,
"Failed to load dynamic input json file '{}' because field "
"'copy_type' had invalid value '{}'",
json_file, copy_type_str);
return std::nullopt;
}
}

const auto entry_region = GetRect(entry_obj, "region", json_file);
if (!entry_region)
return std::nullopt;
Expand Down
22 changes: 22 additions & 0 deletions Source/Core/InputCommon/ImageOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@ void CopyImageRegion(const ImagePixelData& src, ImagePixelData& dst, const Rect&
}
}

void OverlayImageRegion(const ImagePixelData& src, ImagePixelData& dst, const Rect& src_region,
const Rect& dst_region, const Pixel& pixel_skip_color)
{
if (src_region.GetWidth() != dst_region.GetWidth() ||
src_region.GetHeight() != dst_region.GetHeight())
{
return;
}

for (u32 x = 0; x < dst_region.GetWidth(); x++)
{
for (u32 y = 0; y < dst_region.GetHeight(); y++)
{
const auto& src_pixel = src.pixels[(y + src_region.top) * src.width + x + src_region.left];
if (src_pixel == pixel_skip_color)
continue;

dst.pixels[(y + dst_region.top) * dst.width + x + dst_region.left] = src_pixel;
}
}
}

std::optional<ImagePixelData> LoadImage(const std::string& path)
{
File::IOFile file;
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/InputCommon/ImageOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ struct ImagePixelData

void CopyImageRegion(const ImagePixelData& src, ImagePixelData& dst, const Rect& src_region,
const Rect& dst_region);
void OverlayImageRegion(const ImagePixelData& src, ImagePixelData& dst, const Rect& src_region,
const Rect& dst_region, const Pixel& pixel_skip_color = Pixel{});

std::optional<ImagePixelData> LoadImage(const std::string& path);

Expand Down
12 changes: 12 additions & 0 deletions docs/DynamicInputTextures/DynamicInputTexturesV2.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ Here is an example of a single key with a tag:
}
```

By default the region expressed by the key will be overwritten by the host image. For many games though, there are colors or details that we do not want to completely remove and therefore want to overlay the host image on top of the underlying game texture. To do this you can use "copy_type". By default "copy_type" defaults to 'overwrite' but you may also set it to 'overlay'. Here is an example of a key with the 'overlay' copy_type:

```js
{
"bind_type": "single",
"key": "Buttons/A",
"copy_type": "overlay",
"region": [0, 0, 30, 30]
}
```

##### Multi Key

The single key case works well when an image maps directly to Dolphin's emulated controller bindings. However, what about the case where there is a dpad icon? Dolphin has four mappings for that. This is where a "bind_type" of ``multi`` is helpful.
Expand All @@ -96,6 +107,7 @@ Here's an example of that:
{
"bind_type": "multi",
"tag": "dpad",
"copy_type": "overlay",
"region": [0, 0, 45, 45],
"sub_entries": [
{
Expand Down

0 comments on commit e59cda7

Please sign in to comment.