From 59bb164f4c706a59bf0643d86695dd129cdc4ace Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 8 Nov 2018 00:13:34 +0700 Subject: [PATCH] initialization all modules in engine --- headers/enduro2d/core/_core.hpp | 1 + headers/enduro2d/core/engine.hpp | 101 ++++++++- samples/sources/sample_00/sample_00.cpp | 206 +++++++++--------- samples/sources/sample_01/sample_01.cpp | 220 ++++++++++--------- samples/sources/sample_02/sample_02.cpp | 270 +++++++++++++----------- sources/enduro2d/core/engine.cpp | 247 +++++++++++++++++++++- 6 files changed, 711 insertions(+), 334 deletions(-) diff --git a/headers/enduro2d/core/_core.hpp b/headers/enduro2d/core/_core.hpp index 8a68e929..782a2dec 100644 --- a/headers/enduro2d/core/_core.hpp +++ b/headers/enduro2d/core/_core.hpp @@ -13,6 +13,7 @@ namespace e2d { class debug; + class application; class engine; class mouse; class keyboard; diff --git a/headers/enduro2d/core/engine.hpp b/headers/enduro2d/core/engine.hpp index 4ba89721..3e402553 100644 --- a/headers/enduro2d/core/engine.hpp +++ b/headers/enduro2d/core/engine.hpp @@ -10,9 +10,108 @@ namespace e2d { + // + // application + // + + class application : private noncopyable { + public: + virtual ~application() noexcept = default; + virtual bool initialize(); + virtual void shutdown() noexcept; + virtual bool frame_tick(); + }; + using application_uptr = std::unique_ptr; + + // + // bad_engine_operation + // + + class bad_engine_operation final : public exception { + public: + const char* what() const noexcept final { + return "bad engine operation"; + } + }; + + // + // engine + // + class engine final : public module { public: - engine(); + class debug_parameters { + public: + debug_parameters& log_filename(str_view value); + debug_parameters& file_logging(bool value) noexcept; + debug_parameters& console_logging(bool value) noexcept; + + const str& log_filename() const noexcept; + bool file_logging() const noexcept; + bool console_logging() const noexcept; + private: + str log_filename_{"log.txt"}; + bool file_logging_{true}; + bool console_logging_{true}; + }; + + class window_parameters { + public: + window_parameters& caption(str_view value); + window_parameters& size(const v2u& value) noexcept; + window_parameters& fullscreen(bool value) noexcept; + + const str& caption() const noexcept; + const v2u& size() const noexcept; + bool fullscreen() const noexcept; + private: + str caption_{"Enduro2D"}; + v2u size_{640, 480}; + bool fullscreen_{false}; + }; + + class parameters { + public: + parameters() = delete; + parameters(str_view game_name, str_view company_name); + + parameters& game_name(str_view value) noexcept; + parameters& company_name(str_view value) noexcept; + parameters& debug_params(const debug_parameters& value); + parameters& window_params(const window_parameters& value); + + str& game_name() noexcept; + str& company_name() noexcept; + debug_parameters& debug_params() noexcept; + window_parameters& window_params() noexcept; + + const str& game_name() const noexcept; + const str& company_name() const noexcept; + const debug_parameters& debug_params() const noexcept; + const window_parameters& window_params() const noexcept; + private: + str game_name_{"noname"}; + str company_name_{"noname"}; + debug_parameters debug_params_; + window_parameters window_params_; + }; + public: + engine(const parameters& params); ~engine() noexcept final; + + template < typename Application, typename... Args > + bool start(Args&&... args); + bool start(application_uptr app); + private: + class internal_state; + std::unique_ptr state_; }; } + +namespace e2d +{ + template < typename Application, typename... Args > + bool engine::start(Args&&... args) { + return start(std::make_unique(std::forward(args)...)); + } +} diff --git a/samples/sources/sample_00/sample_00.cpp b/samples/sources/sample_00/sample_00.cpp index 398875c1..64b8f8f4 100644 --- a/samples/sources/sample_00/sample_00.cpp +++ b/samples/sources/sample_00/sample_00.cpp @@ -89,106 +89,116 @@ namespace vertex2{color32::blue()}, vertex2{color32::yellow()}}; } + + class game final : public application { + public: + bool initialize() final { + the().register_scheme( + "piratepack", + the().open(url("resources://bin/kenney_piratepack.zip"))); + + the().register_scheme_alias( + "ships", + url("piratepack://PNG/Retina/Ships")); + + shader_ = the().create_shader( + vs_source_cstr, fs_source_cstr); + texture1_ = the().create_texture( + the().open(url("ships://ship (2).png"))); + texture2_ = the().create_texture( + the().open(url("ships://ship (19).png"))); + + if ( !shader_ || !texture1_ || !texture2_ ) { + return false; + } + + const auto indices = generate_quad_indices(); + index_buffer_ = the().create_index_buffer( + buffer(indices.data(), indices.size() * sizeof(indices[0])), + index_declaration::index_type::unsigned_byte, + index_buffer::usage::static_draw); + + const auto vertices1 = generate_quad_vertices(texture1_->size()); + vertex_buffer1_ = the().create_vertex_buffer( + buffer(vertices1.data(), vertices1.size() * sizeof(vertices1[0])), + vertex1::decl(), + vertex_buffer::usage::static_draw); + + const auto vertices2 = generate_quad_colors(); + vertex_buffer2_ = the().create_vertex_buffer( + buffer(vertices2.data(), vertices2.size() * sizeof(vertices2[0])), + vertex2::decl(), + vertex_buffer::usage::static_draw); + + if ( !index_buffer_ || !vertex_buffer1_ || !vertex_buffer2_ ) { + return false; + } + + material_ = render::material() + .add_pass(render::pass_state() + .states(render::state_block() + .capabilities(render::capabilities_state() + .blending(true)) + .blending(render::blending_state() + .src_factor(render::blending_factor::src_alpha) + .dst_factor(render::blending_factor::one_minus_src_alpha))) + .shader(shader_) + .properties(render::property_block() + .sampler("u_texture1", render::sampler_state() + .texture(texture1_) + .min_filter(render::sampler_min_filter::linear) + .mag_filter(render::sampler_mag_filter::linear)) + .sampler("u_texture2", render::sampler_state() + .texture(texture2_) + .min_filter(render::sampler_min_filter::linear) + .mag_filter(render::sampler_mag_filter::linear)))); + + geometry_ = render::geometry() + .indices(index_buffer_) + .add_vertices(vertex_buffer1_) + .add_vertices(vertex_buffer2_); + + begin_game_time_ = time::now_ms(); + return true; + } + + bool frame_tick() final { + const keyboard& k = the().keyboard(); + if ( the().should_close() || k.is_key_just_released(keyboard_key::escape) ) { + return false; + } + + const auto game_time = (time::now_ms() - begin_game_time_).cast_to().value; + const auto framebuffer_size = the().real_size().cast_to(); + const auto projection = math::make_orthogonal_lh_matrix4(framebuffer_size, 0.f, 1.f); + + material_.properties() + .property("u_time", game_time) + .property("u_MVP", projection); + + the().execute(render::command_block<64>() + .add_command(render::clear_command() + .color_value({1.f, 0.4f, 0.f, 1.f})) + .add_command(render::draw_command(material_, geometry_)) + .add_command(render::swap_command(true))); + + return true; + } + private: + shader_ptr shader_; + texture_ptr texture1_; + texture_ptr texture2_; + index_buffer_ptr index_buffer_; + vertex_buffer_ptr vertex_buffer1_; + vertex_buffer_ptr vertex_buffer2_; + render::material material_; + render::geometry geometry_; + milliseconds begin_game_time_; + }; } int e2d_main() { - { - modules::initialize() - .register_scheme("file"); - modules::initialize() - .register_sink(); - modules::initialize(); - modules::initialize(v2u{640, 480}, "Enduro2D", false) - .register_event_listener(the()); - modules::initialize(the(), the()); - } - { - str resources; - filesystem::extract_predef_path(resources, filesystem::predef_path::resources); - the().register_scheme_alias( - "resources", - url{"file", resources}); - the().register_scheme( - "piratepack", - the().open(url("resources://bin/kenney_piratepack.zip"))); - the().register_scheme_alias("ships", url("piratepack://PNG/Retina/Ships")); - } - - auto texture1 = the().create_texture( - the().open(url("ships://ship (2).png"))); - auto texture2 = the().create_texture( - the().open(url("ships://ship (19).png"))); - - const auto shader = the().create_shader( - vs_source_cstr, fs_source_cstr); - - const auto indices = generate_quad_indices(); - const auto index_buffer = the().create_index_buffer( - buffer(indices.data(), indices.size() * sizeof(indices[0])), - index_declaration::index_type::unsigned_byte, - index_buffer::usage::static_draw); - - const auto vertices1 = generate_quad_vertices(texture1->size()); - const auto vertex_buffer1 = the().create_vertex_buffer( - buffer(vertices1.data(), vertices1.size() * sizeof(vertices1[0])), - vertex1::decl(), - vertex_buffer::usage::static_draw); - - const auto vertices2 = generate_quad_colors(); - const auto vertex_buffer2 = the().create_vertex_buffer( - buffer(vertices2.data(), vertices2.size() * sizeof(vertices2[0])), - vertex2::decl(), - vertex_buffer::usage::static_draw); - - if ( !texture1 || !texture2 || !shader || !index_buffer || !vertex_buffer1 || !vertex_buffer2 ) { - return 1; - } - - auto material = render::material() - .add_pass(render::pass_state() - .states(render::state_block() - .capabilities(render::capabilities_state() - .blending(true)) - .blending(render::blending_state() - .src_factor(render::blending_factor::src_alpha) - .dst_factor(render::blending_factor::one_minus_src_alpha))) - .shader(shader) - .properties(render::property_block() - .sampler("u_texture1", render::sampler_state() - .texture(texture1) - .min_filter(render::sampler_min_filter::linear) - .mag_filter(render::sampler_mag_filter::linear)) - .sampler("u_texture2", render::sampler_state() - .texture(texture2) - .min_filter(render::sampler_min_filter::linear) - .mag_filter(render::sampler_mag_filter::linear)))); - - auto geometry = render::geometry() - .indices(index_buffer) - .add_vertices(vertex_buffer1) - .add_vertices(vertex_buffer2); - - const auto begin_game_time = time::now_ms(); - const auto framebuffer_size = the().real_size().cast_to(); - const auto projection = math::make_orthogonal_lh_matrix4(framebuffer_size, 0.f, 1.f); - - const keyboard& k = the().keyboard(); - while ( !the().should_close() && !k.is_key_just_released(keyboard_key::escape) ) { - const auto game_time = (time::now_ms() - begin_game_time).cast_to().value; - - material.properties() - .property("u_time", game_time) - .property("u_MVP", projection); - - the().execute(render::command_block<64>() - .add_command(render::clear_command() - .color_value({1.f, 0.4f, 0.f, 1.f})) - .add_command(render::draw_command(material, geometry)) - .add_command(render::swap_command(true))); - - the().frame_tick(); - window::poll_events(); - } - + auto params = engine::parameters("sample_00", "enduro2d"); + modules::initialize(params).start(); return 0; } diff --git a/samples/sources/sample_01/sample_01.cpp b/samples/sources/sample_01/sample_01.cpp index ae7f4736..8bb12fa6 100644 --- a/samples/sources/sample_01/sample_01.cpp +++ b/samples/sources/sample_01/sample_01.cpp @@ -149,113 +149,123 @@ namespace vertex2{color32::blue()}, vertex2{color32::yellow()}}; } + + class game final : public application { + public: + bool initialize() final { + the().register_scheme( + "piratepack", + the().open(url("resources://bin/kenney_piratepack.zip"))); + + the().register_scheme_alias( + "ships", + url("piratepack://PNG/Retina/Ships")); + + shader_ = the().create_shader( + vs_source_cstr, fs_source_cstr); + + texture_ = the().create_texture( + the().open(url("ships://ship (3).png"))); + + if ( !shader_ || !texture_ ) { + return false; + } + + const auto indices = generate_cube_indices(); + index_buffer_ = the().create_index_buffer( + buffer(indices.data(), indices.size() * sizeof(indices[0])), + index_declaration::index_type::unsigned_byte, + index_buffer::usage::static_draw); + + const auto vertices1 = generate_cube_vertices(make_vec3(1.f)); + vertex_buffer1_ = the().create_vertex_buffer( + buffer(vertices1.data(), vertices1.size() * sizeof(vertices1[0])), + vertex1::decl(), + vertex_buffer::usage::static_draw); + + const auto vertices2 = generate_cube_colors(); + vertex_buffer2_ = the().create_vertex_buffer( + buffer(vertices2.data(), vertices2.size() * sizeof(vertices2[0])), + vertex2::decl(), + vertex_buffer::usage::static_draw); + + if ( !index_buffer_ || !vertex_buffer1_ || !vertex_buffer2_ ) { + return false; + } + + material_ = render::material() + .add_pass(render::pass_state() + .states(render::state_block() + .capabilities(render::capabilities_state() + .culling(true) + .depth_test(true)) + .culling(render::culling_state() + .mode(render::culling_mode::ccw) + .face(render::culling_face::back))) + .shader(shader_) + .properties(render::property_block() + .sampler("u_texture", render::sampler_state() + .texture(texture_) + .min_filter(render::sampler_min_filter::linear) + .mag_filter(render::sampler_mag_filter::linear)))); + + geometry_ = render::geometry() + .indices(index_buffer_) + .add_vertices(vertex_buffer1_) + .add_vertices(vertex_buffer2_); + + begin_game_time_ = time::now_ms(); + return true; + } + + bool frame_tick() final { + const keyboard& k = the().keyboard(); + if ( the().should_close() || k.is_key_just_released(keyboard_key::escape) ) { + return false; + } + + const auto game_time = (time::now_ms() - begin_game_time_).cast_to().value; + const auto framebuffer_size = the().real_size().cast_to(); + const auto projection = math::make_perspective_lh_matrix4( + make_deg(45.f), + framebuffer_size.x / framebuffer_size.y, + 0.1f, + 100.f); + + const auto MVP = + math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 1.f, 0.f, 0.f) * + math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 1.f, 0.f) * + math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 0.f, 1.f) * + math::make_translation_matrix4(0.f, 0.f, 0.f) * + math::make_loot_at_lh_matrix4({0.f,0.f,-3.f}, v3f::zero(), v3f::unit_y()) * + projection; + + material_.properties() + .property("u_time", game_time) + .property("u_MVP", MVP); + + the().execute(render::command_block<64>() + .add_command(render::clear_command() + .color_value({1.f, 0.4f, 0.f, 1.f})) + .add_command(render::draw_command(material_, geometry_)) + .add_command(render::swap_command(true))); + + return true; + } + private: + shader_ptr shader_; + texture_ptr texture_; + index_buffer_ptr index_buffer_; + vertex_buffer_ptr vertex_buffer1_; + vertex_buffer_ptr vertex_buffer2_; + render::material material_; + render::geometry geometry_; + milliseconds begin_game_time_; + }; } int e2d_main() { - { - modules::initialize() - .register_scheme("file"); - modules::initialize() - .register_sink(); - modules::initialize(); - modules::initialize(v2u{640, 480}, "Enduro2D", false) - .register_event_listener(the()); - modules::initialize(the(), the()); - } - { - str resources; - filesystem::extract_predef_path(resources, filesystem::predef_path::resources); - the().register_scheme_alias( - "resources", - url{"file", resources}); - the().register_scheme( - "piratepack", - the().open(url("resources://bin/kenney_piratepack.zip"))); - the().register_scheme_alias("ships", url("piratepack://PNG/Retina/Ships")); - } - - auto texture = the().create_texture( - the().open(url("ships://ship (3).png"))); - - const auto shader = the().create_shader( - vs_source_cstr, fs_source_cstr); - - const auto indices = generate_cube_indices(); - const auto index_buffer = the().create_index_buffer( - buffer(indices.data(), indices.size() * sizeof(indices[0])), - index_declaration::index_type::unsigned_byte, - index_buffer::usage::static_draw); - - const auto vertices1 = generate_cube_vertices(make_vec3(1.f)); - const auto vertex_buffer1 = the().create_vertex_buffer( - buffer(vertices1.data(), vertices1.size() * sizeof(vertices1[0])), - vertex1::decl(), - vertex_buffer::usage::static_draw); - - const auto vertices2 = generate_cube_colors(); - const auto vertex_buffer2 = the().create_vertex_buffer( - buffer(vertices2.data(), vertices2.size() * sizeof(vertices2[0])), - vertex2::decl(), - vertex_buffer::usage::static_draw); - - if ( !texture || !shader || !index_buffer || !vertex_buffer1 || !vertex_buffer2 ) { - return 1; - } - - auto material = render::material() - .add_pass(render::pass_state() - .states(render::state_block() - .capabilities(render::capabilities_state() - .culling(true) - .depth_test(true)) - .culling(render::culling_state() - .mode(render::culling_mode::ccw) - .face(render::culling_face::back))) - .shader(shader) - .properties(render::property_block() - .sampler("u_texture", render::sampler_state() - .texture(texture) - .min_filter(render::sampler_min_filter::linear) - .mag_filter(render::sampler_mag_filter::linear)))); - - auto geometry = render::geometry() - .indices(index_buffer) - .add_vertices(vertex_buffer1) - .add_vertices(vertex_buffer2); - - const auto begin_game_time = time::now_ms(); - const auto framebuffer_size = the().real_size().cast_to(); - const auto projection = math::make_perspective_lh_matrix4( - make_deg(45.f), - framebuffer_size.x / framebuffer_size.y, - 0.1f, - 100.f); - - const keyboard& k = the().keyboard(); - while ( !the().should_close() && !k.is_key_just_released(keyboard_key::escape) ) { - const auto game_time = (time::now_ms() - begin_game_time).cast_to().value; - - const auto MVP = - math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 1.f, 0.f, 0.f) * - math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 1.f, 0.f) * - math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 0.f, 1.f) * - math::make_translation_matrix4(0.f, 0.f, 0.f) * - math::make_loot_at_lh_matrix4({0.f,0.f,-3.f}, v3f::zero(), v3f::unit_y()) * - projection; - - material.properties() - .property("u_time", game_time) - .property("u_MVP", MVP); - - the().execute(render::command_block<64>() - .add_command(render::clear_command() - .color_value({1.f, 0.4f, 0.f, 1.f})) - .add_command(render::draw_command(material, geometry)) - .add_command(render::swap_command(true))); - - the().frame_tick(); - window::poll_events(); - } - + auto params = engine::parameters("sample_01", "enduro2d"); + modules::initialize(params).start(); return 0; } diff --git a/samples/sources/sample_02/sample_02.cpp b/samples/sources/sample_02/sample_02.cpp index dff472b2..e97d7e66 100644 --- a/samples/sources/sample_02/sample_02.cpp +++ b/samples/sources/sample_02/sample_02.cpp @@ -104,137 +104,149 @@ namespace vertex{{-x, y, -z}, {1, 0}}, vertex{{-x, y, z}, {0, 0}}}; } + + class game final : public application { + public: + bool initialize() final { + the().register_scheme( + "piratepack", + the().open(url("resources://bin/kenney_piratepack.zip"))); + + the().register_scheme_alias( + "ships", + url("piratepack://PNG/Retina/Ships")); + + shader_ = the().create_shader( + vs_source_cstr, fs_source_cstr); + + texture_ = the().create_texture( + the().open(url("ships://ship (3).png"))); + + if ( !shader_ || !texture_ ) { + return false; + } + + const auto indices = generate_cube_indices(); + index_buffer_ = the().create_index_buffer( + buffer(indices.data(), indices.size() * sizeof(indices[0])), + index_declaration::index_type::unsigned_byte, + index_buffer::usage::static_draw); + + const auto vertices = generate_cube_vertices(make_vec3(1.f)); + vertex_buffer_ = the().create_vertex_buffer( + buffer(vertices.data(), vertices.size() * sizeof(vertices[0])), + vertex::decl(), + vertex_buffer::usage::static_draw); + + render_target_ = the().create_render_target( + the().real_size() / 10u, + pixel_declaration::pixel_type::rgba8, + pixel_declaration::pixel_type::depth16, + render_target::external_texture::color_and_depth); + + if ( !index_buffer_ || !vertex_buffer_ || !render_target_ ) { + return false; + } + + rt_props_ = render::property_block() + .sampler("u_texture", render::sampler_state() + .texture(render_target_->color()) + .min_filter(render::sampler_min_filter::linear) + .mag_filter(render::sampler_mag_filter::linear)); + + tex_props_ = render::property_block() + .sampler("u_texture", render::sampler_state() + .texture(texture_) + .min_filter(render::sampler_min_filter::linear) + .mag_filter(render::sampler_mag_filter::linear)); + + material_ = render::material() + .add_pass(render::pass_state() + .states(render::state_block() + .capabilities(render::capabilities_state() + .blending(true) + .culling(true) + .depth_test(true)) + .blending(render::blending_state() + .src_factor(render::blending_factor::src_alpha) + .dst_factor(render::blending_factor::one_minus_src_alpha)) + .culling(render::culling_state() + .mode(render::culling_mode::ccw) + .face(render::culling_face::back))) + .shader(shader_)) + .properties(render::property_block() + .sampler("u_texture", render::sampler_state() + .texture(texture_) + .min_filter(render::sampler_min_filter::linear) + .mag_filter(render::sampler_mag_filter::linear))); + + geometry_ = render::geometry() + .indices(index_buffer_) + .add_vertices(vertex_buffer_); + + begin_game_time_ = time::now_ms(); + return true; + } + + bool frame_tick() final { + const keyboard& k = the().keyboard(); + if ( the().should_close() || k.is_key_just_released(keyboard_key::escape) ) { + return false; + } + + const auto game_time = (time::now_ms() - begin_game_time_).cast_to().value; + const auto framebuffer_size = the().real_size().cast_to(); + const auto projection = math::make_perspective_lh_matrix4( + make_deg(45.f), + framebuffer_size.x / framebuffer_size.y, + 0.1f, + 100.f); + + const auto MVP = + math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 1.f, 0.f, 0.f) * + math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 1.f, 0.f) * + math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 0.f, 1.f) * + math::make_translation_matrix4(0.f, 0.f, 0.f) * + math::make_loot_at_lh_matrix4({0.f,0.f,-2.f}, v3f::zero(), v3f::unit_y()) * + projection; + + material_.properties() + .property("u_time", game_time) + .property("u_MVP", MVP); + + the().execute(render::command_block<64>() + .add_command(render::target_command(render_target_)) + .add_command(render::viewport_command(render_target_->size())) + .add_command(render::clear_command() + .color_value({0.f, 0.4f, 0.f, 1.f})) + .add_command(render::draw_command(material_, geometry_, tex_props_))); + + the().execute(render::command_block<64>() + .add_command(render::target_command(nullptr)) + .add_command(render::viewport_command(the().real_size())) + .add_command(render::clear_command() + .color_value({1.f, 0.4f, 0.f, 1.f})) + .add_command(render::draw_command(material_, geometry_, rt_props_)) + .add_command(render::swap_command(true))); + + return true; + } + private: + shader_ptr shader_; + texture_ptr texture_; + index_buffer_ptr index_buffer_; + vertex_buffer_ptr vertex_buffer_; + render_target_ptr render_target_; + render::property_block rt_props_; + render::property_block tex_props_; + render::material material_; + render::geometry geometry_; + milliseconds begin_game_time_; + }; } int e2d_main() { - { - modules::initialize() - .register_scheme("file"); - modules::initialize() - .register_sink(); - modules::initialize(); - modules::initialize(v2u{640, 480}, "Enduro2D", false) - .register_event_listener(the()); - modules::initialize(the(), the()); - } - { - str resources; - filesystem::extract_predef_path(resources, filesystem::predef_path::resources); - the().register_scheme_alias( - "resources", - url{"file", resources}); - the().register_scheme( - "piratepack", - the().open(url("resources://bin/kenney_piratepack.zip"))); - the().register_scheme_alias("ships", url("piratepack://PNG/Retina/Ships")); - } - - auto texture = the().create_texture( - the().open(url("ships://ship (3).png"))); - - const auto shader = the().create_shader( - vs_source_cstr, fs_source_cstr); - - const auto indices = generate_cube_indices(); - const auto index_buffer = the().create_index_buffer( - buffer(indices.data(), indices.size() * sizeof(indices[0])), - index_declaration::index_type::unsigned_byte, - index_buffer::usage::static_draw); - - const auto vertices = generate_cube_vertices(make_vec3(1.f)); - const auto vertex_buffer = the().create_vertex_buffer( - buffer(vertices.data(), vertices.size() * sizeof(vertices[0])), - vertex::decl(), - vertex_buffer::usage::static_draw); - - if ( !texture || !shader || !index_buffer || !vertex_buffer ) { - return 1; - } - - auto material = render::material() - .add_pass(render::pass_state() - .states(render::state_block() - .capabilities(render::capabilities_state() - .blending(true) - .culling(true) - .depth_test(true)) - .blending(render::blending_state() - .src_factor(render::blending_factor::src_alpha) - .dst_factor(render::blending_factor::one_minus_src_alpha)) - .culling(render::culling_state() - .mode(render::culling_mode::ccw) - .face(render::culling_face::back))) - .shader(shader)) - .properties(render::property_block() - .sampler("u_texture", render::sampler_state() - .texture(texture) - .min_filter(render::sampler_min_filter::linear) - .mag_filter(render::sampler_mag_filter::linear))); - - auto geometry = render::geometry() - .indices(index_buffer) - .add_vertices(vertex_buffer); - - const auto begin_game_time = time::now_ms(); - const auto framebuffer_size = the().real_size().cast_to(); - const auto projection = math::make_perspective_lh_matrix4( - make_deg(45.f), - framebuffer_size.x / framebuffer_size.y, - 0.1f, - 100.f); - - const auto rt = the().create_render_target( - the().real_size() / 10u, - pixel_declaration::pixel_type::rgba8, - pixel_declaration::pixel_type::depth16, - render_target::external_texture::color_and_depth); - - auto rt_props = render::property_block() - .sampler("u_texture", render::sampler_state() - .texture(rt->color()) - .min_filter(render::sampler_min_filter::linear) - .mag_filter(render::sampler_mag_filter::linear)); - - auto texture_props = render::property_block() - .sampler("u_texture", render::sampler_state() - .texture(texture) - .min_filter(render::sampler_min_filter::linear) - .mag_filter(render::sampler_mag_filter::linear)); - - const keyboard& k = the().keyboard(); - while ( !the().should_close() && !k.is_key_just_released(keyboard_key::escape) ) { - const auto game_time = (time::now_ms() - begin_game_time).cast_to().value; - - const auto MVP = - math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 1.f, 0.f, 0.f) * - math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 1.f, 0.f) * - math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 0.f, 1.f) * - math::make_translation_matrix4(0.f, 0.f, 0.f) * - math::make_loot_at_lh_matrix4({0.f,0.f,-2.f}, v3f::zero(), v3f::unit_y()) * - projection; - - material.properties() - .property("u_time", game_time) - .property("u_MVP", MVP); - - the().execute(render::command_block<64>() - .add_command(render::target_command(rt)) - .add_command(render::viewport_command(rt->size())) - .add_command(render::clear_command() - .color_value({0.f, 0.4f, 0.f, 1.f})) - .add_command(render::draw_command(material, geometry, texture_props))); - - the().execute(render::command_block<64>() - .add_command(render::target_command(nullptr)) - .add_command(render::viewport_command(the().real_size())) - .add_command(render::clear_command() - .color_value({1.f, 0.4f, 0.f, 1.f})) - .add_command(render::draw_command(material, geometry, rt_props)) - .add_command(render::swap_command(true))); - - the().frame_tick(); - window::poll_events(); - } - + auto params = engine::parameters("sample_02", "enduro2d"); + modules::initialize(params).start(); return 0; } diff --git a/sources/enduro2d/core/engine.cpp b/sources/enduro2d/core/engine.cpp index 45e40487..c40b60af 100644 --- a/sources/enduro2d/core/engine.cpp +++ b/sources/enduro2d/core/engine.cpp @@ -6,13 +6,258 @@ #include +#include +#include +#include +#include +#include + namespace { using namespace e2d; + + template < typename Module, typename... Args > + void safe_module_initialize(Args&&... args) { + if ( !modules::is_initialized() ) { + modules::initialize(std::forward(args)...); + } + } + + void safe_register_predef_path( + vfs& the_vfs, + str_view scheme, + filesystem::predef_path predef_path) + { + str path; + if ( filesystem::extract_predef_path(path, predef_path) ) { + the_vfs.register_scheme_alias(scheme, url{"file", path}); + } + } } namespace e2d { - engine::engine() = default; + // + // application + // + + bool application::initialize() { + return true; + } + + void application::shutdown() noexcept { + } + + bool application::frame_tick() { + return true; + } + + // + // engine::debug_parameters + // + + engine::debug_parameters& engine::debug_parameters::log_filename(str_view value) { + log_filename_ = value; + return *this; + } + + engine::debug_parameters& engine::debug_parameters::file_logging(bool value) noexcept { + file_logging_ = value; + return *this; + } + + engine::debug_parameters& engine::debug_parameters::console_logging(bool value) noexcept { + console_logging_ = value; + return *this; + } + + const str& engine::debug_parameters::log_filename() const noexcept { + return log_filename_; + } + + bool engine::debug_parameters::file_logging() const noexcept { + return file_logging_; + } + + bool engine::debug_parameters::console_logging() const noexcept { + return console_logging_; + } + + // + // engine::window_parameters + // + + engine::window_parameters& engine::window_parameters::caption(str_view value) { + caption_ = value; + return *this; + } + + engine::window_parameters& engine::window_parameters::size(const v2u& value) noexcept { + size_ = value; + return *this; + } + + engine::window_parameters& engine::window_parameters::fullscreen(bool value) noexcept { + fullscreen_ = value; + return *this; + } + + const str& engine::window_parameters::caption() const noexcept { + return caption_; + } + + const v2u& engine::window_parameters::size() const noexcept { + return size_; + } + + bool engine::window_parameters::fullscreen() const noexcept { + return fullscreen_; + } + + // + // engine::parameters + // + + engine::parameters::parameters(str_view game_name, str_view company_name) + : game_name_(game_name) + , company_name_(company_name) {} + + engine::parameters& engine::parameters::game_name(str_view value) noexcept { + game_name_ = value; + return *this; + } + + engine::parameters& engine::parameters::company_name(str_view value) noexcept { + company_name_ = value; + return *this; + } + + engine::parameters& engine::parameters::debug_params(const debug_parameters& value) { + debug_params_ = value; + return *this; + } + + engine::parameters& engine::parameters::window_params(const window_parameters& value) { + window_params_ = value; + return *this; + } + + str& engine::parameters::game_name() noexcept { + return game_name_; + } + + str& engine::parameters::company_name() noexcept { + return company_name_; + } + + engine::debug_parameters& engine::parameters::debug_params() noexcept { + return debug_params_; + } + + engine::window_parameters& engine::parameters::window_params() noexcept { + return window_params_; + } + + const str& engine::parameters::game_name() const noexcept { + return game_name_; + } + + const str& engine::parameters::company_name() const noexcept { + return company_name_; + } + + const engine::debug_parameters& engine::parameters::debug_params() const noexcept { + return debug_params_; + } + + const engine::window_parameters& engine::parameters::window_params() const noexcept { + return window_params_; + } + + // + // engine::internal_state + // + + class engine::internal_state final : private e2d::noncopyable { + public: + internal_state() = default; + ~internal_state() noexcept = default; + }; + + // + // engine + // + + engine::engine(const parameters& params) + : state_(new internal_state()) + { + // setup debug + + safe_module_initialize(); + + if ( params.debug_params().console_logging() ) { + the().register_sink(); + } + + // setup vfs + + safe_module_initialize(); + + the().register_scheme("file"); + safe_register_predef_path(the(), "home", filesystem::predef_path::home); + safe_register_predef_path(the(), "appdata", filesystem::predef_path::appdata); + safe_register_predef_path(the(), "desktop", filesystem::predef_path::desktop); + safe_register_predef_path(the(), "working", filesystem::predef_path::working); + safe_register_predef_path(the(), "documents", filesystem::predef_path::documents); + safe_register_predef_path(the(), "resources", filesystem::predef_path::resources); + safe_register_predef_path(the(), "executable", filesystem::predef_path::executable); + + if ( params.debug_params().file_logging() ) { + url log_url = url("appdata://") + / params.company_name() + / params.game_name() + / params.debug_params().log_filename(); + output_stream_uptr log_stream = the().write(log_url, false); + the().register_sink(std::move(log_stream)); + } + + // setup input + + safe_module_initialize(); + + // setup window + + safe_module_initialize( + params.window_params().size(), + params.window_params().caption(), + params.window_params().fullscreen()); + + the().register_event_listener(the()); + + // setup render + + safe_module_initialize( + the(), + the()); + } + engine::~engine() noexcept = default; + + bool engine::start(application_uptr app) { + if ( !app || !app->initialize() ) { + the().error("ENGINE: Failed to initialize application"); + return false; + } + try { + while ( app->frame_tick() ) { + the().frame_tick(); + window::poll_events(); + } + } catch ( ... ) { + app->shutdown(); + throw; + } + app->shutdown(); + return true; + } }