Files
oboe/src/gfx/render_image.cpp
Celtic Minstrel 5cfc6ba328 Fix all the compile warnings that occur on Mac.
(Except the OpenGL deprecation warning and some warnings coming from Boost.Process.)
2025-03-08 20:43:04 -05:00

181 lines
6.7 KiB
C++

/*
* graphtool.cpp
* BoE
*
* Created by Celtic Minstrel on 16/04/09.
*
*/
#include "render_image.hpp"
#include <iostream>
#include <fstream>
#include <boost/filesystem/path.hpp>
#include "fileio/fileio.hpp"
#include "gfx/render_shapes.hpp"
#include "gfx/render_text.hpp"
#include "winutil.hpp"
sf::Shader maskShader;
extern fs::path progDir;
void init_shaders() {
fs::path shaderPath = progDir/"data"/"shaders";
fs::path fragPath = shaderPath/"mask.frag", vertPath = shaderPath/"mask.vert";
do {
std::ifstream fin;
fin.open(fragPath.string().c_str());
if(!fin.good()) {
std::cerr << std_fmterr << ": Error loading fragment shader" << fragPath << std::endl;
break;
}
fin.seekg(0, std::ios::end);
int size = fin.tellg();
fin.seekg(0);
char* fbuf = new char[size + 1];
fbuf[size] = 0;
fin.read(fbuf, size);
fbuf[fin.gcount()] = 0;
fin.close();
fin.open(vertPath.string().c_str());
if(!fin.good()) {
std::cerr << std_fmterr << ": Error loading vertex shader" << vertPath << std::endl;
delete[] fbuf;
break;
}
fin.seekg(0, std::ios::end);
size = fin.tellg();
fin.seekg(0);
char* vbuf = new char[size + 1];
vbuf[size] = 0;
fin.read(vbuf, size);
vbuf[fin.gcount()] = 0;
if(!maskShader.loadFromMemory(vbuf, fbuf)) {
std::cerr << "Error: Failed to load shaders from " << shaderPath << "\nVertex:\n" << vbuf << "\nFragment:\n" << fbuf << std::endl;
}
delete[] fbuf;
delete[] vbuf;
} while(false);
}
void draw_splash(const sf::Texture& splash, sf::RenderWindow& targ, rectangle dest_rect) {
rectangle from_rect = rectangle(splash);
targ.clear(sf::Color::Black);
rect_draw_some_item(splash, from_rect, targ, dest_rect);
targ.display();
}
static void rect_draw_some_item(const sf::Texture& src_gworld,rectangle src_rect,sf::RenderTarget& targ_gworld,rectangle targ_rect,sf::RenderStates mode);
void rect_draw_some_item(sf::RenderTarget& targ_gworld,rectangle targ_rect) {
fill_rect(targ_gworld, targ_rect, sf::Color::Black);
}
void rect_draw_some_item(const sf::Texture& src_gworld,rectangle src_rect,sf::RenderTarget& targ_gworld,rectangle targ_rect,sf::BlendMode mode){
rect_draw_some_item(src_gworld, src_rect, targ_gworld, targ_rect, sf::RenderStates(mode));
}
// I added this because I tried using clip_rect to fix missiles/booms and it didn't work.
void rect_draw_some_item(const sf::Texture& src_gworld,rectangle src_rect,sf::RenderTarget& targ_gworld,rectangle targ_rect,rectangle in_frame,sf::BlendMode mode){
rectangle targ_clipped = targ_rect & in_frame;
if(targ_clipped.empty()) return;
rectangle src_clipped = src_rect;
src_clipped.top += (targ_clipped.top - targ_rect.top);
src_clipped.left += (targ_clipped.left - targ_rect.left);
src_clipped.bottom += (targ_clipped.bottom - targ_rect.bottom);
src_clipped.right += (targ_clipped.right - targ_rect.right);
rect_draw_some_item(src_gworld, src_rect, targ_gworld, targ_clipped, sf::RenderStates(mode));
}
void rect_draw_some_item(const sf::Texture& src_gworld,rectangle src_rect,sf::RenderTarget& targ_gworld,rectangle targ_rect,sf::RenderStates mode) {
rectangle src_gworld_rect(src_gworld), targ_gworld_rect(targ_gworld);
src_rect &= src_gworld_rect;
targ_rect &= targ_gworld_rect;
if(src_rect.empty() || targ_rect.empty()) return;
setActiveRenderTarget(targ_gworld);
sf::Sprite tile(src_gworld, src_rect);
tile.setPosition(targ_rect.left, targ_rect.top);
double xScale = targ_rect.width(), yScale = targ_rect.height();
xScale /= src_rect.width();
yScale /= src_rect.height();
tile.setScale(xScale, yScale);
targ_gworld.draw(tile, mode);
}
void rect_draw_some_item(const sf::Texture& src_gworld,rectangle src_rect,const sf::Texture& mask_gworld,sf::RenderTarget& targ_gworld,rectangle targ_rect) {
static sf::RenderTexture src;
static bool inited = false;
if(!inited || src_rect.width() != src.getSize().x || src_rect.height() != src.getSize().y) {
src.create(src_rect.width(), src_rect.height());
inited = true;
}
rectangle dest_rect = src_rect;
dest_rect.offset(-dest_rect.left,-dest_rect.top);
rect_draw_some_item(src_gworld, src_rect, src, dest_rect);
src.display();
maskShader.setParameter("texture", sf::Shader::CurrentTexture);
maskShader.setParameter("mask", mask_gworld);
rect_draw_some_item(src.getTexture(), dest_rect, targ_gworld, targ_rect, &maskShader);
}
std::map<sf::RenderTexture*,std::vector<ScaleAwareText>> store_scale_aware_text;
std::map<sf::RenderTexture*,rectangle> store_clip_rects;
static const bool DEBUG_SCALE_AWARE_TEXT = false;
static void draw_stored_scale_aware_text(sf::RenderTexture& texture, sf::RenderTarget& dest_window, rectangle targ_rect) {
// Temporarily switch target window to its unscaled view to draw scale-aware text
sf::View scaled_view = dest_window.getView();
sf::Vector2f scaled_top_left = scaled_view_top_left(dest_window, scaled_view);
dest_window.setView(dest_window.getDefaultView());
std::vector<ScaleAwareText> stored_text = store_scale_aware_text[&texture];
for(ScaleAwareText text : stored_text){
sf::Text str_to_draw = text.text;
if(!text.clip_rect.empty()){
rectangle rect = text.clip_rect;
rect.offset(targ_rect.left, targ_rect.top);
rect.top *= get_ui_scale();
rect.left *= get_ui_scale();
rect.bottom *= get_ui_scale();
rect.right *= get_ui_scale();
rect.offset(scaled_top_left.x, scaled_top_left.y);
// For debugging:
if(DEBUG_SCALE_AWARE_TEXT)
frame_rect(dest_window, rect, Colours::RED);
clip_rect(dest_window, rect);
}
sf::Vector2f position = str_to_draw.getPosition();
position = position + sf::Vector2f {0.0f+targ_rect.left, 0.0f+targ_rect.top};
position *= (float)get_ui_scale();
str_to_draw.setPosition(position + scaled_top_left);
dest_window.draw(str_to_draw);
if(!text.clip_rect.empty())
undo_clip(dest_window);
}
dest_window.setView(scaled_view);
}
void rect_draw_some_item(sf::RenderTexture& src_render_gworld,rectangle src_rect,sf::RenderTarget& targ_gworld,rectangle targ_rect,sf::BlendMode mode) {
rect_draw_some_item(src_render_gworld.getTexture(), src_rect, targ_gworld, targ_rect, mode);
draw_stored_scale_aware_text(src_render_gworld, targ_gworld, targ_rect);
}
void rect_draw_some_item(sf::RenderTexture& src_render_gworld,rectangle src_rect,const sf::Texture& mask_gworld,sf::RenderTarget& targ_gworld,rectangle targ_rect) {
rect_draw_some_item(src_render_gworld.getTexture(), src_rect, mask_gworld, targ_gworld, targ_rect);
draw_stored_scale_aware_text(src_render_gworld, targ_gworld, targ_rect);
}
void setActiveRenderTarget(sf::RenderTarget& where) {
const std::type_info& type = typeid(where);
if(type == typeid(sf::RenderWindow&))
dynamic_cast<sf::RenderWindow&>(where).setActive();
else if(type == typeid(sf::RenderTexture&))
dynamic_cast<sf::RenderTexture&>(where).setActive();
else throw std::bad_cast();
}