mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp.git
synced 2026-05-10 19:11:36 +00:00
Created mod UI API functions for imageview elements
This commit is contained in:
parent
9284346fe2
commit
d45c4f7236
10 changed files with 278 additions and 90 deletions
|
|
@ -178,6 +178,7 @@ set (SOURCES
|
||||||
${CMAKE_SOURCE_DIR}/src/ui/ui_mod_menu.cpp
|
${CMAKE_SOURCE_DIR}/src/ui/ui_mod_menu.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ui/ui_api.cpp
|
${CMAKE_SOURCE_DIR}/src/ui/ui_api.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ui/ui_api_events.cpp
|
${CMAKE_SOURCE_DIR}/src/ui/ui_api_events.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/ui/ui_api_images.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ui/util/hsv.cpp
|
${CMAKE_SOURCE_DIR}/src/ui/util/hsv.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ui/core/ui_context.cpp
|
${CMAKE_SOURCE_DIR}/src/ui/core/ui_context.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_button.cpp
|
${CMAKE_SOURCE_DIR}/src/ui/elements/ui_button.cpp
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,9 @@ namespace recompui {
|
||||||
Rml::ElementPtr create_custom_element(Rml::Element* parent, std::string tag);
|
Rml::ElementPtr create_custom_element(Rml::Element* parent, std::string tag);
|
||||||
Rml::ElementDocument* load_document(const std::filesystem::path& path);
|
Rml::ElementDocument* load_document(const std::filesystem::path& path);
|
||||||
Rml::ElementDocument* create_empty_document();
|
Rml::ElementDocument* create_empty_document();
|
||||||
void queue_image_from_bytes(const std::string &src, const std::vector<char> &bytes);
|
|
||||||
|
void queue_image_from_bytes_rgba32(const std::string &src, const std::vector<char> &bytes, uint32_t width, uint32_t height);
|
||||||
|
void queue_image_from_bytes_file(const std::string &src, const std::vector<char> &bytes);
|
||||||
void release_image(const std::string &src);
|
void release_image(const std::string &src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
#include "recomp_ui.h"
|
#include "recomp_ui.h"
|
||||||
|
|
||||||
|
#include "ui_helpers.h"
|
||||||
|
#include "ui_api_images.h"
|
||||||
|
|
||||||
#include "core/ui_context.h"
|
#include "core/ui_context.h"
|
||||||
#include "core/ui_resource.h"
|
#include "core/ui_resource.h"
|
||||||
|
|
||||||
|
|
@ -25,80 +28,6 @@
|
||||||
|
|
||||||
using namespace recompui;
|
using namespace recompui;
|
||||||
|
|
||||||
constexpr ResourceId root_element_id{ 0xFFFFFFFE };
|
|
||||||
|
|
||||||
// Helpers
|
|
||||||
|
|
||||||
ContextId get_context(uint8_t* rdram, recomp_context* ctx) {
|
|
||||||
uint32_t context_id = _arg<0, uint32_t>(rdram, ctx);
|
|
||||||
return ContextId{ .slot_id = context_id };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int arg_index>
|
|
||||||
ResourceId arg_resource_id(uint8_t* rdram, recomp_context* ctx) {
|
|
||||||
uint32_t slot_id = _arg<arg_index, uint32_t>(rdram, ctx);
|
|
||||||
|
|
||||||
return ResourceId{ .slot_id = slot_id };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int arg_index>
|
|
||||||
Element* arg_element(uint8_t* rdram, recomp_context* ctx, ContextId ui_context) {
|
|
||||||
ResourceId resource = arg_resource_id<arg_index>(rdram, ctx);
|
|
||||||
|
|
||||||
if (resource == ResourceId::null()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
else if (resource == root_element_id) {
|
|
||||||
return ui_context.get_root_element();
|
|
||||||
}
|
|
||||||
|
|
||||||
return resource.as_element();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int arg_index>
|
|
||||||
Style* arg_style(uint8_t* rdram, recomp_context* ctx) {
|
|
||||||
ResourceId resource = arg_resource_id<arg_index>(rdram, ctx);
|
|
||||||
|
|
||||||
if (resource == ResourceId::null()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
else if (resource == root_element_id) {
|
|
||||||
ContextId ui_context = recompui::get_current_context();
|
|
||||||
return ui_context.get_root_element();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int arg_index>
|
|
||||||
Color arg_color(uint8_t* rdram, recomp_context* ctx) {
|
|
||||||
PTR(u8) color_arg = _arg<arg_index, PTR(u8)>(rdram, ctx);
|
|
||||||
|
|
||||||
Color ret{};
|
|
||||||
|
|
||||||
ret.r = MEM_B(0, color_arg);
|
|
||||||
ret.g = MEM_B(1, color_arg);
|
|
||||||
ret.b = MEM_B(2, color_arg);
|
|
||||||
ret.a = MEM_B(3, color_arg);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void return_resource(recomp_context* ctx, ResourceId resource) {
|
|
||||||
_return<uint32_t>(ctx, resource.slot_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void return_string(uint8_t* rdram, recomp_context* ctx, const std::string& ret) {
|
|
||||||
gpr addr = (reinterpret_cast<uint8_t*>(recomp::alloc(rdram, ret.size() + 1)) - rdram) + 0xFFFFFFFF80000000ULL;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < ret.size(); i++) {
|
|
||||||
MEM_B(i, addr) = ret[i];
|
|
||||||
}
|
|
||||||
MEM_B(ret.size(), addr) = '\x00';
|
|
||||||
|
|
||||||
_return<PTR(char)>(ctx, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
void recompui_create_context(uint8_t* rdram, recomp_context* ctx) {
|
void recompui_create_context(uint8_t* rdram, recomp_context* ctx) {
|
||||||
(void)rdram;
|
(void)rdram;
|
||||||
|
|
@ -915,4 +844,5 @@ void recompui::register_ui_exports() {
|
||||||
REGISTER_FUNC(recompui_get_input_text);
|
REGISTER_FUNC(recompui_get_input_text);
|
||||||
REGISTER_FUNC(recompui_set_input_text);
|
REGISTER_FUNC(recompui_set_input_text);
|
||||||
REGISTER_FUNC(recompui_register_callback);
|
REGISTER_FUNC(recompui_register_callback);
|
||||||
|
register_ui_image_exports();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
108
src/ui/ui_api_images.cpp
Normal file
108
src/ui/ui_api_images.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "recomp_ui.h"
|
||||||
|
#include "librecomp/overlays.hpp"
|
||||||
|
#include "librecomp/helpers.hpp"
|
||||||
|
#include "ultramodern/error_handling.hpp"
|
||||||
|
|
||||||
|
#include "ui_helpers.h"
|
||||||
|
#include "ui_api_images.h"
|
||||||
|
#include "elements/ui_image.h"
|
||||||
|
|
||||||
|
using namespace recompui;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
std::mutex mutex;
|
||||||
|
std::unordered_set<uint32_t> textures{};
|
||||||
|
uint32_t textures_created = 0;
|
||||||
|
} TextureState;
|
||||||
|
|
||||||
|
const std::string mod_texture_prefix = "?/mod_api/";
|
||||||
|
|
||||||
|
static std::string get_texture_name(uint32_t texture_id) {
|
||||||
|
return mod_texture_prefix + std::to_string(texture_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_new_texture_id() {
|
||||||
|
std::lock_guard lock{TextureState.mutex};
|
||||||
|
uint32_t cur_id = TextureState.textures_created++;
|
||||||
|
TextureState.textures.emplace(cur_id);
|
||||||
|
|
||||||
|
return cur_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void release_texture(uint32_t texture_id) {
|
||||||
|
std::string texture_name = get_texture_name(texture_id);
|
||||||
|
std::lock_guard lock{TextureState.mutex};
|
||||||
|
|
||||||
|
if (TextureState.textures.erase(texture_id) == 0) {
|
||||||
|
recompui::message_box("Fatal error in mod - attempted to destroy texture that doesn't exist!");
|
||||||
|
assert(false);
|
||||||
|
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
recompui::release_image(texture_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void recompui_create_texture_rgba32(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
thread_local std::vector<char> data;
|
||||||
|
PTR(void) data_in = _arg<0, PTR(void)>(rdram, ctx);
|
||||||
|
uint32_t width = _arg<1, uint32_t>(rdram, ctx);
|
||||||
|
uint32_t height = _arg<2, uint32_t>(rdram, ctx);
|
||||||
|
uint32_t cur_id = get_new_texture_id();
|
||||||
|
|
||||||
|
// The size in bytes of the image's pixel data.
|
||||||
|
size_t size_bytes = width * height * 4 * sizeof(uint8_t);
|
||||||
|
data.resize(size_bytes);
|
||||||
|
|
||||||
|
// Byteswap copy the pixel data.
|
||||||
|
for (size_t i = 0; i < size_bytes; i++) {
|
||||||
|
data[i] = MEM_B(i, data_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a texture name from the ID and queue its bytes.
|
||||||
|
std::string texture_name = get_texture_name(cur_id);
|
||||||
|
recompui::queue_image_from_bytes_rgba32(texture_name, data, width, height);
|
||||||
|
|
||||||
|
// Return the new texture ID.
|
||||||
|
_return(ctx, cur_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void recompui_destroy_texture(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
uint32_t texture_id = _arg<0, uint32_t>(rdram, ctx);
|
||||||
|
|
||||||
|
release_texture(texture_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void recompui_create_imageview(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
ContextId ui_context = get_context(rdram, ctx);
|
||||||
|
Element* parent = arg_element<1>(rdram, ctx, ui_context);
|
||||||
|
uint32_t texture_id = _arg<2, uint32_t>(rdram, ctx);
|
||||||
|
|
||||||
|
Element* ret = ui_context.create_element<Image>(parent, get_texture_name(texture_id));
|
||||||
|
return_resource(ctx, ret->get_resource_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
void recompui_set_imageview_texture(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
Style* resource = arg_style<0>(rdram, ctx);
|
||||||
|
uint32_t texture_id = _arg<1, uint32_t>(rdram, ctx);
|
||||||
|
|
||||||
|
if (!resource->is_element()) {
|
||||||
|
recompui::message_box("Fatal error in mod - attempted to set texture of non-element");
|
||||||
|
assert(false);
|
||||||
|
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
Element* element = static_cast<Element*>(resource);
|
||||||
|
element->set_src(get_texture_name(texture_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define REGISTER_FUNC(name) recomp::overlays::register_base_export(#name, name)
|
||||||
|
|
||||||
|
void recompui::register_ui_image_exports() {
|
||||||
|
REGISTER_FUNC(recompui_create_texture_rgba32);
|
||||||
|
REGISTER_FUNC(recompui_destroy_texture);
|
||||||
|
REGISTER_FUNC(recompui_create_imageview);
|
||||||
|
REGISTER_FUNC(recompui_set_imageview_texture);
|
||||||
|
}
|
||||||
10
src/ui/ui_api_images.h
Normal file
10
src/ui/ui_api_images.h
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef __UI_API_IMAGES_H__
|
||||||
|
#define __UI_API_IMAGES_H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace recompui {
|
||||||
|
void register_ui_image_exports();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
87
src/ui/ui_helpers.h
Normal file
87
src/ui/ui_helpers.h
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
#ifndef __UI_HELPERS_H__
|
||||||
|
#define __UI_HELPERS_H__
|
||||||
|
|
||||||
|
#include "librecomp/helpers.hpp"
|
||||||
|
#include "librecomp/addresses.hpp"
|
||||||
|
|
||||||
|
#include "elements/ui_element.h"
|
||||||
|
#include "elements/ui_types.h"
|
||||||
|
#include "core/ui_context.h"
|
||||||
|
#include "core/ui_resource.h"
|
||||||
|
|
||||||
|
namespace recompui {
|
||||||
|
|
||||||
|
constexpr ResourceId root_element_id{ 0xFFFFFFFE };
|
||||||
|
|
||||||
|
inline ContextId get_context(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
uint32_t context_id = _arg<0, uint32_t>(rdram, ctx);
|
||||||
|
return ContextId{ .slot_id = context_id };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int arg_index>
|
||||||
|
ResourceId arg_resource_id(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
uint32_t slot_id = _arg<arg_index, uint32_t>(rdram, ctx);
|
||||||
|
|
||||||
|
return ResourceId{ .slot_id = slot_id };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int arg_index>
|
||||||
|
Element* arg_element(uint8_t* rdram, recomp_context* ctx, ContextId ui_context) {
|
||||||
|
ResourceId resource = arg_resource_id<arg_index>(rdram, ctx);
|
||||||
|
|
||||||
|
if (resource == ResourceId::null()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else if (resource == root_element_id) {
|
||||||
|
return ui_context.get_root_element();
|
||||||
|
}
|
||||||
|
|
||||||
|
return resource.as_element();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int arg_index>
|
||||||
|
Style* arg_style(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
ResourceId resource = arg_resource_id<arg_index>(rdram, ctx);
|
||||||
|
|
||||||
|
if (resource == ResourceId::null()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else if (resource == root_element_id) {
|
||||||
|
ContextId ui_context = recompui::get_current_context();
|
||||||
|
return ui_context.get_root_element();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int arg_index>
|
||||||
|
Color arg_color(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
PTR(u8) color_arg = _arg<arg_index, PTR(u8)>(rdram, ctx);
|
||||||
|
|
||||||
|
Color ret{};
|
||||||
|
|
||||||
|
ret.r = MEM_B(0, color_arg);
|
||||||
|
ret.g = MEM_B(1, color_arg);
|
||||||
|
ret.b = MEM_B(2, color_arg);
|
||||||
|
ret.a = MEM_B(3, color_arg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void return_resource(recomp_context* ctx, ResourceId resource) {
|
||||||
|
_return<uint32_t>(ctx, resource.slot_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void return_string(uint8_t* rdram, recomp_context* ctx, const std::string& ret) {
|
||||||
|
gpr addr = (reinterpret_cast<uint8_t*>(recomp::alloc(rdram, ret.size() + 1)) - rdram) + 0xFFFFFFFF80000000ULL;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ret.size(); i++) {
|
||||||
|
MEM_B(i, addr) = ret[i];
|
||||||
|
}
|
||||||
|
MEM_B(ret.size(), addr) = '\x00';
|
||||||
|
|
||||||
|
_return<PTR(char)>(ctx, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -441,7 +441,7 @@ void ModMenu::create_mod_list() {
|
||||||
const std::vector<char> &thumbnail = recomp::mods::get_mod_thumbnail(mod_details[mod_index].mod_id);
|
const std::vector<char> &thumbnail = recomp::mods::get_mod_thumbnail(mod_details[mod_index].mod_id);
|
||||||
std::string thumbnail_name = generate_thumbnail_src_for_mod(mod_details[mod_index].mod_id);
|
std::string thumbnail_name = generate_thumbnail_src_for_mod(mod_details[mod_index].mod_id);
|
||||||
if (!thumbnail.empty()) {
|
if (!thumbnail.empty()) {
|
||||||
recompui::queue_image_from_bytes(thumbnail_name, thumbnail);
|
recompui::queue_image_from_bytes_file(thumbnail_name, thumbnail);
|
||||||
loaded_thumbnails.emplace(thumbnail_name);
|
loaded_thumbnails.emplace(thumbnail_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,19 @@ T from_bytes_le(const char* input) {
|
||||||
return *reinterpret_cast<const T*>(input);
|
return *reinterpret_cast<const T*>(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::pair<std::string, std::vector<char>> ImageFromBytes;
|
enum class ImageType {
|
||||||
|
File,
|
||||||
|
RGBA32
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ImageFromBytes {
|
||||||
|
ImageType type;
|
||||||
|
// Dimensions only used for RGBA32 data. Files pull the size from the file data.
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
std::string name;
|
||||||
|
std::vector<char> bytes;
|
||||||
|
};
|
||||||
|
|
||||||
namespace recompui {
|
namespace recompui {
|
||||||
class RmlRenderInterface_RT64_impl : public Rml::RenderInterfaceCompatibility {
|
class RmlRenderInterface_RT64_impl : public Rml::RenderInterfaceCompatibility {
|
||||||
|
|
@ -138,7 +150,7 @@ class RmlRenderInterface_RT64_impl : public Rml::RenderInterfaceCompatibility {
|
||||||
bool scissor_enabled_ = false;
|
bool scissor_enabled_ = false;
|
||||||
std::vector<std::unique_ptr<RT64::RenderBuffer>> stale_buffers_{};
|
std::vector<std::unique_ptr<RT64::RenderBuffer>> stale_buffers_{};
|
||||||
moodycamel::ConcurrentQueue<ImageFromBytes> image_from_bytes_queue;
|
moodycamel::ConcurrentQueue<ImageFromBytes> image_from_bytes_queue;
|
||||||
std::unordered_map<std::string, std::vector<char>> image_from_bytes_map;
|
std::unordered_map<std::string, ImageFromBytes> image_from_bytes_map;
|
||||||
public:
|
public:
|
||||||
RmlRenderInterface_RT64_impl(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
RmlRenderInterface_RT64_impl(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||||
interface_ = interface;
|
interface_ = interface;
|
||||||
|
|
@ -415,11 +427,30 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This data copy can be avoided when RT64::TextureCache::loadTextureFromBytes's function is updated to only take a pointer and size as the input.
|
RT64::Texture* texture = nullptr;
|
||||||
std::vector<uint8_t> data_copy(it->second.data(), it->second.data() + it->second.size());
|
|
||||||
std::unique_ptr<RT64::RenderBuffer> texture_buffer;
|
std::unique_ptr<RT64::RenderBuffer> texture_buffer;
|
||||||
|
ImageFromBytes& img = it->second;
|
||||||
copy_command_list_->begin();
|
copy_command_list_->begin();
|
||||||
RT64::Texture *texture = RT64::TextureCache::loadTextureFromBytes(device_, copy_command_list_.get(), data_copy, texture_buffer);
|
|
||||||
|
switch (img.type) {
|
||||||
|
case ImageType::RGBA32:
|
||||||
|
{
|
||||||
|
// Read the image header (two 32-bit values for width and height respectively).
|
||||||
|
uint32_t rowPitch = img.width * 4;
|
||||||
|
size_t byteCount = img.height * rowPitch;
|
||||||
|
texture = new RT64::Texture();
|
||||||
|
RT64::TextureCache::setRGBA32(texture, device_, copy_command_list_.get(), reinterpret_cast<const uint8_t*>(img.bytes.data()), byteCount, img.width, img.height, rowPitch, texture_buffer, nullptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ImageType::File:
|
||||||
|
{
|
||||||
|
// TODO: This data copy can be avoided when RT64::TextureCache::loadTextureFromBytes's function is updated to only take a pointer and size as the input.
|
||||||
|
std::vector<uint8_t> data_copy(img.bytes.data(), img.bytes.data() + img.bytes.size());
|
||||||
|
texture = RT64::TextureCache::loadTextureFromBytes(device_, copy_command_list_.get(), data_copy, texture_buffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
copy_command_list_->end();
|
copy_command_list_->end();
|
||||||
copy_command_queue_->executeCommandLists(copy_command_list_.get(), copy_command_fence_.get());
|
copy_command_queue_->executeCommandLists(copy_command_list_.get(), copy_command_fence_.get());
|
||||||
copy_command_queue_->waitForCommandFence(copy_command_fence_.get());
|
copy_command_queue_->waitForCommandFence(copy_command_fence_.get());
|
||||||
|
|
@ -626,14 +657,21 @@ public:
|
||||||
list_ = nullptr;
|
list_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void queue_image_from_bytes(const std::string &src, const std::vector<char> &bytes) {
|
void queue_image_from_bytes_file(const std::string &src, const std::vector<char> &bytes) {
|
||||||
image_from_bytes_queue.enqueue(ImageFromBytes(src, bytes));
|
// Width and height aren't used for file images, so set them to 0.
|
||||||
|
image_from_bytes_queue.enqueue(ImageFromBytes(ImageType::File, 0, 0, src, bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_image_from_bytes_rgba32(const std::string &src, const std::vector<char> &bytes, uint32_t width, uint32_t height) {
|
||||||
|
image_from_bytes_queue.enqueue(ImageFromBytes(ImageType::RGBA32, width, height, src, bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush_image_from_bytes_queue() {
|
void flush_image_from_bytes_queue() {
|
||||||
ImageFromBytes image_from_bytes;
|
ImageFromBytes image_from_bytes;
|
||||||
while (image_from_bytes_queue.try_dequeue(image_from_bytes)) {
|
while (image_from_bytes_queue.try_dequeue(image_from_bytes)) {
|
||||||
image_from_bytes_map.emplace(image_from_bytes.first, std::move(image_from_bytes.second));
|
// We can move the name into the map since the name in the actual entry is no longer needed.
|
||||||
|
// After that, move the entry itself into the map.
|
||||||
|
image_from_bytes_map.emplace(std::move(image_from_bytes.name), std::move(image_from_bytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -669,8 +707,14 @@ void recompui::RmlRenderInterface_RT64::end(RT64::RenderCommandList* list, RT64:
|
||||||
impl->end(list, framebuffer);
|
impl->end(list, framebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void recompui::RmlRenderInterface_RT64::queue_image_from_bytes(const std::string &src, const std::vector<char> &bytes) {
|
void recompui::RmlRenderInterface_RT64::queue_image_from_bytes_file(const std::string &src, const std::vector<char> &bytes) {
|
||||||
assert(static_cast<bool>(impl));
|
assert(static_cast<bool>(impl));
|
||||||
|
|
||||||
impl->queue_image_from_bytes(src, bytes);
|
impl->queue_image_from_bytes_file(src, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void recompui::RmlRenderInterface_RT64::queue_image_from_bytes_rgba32(const std::string &src, const std::vector<char> &bytes, uint32_t width, uint32_t height) {
|
||||||
|
assert(static_cast<bool>(impl));
|
||||||
|
|
||||||
|
impl->queue_image_from_bytes_rgba32(src, bytes, width, height);
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define __UI_RENDERER_H__
|
#define __UI_RENDERER_H__
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include "recomp_ui.h"
|
||||||
|
|
||||||
namespace RT64 {
|
namespace RT64 {
|
||||||
struct RenderInterface;
|
struct RenderInterface;
|
||||||
|
|
@ -29,7 +30,8 @@ namespace recompui {
|
||||||
|
|
||||||
void start(RT64::RenderCommandList* list, int image_width, int image_height);
|
void start(RT64::RenderCommandList* list, int image_width, int image_height);
|
||||||
void end(RT64::RenderCommandList* list, RT64::RenderFramebuffer* framebuffer);
|
void end(RT64::RenderCommandList* list, RT64::RenderFramebuffer* framebuffer);
|
||||||
void queue_image_from_bytes(const std::string &src, const std::vector<char> &bytes);
|
void queue_image_from_bytes_file(const std::string &src, const std::vector<char> &bytes);
|
||||||
|
void queue_image_from_bytes_rgba32(const std::string &src, const std::vector<char> &bytes, uint32_t width, uint32_t height);
|
||||||
};
|
};
|
||||||
} // namespace recompui
|
} // namespace recompui
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -822,8 +822,12 @@ Rml::ElementDocument* recompui::create_empty_document() {
|
||||||
return ui_state->context->CreateDocument();
|
return ui_state->context->CreateDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
void recompui::queue_image_from_bytes(const std::string &src, const std::vector<char> &bytes) {
|
void recompui::queue_image_from_bytes_file(const std::string &src, const std::vector<char> &bytes) {
|
||||||
ui_state->render_interface.queue_image_from_bytes(src, bytes);
|
ui_state->render_interface.queue_image_from_bytes_file(src, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void recompui::queue_image_from_bytes_rgba32(const std::string &src, const std::vector<char> &bytes, uint32_t width, uint32_t height) {
|
||||||
|
ui_state->render_interface.queue_image_from_bytes_rgba32(src, bytes, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void recompui::release_image(const std::string &src) {
|
void recompui::release_image(const std::string &src) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue