I can now apply shaders to any GUI element, but I need a shader manager that will allow for hot reloading and tracking input/output variables.
This commit is contained in:
parent
80b4faf940
commit
a5b8e411e3
8 changed files with 121 additions and 16 deletions
2
Makefile
2
Makefile
|
@ -22,7 +22,7 @@ tracy_build:
|
||||||
meson compile -j 10 -C builddir
|
meson compile -j 10 -C builddir
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
./builddir/runtests "[combat-battle]"
|
./builddir/runtests
|
||||||
|
|
||||||
run: build test
|
run: build test
|
||||||
powershell "cp ./builddir/zedcaster.exe ."
|
powershell "cp ./builddir/zedcaster.exe ."
|
||||||
|
|
|
@ -15,9 +15,10 @@ namespace gui {
|
||||||
|
|
||||||
void CombatUI::make_button(std::string name, std::wstring label, Events::GUI event) {
|
void CombatUI::make_button(std::string name, std::wstring label, Events::GUI event) {
|
||||||
auto button = $gui.entity(name);
|
auto button = $gui.entity(name);
|
||||||
// $gui.set<Sprite>(button, {"leather_pouch-128"});
|
$gui.set<Sprite>(button, {"leather_pouch-128"});
|
||||||
$gui.set<Rectangle>(button, {});
|
// $gui.set<Rectangle>(button, {});
|
||||||
$gui.set<Label>(button, {label});
|
$gui.set<Label>(button, {label});
|
||||||
|
$gui.set<Shader>(button, {.duration=0.2f});
|
||||||
$gui.set<Clickable>(button,
|
$gui.set<Clickable>(button,
|
||||||
guecs::make_action(*$level.world, event));
|
guecs::make_action(*$level.world, event));
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,8 +72,8 @@ constexpr int COMBAT_UI_HEIGHT = SCREEN_HEIGHT - RAY_VIEW_HEIGHT;
|
||||||
constexpr wchar_t BG_TILE = L'█';
|
constexpr wchar_t BG_TILE = L'█';
|
||||||
constexpr wchar_t UI_BASE_CHAR = L'█';
|
constexpr wchar_t UI_BASE_CHAR = L'█';
|
||||||
constexpr int BG_BOX_OFFSET=5;
|
constexpr int BG_BOX_OFFSET=5;
|
||||||
constexpr const char *FONT_FILE_NAME="./assets/text.otf";
|
constexpr const char *FONT_FILE_NAME="assets/text.otf";
|
||||||
|
constexpr const char *DEFAULT_UI_SHADER = "shaders/ui_shader.frag";
|
||||||
|
|
||||||
constexpr std::array<std::wstring, 8> COMPASS{
|
constexpr std::array<std::wstring, 8> COMPASS{
|
||||||
// L"E", L"SE", L"S", L"SW", L"W", L"NW", L"N", L"NE"
|
// L"E", L"SE", L"S", L"SW", L"W", L"NW", L"N", L"NE"
|
||||||
|
|
60
guecs.cpp
60
guecs.cpp
|
@ -65,6 +65,33 @@ namespace guecs {
|
||||||
shape->setFillColor(color);
|
shape->setFillColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shader::init(lel::Cell &cell) {
|
||||||
|
ptr = std::make_shared<sf::Shader>();
|
||||||
|
bool good = ptr->loadFromFile(name, sf::Shader::Type::Fragment);
|
||||||
|
dbc::check(good, fmt::format("failed to load shader {}", name));
|
||||||
|
ptr->setUniform("u_resolution", sf::Vector2f({float(cell.w), float(cell.h)}));
|
||||||
|
|
||||||
|
clock = std::make_shared<sf::Clock>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::step() {
|
||||||
|
sf::Time u_time = clock->getElapsedTime();
|
||||||
|
float current_time = u_time.asSeconds();
|
||||||
|
|
||||||
|
if(current_time < u_time_end) {
|
||||||
|
ptr->setUniform("u_time", current_time);
|
||||||
|
} else {
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::run() {
|
||||||
|
active = true;
|
||||||
|
sf::Time u_time = clock->getElapsedTime();
|
||||||
|
u_time_end = u_time.asSeconds() + duration;
|
||||||
|
ptr->setUniform("u_duration", duration);
|
||||||
|
ptr->setUniform("u_time_end", u_time_end);
|
||||||
|
}
|
||||||
|
|
||||||
UI::UI() {
|
UI::UI() {
|
||||||
$font = make_shared<sf::Font>(FONT_FILE_NAME);
|
$font = make_shared<sf::Font>(FONT_FILE_NAME);
|
||||||
|
@ -114,6 +141,10 @@ namespace guecs {
|
||||||
rect.init(cell);
|
rect.init(cell);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$world.query<lel::Cell, Shader>([](auto, auto& cell, auto& shader) {
|
||||||
|
shader.init(cell);
|
||||||
|
});
|
||||||
|
|
||||||
$world.query<Rectangle, Meter>([](auto, auto& bg, auto &) {
|
$world.query<Rectangle, Meter>([](auto, auto& bg, auto &) {
|
||||||
bg.shape->setFillColor(ColorValue::BLACK);
|
bg.shape->setFillColor(ColorValue::BLACK);
|
||||||
});
|
});
|
||||||
|
@ -152,27 +183,31 @@ namespace guecs {
|
||||||
window.draw(*bg.shape);
|
window.draw(*bg.shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
$world.query<Rectangle>([&](auto, auto& rect) {
|
$world.query<Shader>([&](auto, auto& shader) {
|
||||||
window.draw(*rect.shape);
|
if(shader.active) shader.step();
|
||||||
});
|
});
|
||||||
|
|
||||||
$world.query<lel::Cell, Meter>([&](auto, auto& cell, const auto &meter) {
|
$world.query<Rectangle>([&](auto ent, auto& rect) {
|
||||||
|
render_helper(window, ent, true, rect.shape);
|
||||||
|
});
|
||||||
|
|
||||||
|
$world.query<lel::Cell, Meter>([&](auto ent, auto& cell, const auto &meter) {
|
||||||
float level = std::clamp(meter.percent, 0.0f, 1.0f) * float(cell.w);
|
float level = std::clamp(meter.percent, 0.0f, 1.0f) * float(cell.w);
|
||||||
// ZED: this 6 is a border width, make it a thing
|
// ZED: this 6 is a border width, make it a thing
|
||||||
meter.bar.shape->setSize({std::max(level, 0.0f), float(cell.h - 6)});
|
meter.bar.shape->setSize({std::max(level, 0.0f), float(cell.h - 6)});
|
||||||
window.draw(*meter.bar.shape);
|
render_helper(window, ent, true, meter.bar.shape);
|
||||||
});
|
});
|
||||||
|
|
||||||
$world.query<Sprite>([&](auto, auto& sprite) {
|
$world.query<Sprite>([&](auto ent, auto& sprite) {
|
||||||
window.draw(*sprite.sprite);
|
render_helper(window, ent, false, sprite.sprite);
|
||||||
});
|
});
|
||||||
|
|
||||||
$world.query<Label>([&](auto, auto& text) {
|
$world.query<Label>([&](auto ent, auto& text) {
|
||||||
window.draw(*text.text);
|
render_helper(window, ent, false, text.text);
|
||||||
});
|
});
|
||||||
|
|
||||||
$world.query<Textual>([&](auto, auto& text) {
|
$world.query<Textual>([&](auto ent, auto& text) {
|
||||||
window.draw(*text.text);
|
render_helper(window, ent, true, text.text);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +218,11 @@ namespace guecs {
|
||||||
if((x >= cell.x && x <= cell.x + cell.w) &&
|
if((x >= cell.x && x <= cell.x + cell.w) &&
|
||||||
(y >= cell.y && y <= cell.y + cell.h))
|
(y >= cell.y && y <= cell.y + cell.h))
|
||||||
{
|
{
|
||||||
|
if($world.has<Shader>(ent)) {
|
||||||
|
auto& shader = $world.get<Shader>(ent);
|
||||||
|
shader.run();
|
||||||
|
}
|
||||||
|
|
||||||
if(auto action_data = get_if<ActionData>(ent)) {
|
if(auto action_data = get_if<ActionData>(ent)) {
|
||||||
clicked.action(ent, action_data->data);
|
clicked.action(ent, action_data->data);
|
||||||
} else {
|
} else {
|
||||||
|
|
30
guecs.hpp
30
guecs.hpp
|
@ -81,6 +81,19 @@ namespace guecs {
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Shader {
|
||||||
|
float duration = 0.1f;
|
||||||
|
std::string name{DEFAULT_UI_SHADER};
|
||||||
|
float u_time_end = 0.0;
|
||||||
|
bool active = false;
|
||||||
|
std::shared_ptr<sf::Shader> ptr = nullptr;
|
||||||
|
std::shared_ptr<sf::Clock> clock = nullptr;
|
||||||
|
|
||||||
|
void init(lel::Cell &cell);
|
||||||
|
void run();
|
||||||
|
void step();
|
||||||
|
};
|
||||||
|
|
||||||
struct Background {
|
struct Background {
|
||||||
float x = 0.0f;
|
float x = 0.0f;
|
||||||
float y = 0.0f;
|
float y = 0.0f;
|
||||||
|
@ -178,6 +191,22 @@ namespace guecs {
|
||||||
remove<Comp>(ent);
|
remove<Comp>(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void render_helper(sf::RenderWindow& window, DinkyECS::Entity ent, bool is_shape, T& target) {
|
||||||
|
sf::Shader *shader_ptr = nullptr;
|
||||||
|
|
||||||
|
if($world.has<Shader>(ent)) {
|
||||||
|
auto& shader = $world.get<Shader>(ent);
|
||||||
|
|
||||||
|
if(shader.active) {
|
||||||
|
shader_ptr = shader.ptr.get();
|
||||||
|
shader_ptr->setUniform("is_shape", is_shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.draw(*target, shader_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void show_sprite(string region, string sprite_name);
|
void show_sprite(string region, string sprite_name);
|
||||||
void show_text(string region, wstring content);
|
void show_text(string region, wstring content);
|
||||||
void update_text(string region, wstring content);
|
void update_text(string region, wstring content);
|
||||||
|
@ -186,4 +215,5 @@ namespace guecs {
|
||||||
};
|
};
|
||||||
|
|
||||||
Clickable make_action(DinkyECS::World& target, Events::GUI event);
|
Clickable make_action(DinkyECS::World& target, Events::GUI event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,7 +393,7 @@ void Raycaster::update_level(GameLevel level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Raycaster::init_shaders() {
|
void Raycaster::init_shaders() {
|
||||||
dbc::check(sf::Shader::isAvailable(), "no shaders?!");
|
// dbc::check(sf::Shader::isAvailable(), "no shaders?!");
|
||||||
bool good = $brightness.loadFromFile("shaders/modal.frag", sf::Shader::Type::Fragment);
|
bool good = $brightness.loadFromFile("shaders/modal.frag", sf::Shader::Type::Fragment);
|
||||||
dbc::check(good, "shader could not be loaded");
|
dbc::check(good, "shader could not be loaded");
|
||||||
$brightness.setUniform("source", sf::Shader::CurrentTexture);
|
$brightness.setUniform("source", sf::Shader::CurrentTexture);
|
||||||
|
|
22
shaders/ui_shader.frag
Normal file
22
shaders/ui_shader.frag
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform vec2 u_mouse;
|
||||||
|
uniform float u_duration;
|
||||||
|
uniform float u_time;
|
||||||
|
uniform float u_time_end;
|
||||||
|
uniform sampler2D texture;
|
||||||
|
uniform bool is_shape;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
if(is_shape) {
|
||||||
|
float tick = (u_time_end - u_time) / u_duration;
|
||||||
|
float blink = smoothstep(1.0, 0.5, tick);
|
||||||
|
vec4 color = vec4(blink, blink, blink, 1.0);
|
||||||
|
gl_FragColor = gl_Color * color;
|
||||||
|
} else {
|
||||||
|
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
|
||||||
|
float tick = (u_time_end - u_time) / u_duration;
|
||||||
|
float blink = smoothstep(1.0, 0.5, tick);
|
||||||
|
vec4 color = vec4(blink, blink, blink, 1.0);
|
||||||
|
gl_FragColor = gl_Color * color * pixel;
|
||||||
|
}
|
||||||
|
}
|
12
shaders/ui_shape_shader.frag
Normal file
12
shaders/ui_shape_shader.frag
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform vec2 u_mouse;
|
||||||
|
uniform float u_duration;
|
||||||
|
uniform float u_time;
|
||||||
|
uniform float u_time_end;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float tick = (u_time_end - u_time) / u_duration;
|
||||||
|
float blink = smoothstep(1.0, 0.5, tick);
|
||||||
|
vec4 color = vec4(blink, blink, blink, 1.0);
|
||||||
|
gl_FragColor = gl_Color * color;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue