Compare commits
No commits in common. "b8f041584fd5f863d37a344eab47ea62b02f22be" and "87296180eead0ccdd4e98547961b2b550067eef4" have entirely different histories.
b8f041584f
...
87296180ee
2
dependencies/imgui
vendored
2
dependencies/imgui
vendored
@ -1 +1 @@
|
||||
Subproject commit 7b6314f47d2aaa3758cfeeca66af34f5c9309ca4
|
||||
Subproject commit 271910e3495e686a252b4b85369dec0605ba0d20
|
||||
2
dependencies/resource_embedder
vendored
2
dependencies/resource_embedder
vendored
@ -1 +1 @@
|
||||
Subproject commit e062aba71a93f4504180d1a4037b1849c95ba51d
|
||||
Subproject commit b921791be512bffc252ab555e47d48e0fb8261b5
|
||||
@ -20,9 +20,7 @@ f32 MainWindow::getDPI(){
|
||||
return dpi;
|
||||
}
|
||||
|
||||
void MainWindow::open(const char* window_title, UpdatingFunc _update){
|
||||
update = _update;
|
||||
|
||||
void MainWindow::init(const char* window_title){
|
||||
SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING));
|
||||
SDL_version v;
|
||||
SDL_GetVersion(&v);
|
||||
@ -78,9 +76,9 @@ void MainWindow::open(const char* window_title, UpdatingFunc _update){
|
||||
}
|
||||
|
||||
// Wait, poll and handle events (inputs, window resize, etc.)
|
||||
void MainWindow::poll_events(bool waitForEvent){
|
||||
void MainWindow::poll_events(u16& frame_updates_requested, bool wait){
|
||||
SDL_Event event;
|
||||
if(waitForEvent){
|
||||
if(wait){
|
||||
// waits for first event in cpu-efficient way
|
||||
SDL_TRY(SDL_WaitEvent(&event) != 1);
|
||||
}
|
||||
@ -89,7 +87,8 @@ void MainWindow::poll_events(bool waitForEvent){
|
||||
return;
|
||||
|
||||
do {
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
if(ImGui_ImplSDL2_ProcessEvent(&event))
|
||||
frame_updates_requested=2;
|
||||
switch(event.type){
|
||||
case SDL_QUIT: {
|
||||
close();
|
||||
@ -160,45 +159,62 @@ void MainWindow::draw_frame(){
|
||||
SDL_SetRenderDrawColor(sdl_renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255));
|
||||
SDL_RenderClear(sdl_renderer);
|
||||
|
||||
// Example sprite
|
||||
//Resources::Texture tutel(Resources::getResource("tutel.png"), sdl_renderer);
|
||||
static Resources::CacheStorage<Resources::Texture> textures;
|
||||
Resources::Texture& tutel = textures.getOrCreate("tutel.png", sdl_renderer);
|
||||
tutel.render(SDL_FRectConstruct(100, 100, 400, 400));
|
||||
// Resources::getCached
|
||||
Resources::Texture sprite(sdl_renderer);
|
||||
sprite.loadFrom(Resources::getResource("tutel.png"));
|
||||
sprite.render(SDL_FRectConstruct(100, 100, 400, 400));
|
||||
|
||||
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), sdl_renderer);
|
||||
// Swap buffers
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
}
|
||||
|
||||
void MainWindow::startUpdateLoop(){
|
||||
void MainWindow::startAndWait(){
|
||||
if(loop_running)
|
||||
throw UsefulException("loop is running already");
|
||||
throw UsefulException("loop is already running");
|
||||
|
||||
nsec_t prev_update_time_ns = getMonotonicTimeNsec();
|
||||
// draw first frame
|
||||
draw_frame();
|
||||
|
||||
u16 frame_updates_requested=1;
|
||||
u64 prev_update_time_ms=SDL_GetTicks64();
|
||||
loop_running=true;
|
||||
// main loop
|
||||
while(loop_running){
|
||||
poll_events(false);
|
||||
// waits for events
|
||||
main_loop_wait_for_input = false;
|
||||
poll_events(frame_updates_requested, main_loop_wait_for_input);
|
||||
|
||||
nsec_t update_time_ns = getMonotonicTimeNsec();
|
||||
if(update_time_ns < prev_update_time_ns)
|
||||
throw UsefulException("monotonic clock returned unexpected value");
|
||||
f64 delta_time_s = (f64)(update_time_ns - prev_update_time_ns) / 1e9;
|
||||
prev_update_time_ns = update_time_ns;
|
||||
if(frame_updates_requested==0)
|
||||
{
|
||||
u64 update_time_ms=SDL_GetTicks64();
|
||||
if(update_time_ms >= prev_update_time_ms + 1000/fps_min){
|
||||
// if frame rate < fps_min then requests frame draw
|
||||
// works only if main_loop_wait_for_input = false
|
||||
frame_updates_requested=1;
|
||||
prev_update_time_ms=update_time_ms;
|
||||
}
|
||||
else {
|
||||
// skips frame rendering and waits to limit fps
|
||||
u32 frame_delay_ms=1000/fps_max;
|
||||
SDL_Delay(frame_delay_ms);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
update(delta_time_s);
|
||||
// deaws requested number of frames
|
||||
while(frame_updates_requested>0) {
|
||||
draw_frame();
|
||||
|
||||
nsec_t after_update_time_ns = getMonotonicTimeNsec();
|
||||
nsec_t frame_delay_ns = (nsec_t)1e9 / fps_max - (after_update_time_ns - update_time_ns);
|
||||
if(frame_delay_ns > 0){
|
||||
std::cout<<"frameDelay: "<<frame_delay_ns / 1e9f<<std::endl;
|
||||
SDL_Delay(frame_delay_ns / 1e6);
|
||||
frame_updates_requested--;
|
||||
}
|
||||
}
|
||||
|
||||
destroy();
|
||||
// Cleanup
|
||||
MainWindow::destroy();
|
||||
}
|
||||
|
||||
void MainWindow::close(){
|
||||
loop_running=false;
|
||||
}
|
||||
|
||||
void MainWindow::destroy(){
|
||||
@ -210,10 +226,6 @@ void MainWindow::destroy(){
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void MainWindow::close(){
|
||||
loop_running = false;
|
||||
}
|
||||
|
||||
void MainWindow::draw_bg_window(){
|
||||
const ImGuiDockNodeFlags dockspace_flags =
|
||||
ImGuiDockNodeFlags_PassthruCentralNode;
|
||||
@ -280,9 +292,10 @@ void MainWindow::draw_bg_window(){
|
||||
|
||||
void MainWindow::draw_debug_window(){
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui::Begin("Debug Options");
|
||||
ImGui::ColorEdit3("clear_color", (float*)&clear_color);
|
||||
ImGui::InputInt("fps_max", &fps_max);
|
||||
ImGui::Checkbox("main_loop_wait_for_input", &main_loop_wait_for_input);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.2f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window);
|
||||
ImGui::Checkbox("Metrics/Debug Window", &show_metrics_window);
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#include <SDL.h>
|
||||
#include <imgui.h>
|
||||
#include "../std.hpp"
|
||||
#include "../time.hpp"
|
||||
|
||||
/// converts hex color to float vector
|
||||
#define RGBAHexToF(R8,G8,B8,A8) ImVec4(((u8)35)/255.0f, ((u8)35)/255.0f, ((u8)50)/255.0f, ((u8)255)/255.0f)
|
||||
@ -14,32 +13,30 @@ namespace ougge::GUI {
|
||||
|
||||
#define default_font "DroidSans"
|
||||
|
||||
using UpdatingFunc = void (*)(f64 deltaTime);
|
||||
|
||||
class MainWindow {
|
||||
public:
|
||||
ImVec4 clear_color = RGBAHexToF(35,35,50,255);
|
||||
f32 default_font_size = 14.0f;
|
||||
int fps_max = 30;
|
||||
// called on each frame
|
||||
UpdatingFunc update = nullptr;
|
||||
u8 fps_min = 30;
|
||||
u8 fps_max = 60;
|
||||
|
||||
private:
|
||||
bool loop_running = false;
|
||||
bool loop_running=false;
|
||||
bool main_loop_wait_for_input=true;
|
||||
bool show_demo_window = false;
|
||||
bool show_metrics_window = false;
|
||||
SDL_Window* sdl_window = nullptr;
|
||||
SDL_Renderer* sdl_renderer = nullptr;
|
||||
|
||||
public:
|
||||
void open(const char* window_title, UpdatingFunc update);
|
||||
void startUpdateLoop();
|
||||
void init(const char* window_title);
|
||||
void startAndWait();
|
||||
void close();
|
||||
f32 getDPI();
|
||||
|
||||
private:
|
||||
void destroy();
|
||||
f32 getDPI();
|
||||
void poll_events(bool waitForEvent);
|
||||
void poll_events(u16& frame_updates_requested, bool wait);
|
||||
void draw_frame();
|
||||
void draw_ui();
|
||||
void draw_debug_window();
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include <unordered_map>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "../exceptions.hpp"
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ougge::Resources {
|
||||
|
||||
@ -45,21 +43,4 @@ public:
|
||||
|
||||
Resource& getResource(const std::string& path);
|
||||
|
||||
/// @brief stores requested resources in memory
|
||||
/// @tparam T must implement constructor `T(const Resource&, ...)`
|
||||
template<class T>
|
||||
class CacheStorage {
|
||||
std::unordered_map<std::string, T> _map;
|
||||
|
||||
public:
|
||||
template<typename... TCtorArgs>
|
||||
T& getOrCreate(const std::string& name, TCtorArgs&&... ctor_args){
|
||||
auto it = _map.find(name);
|
||||
if(it != _map.end())
|
||||
return it->second;
|
||||
auto& res = getResource(name);
|
||||
auto e = _map.emplace(name, T(res, ctor_args...));
|
||||
return e.first->second;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -23,7 +23,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {
|
||||
const char* path;
|
||||
|
||||
@ -22,7 +22,7 @@ ImFont* ImFont_LoadFromResource(const std::string& font_name, f32 font_size, f32
|
||||
ImFontConfig font_cfg = ImFontConfig();
|
||||
std::sprintf(font_cfg.Name, "%s %ipx", font_name.c_str(), (i32)font_size);
|
||||
|
||||
auto& res = getResource("fonts/" + font_name + ".ttf");
|
||||
Resource& res = getResource("fonts/" + font_name + ".ttf");
|
||||
char* font_data = new char[res.size];
|
||||
res.openStream()->read(font_data, res.size);
|
||||
|
||||
|
||||
@ -4,20 +4,29 @@
|
||||
|
||||
namespace ougge::Resources {
|
||||
|
||||
Texture::Texture(const Resource& r, SDL_Renderer* renderer)
|
||||
: Texture(*r.openStream(), r.size, renderer)
|
||||
Texture::Texture(SDL_Renderer* renderer)
|
||||
: renderer(renderer), texture(nullptr), w(0), h(0)
|
||||
{}
|
||||
|
||||
Texture::Texture(std::istream& s, size_t size, SDL_Renderer* renderer)
|
||||
: renderer(renderer), texture(nullptr), w(0), h(0)
|
||||
{
|
||||
Texture::~Texture(){
|
||||
SDL_DestroyTexture(texture);
|
||||
}
|
||||
|
||||
void Texture::loadFrom(const Resource& r){
|
||||
auto s = r.openStream();
|
||||
loadFrom(*s, r.size);
|
||||
}
|
||||
|
||||
void Texture::loadFrom(std::istream& s, size_t size){
|
||||
if(texture)
|
||||
throw UsefulException("texture has been loaded already");
|
||||
SDL_RWops* sdl_stream = SDL_RWFromIStream(s, size);
|
||||
if(!sdl_stream)
|
||||
throw SDLException();
|
||||
texture = std::shared_ptr<SDL_Texture>(IMG_LoadTexture_RW(renderer, sdl_stream, 1), SDL_DestroyTexture);
|
||||
texture = IMG_LoadTexture_RW(renderer, sdl_stream, 1);
|
||||
if(!texture)
|
||||
throw IMGException();
|
||||
SDL_TRY(SDL_QueryTexture(texture.get(), nullptr, nullptr, &w, &h));
|
||||
SDL_TRY(SDL_QueryTexture(texture, nullptr, nullptr, &w, &h));
|
||||
}
|
||||
|
||||
SDL_RenderCopyExF_Params::SDL_RenderCopyExF_Params()
|
||||
@ -26,19 +35,19 @@ SDL_RenderCopyExF_Params::SDL_RenderCopyExF_Params()
|
||||
|
||||
void Texture::render(const SDL_FRect& target_section){
|
||||
SDL_TRY(
|
||||
SDL_RenderCopyF(renderer, texture.get(), nullptr, &target_section)
|
||||
SDL_RenderCopyF(renderer, texture, nullptr, &target_section)
|
||||
);
|
||||
}
|
||||
|
||||
void Texture::render(const SDL_FRect& target_section, const SDL_Rect& texture_section){
|
||||
SDL_TRY(
|
||||
SDL_RenderCopyF(renderer, texture.get(), &texture_section, &target_section)
|
||||
SDL_RenderCopyF(renderer, texture, &texture_section, &target_section)
|
||||
);
|
||||
}
|
||||
|
||||
void Texture::render(const SDL_RenderCopyExF_Params& p){
|
||||
SDL_TRY(
|
||||
SDL_RenderCopyExF(renderer, texture.get(),
|
||||
SDL_RenderCopyExF(renderer, texture,
|
||||
optional_value_ptr_or_null(p.texture_section),
|
||||
optional_value_ptr_or_null(p.target_section),
|
||||
p.rotation_angle,
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <SDL.h>
|
||||
#include "Resources.hpp"
|
||||
|
||||
@ -30,12 +29,15 @@ struct SDL_RenderCopyExF_Params {
|
||||
|
||||
struct Texture {
|
||||
SDL_Renderer* renderer;
|
||||
std::shared_ptr<SDL_Texture> texture;
|
||||
SDL_Texture* texture;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
Texture(const Resource& r, SDL_Renderer* renderer);
|
||||
Texture(std::istream& s, size_t size, SDL_Renderer* renderer);
|
||||
Texture(SDL_Renderer* renderer);
|
||||
~Texture();
|
||||
|
||||
void loadFrom(const Resource& r);
|
||||
void loadFrom(std::istream& s, size_t size);
|
||||
|
||||
void render(const SDL_FRect& target_section);
|
||||
void render(const SDL_FRect& target_section, const SDL_Rect& texture_section);
|
||||
|
||||
11
src/main.cpp
11
src/main.cpp
@ -8,16 +8,15 @@
|
||||
|
||||
using namespace ougge;
|
||||
|
||||
void update(f64 deltaTime){
|
||||
std::cout<<"deltaTime: "<<deltaTime<<std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, const char** argv){
|
||||
if(setlocale(LC_CTYPE, "C.UTF-8")!=0)
|
||||
std::cerr<<"\e[93msetlocale failed!\n";
|
||||
|
||||
try {
|
||||
Resources::init();
|
||||
GUI::MainWindow w;
|
||||
w.open("ougge", update);
|
||||
w.startUpdateLoop();
|
||||
w.init("ougge");
|
||||
w.startAndWait();
|
||||
}
|
||||
catch(const std::exception& e){
|
||||
std::cerr<<"Catched exception: "<<e.what()<<std::endl;
|
||||
|
||||
19
src/time.cpp
19
src/time.cpp
@ -1,19 +0,0 @@
|
||||
// posix version definition to use clock_gettime
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "time.hpp"
|
||||
#include <ctime>
|
||||
#include "UsefulException.hpp"
|
||||
|
||||
nsec_t getMonotonicTimeNsec(){
|
||||
struct timespec t;
|
||||
if(clock_gettime(CLOCK_MONOTONIC, &t) != 0)
|
||||
throw UsefulException("clock_gettime(CLOCK_MONOTONIC) error");
|
||||
return (nsec_t)t.tv_sec * 1e9 + (nsec_t)t.tv_nsec;
|
||||
}
|
||||
10
src/time.hpp
10
src/time.hpp
@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "std.hpp"
|
||||
|
||||
/// nanoseconds
|
||||
typedef i64 nsec_t;
|
||||
|
||||
/// can be used to measure delta time
|
||||
///@return time from some moment in nanoseconds.
|
||||
nsec_t getMonotonicTimeNsec();
|
||||
Loading…
Reference in New Issue
Block a user