Last active
August 29, 2015 13:59
-
-
Save usagi/10658860 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| // TODO: impl |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <forward_list> | |
| #include <unordered_map> | |
| #include <GLFW/glfw3.h> | |
| #include "subsystem_base.hxx" | |
| namespace | |
| { | |
| using window_owner_dictionary_t = std::unordered_map | |
| < GLFWwindow* | |
| , std::weak_ptr<wonder_rabbit_project::wonderland::subsystem::subsystem_base_t> | |
| >; | |
| window_owner_dictionary_t window_owner_dictionary; | |
| } | |
| namespace wonder_rabbit_project | |
| { | |
| namespace wonderland | |
| { | |
| namespace subsystem | |
| { | |
| struct glfw3_runtime_error_t | |
| : subsystem_runtime_error_t | |
| { | |
| glfw3_runtime_error_t(const std::string& what) | |
| : subsystem_runtime_error_t(what) | |
| { } | |
| }; | |
| class GLFW3_t | |
| : public subsystem_base_t | |
| { | |
| using dtor_hook_t = std::function<void()>; | |
| using dtor_hooks_t = std::forward_list<dtor_hook_t>; | |
| dtor_hooks_t _dtor_hooks; | |
| GLFWwindow* _window; | |
| public: | |
| static constexpr const char* initialize_param_key_width = "width"; | |
| static constexpr const char* initialize_param_key_height = "height"; | |
| static constexpr const char* initialize_param_key_title = "title"; | |
| static constexpr const char* initialize_param_key_monitor = "monitor"; | |
| static constexpr const char* initialize_param_key_window = "window"; | |
| static constexpr int initialize_param_default_width = 320; | |
| static constexpr int initialize_param_default_height = 240; | |
| static constexpr const char* initialize_param_default_title = "some other wonderland with GLFW3"; | |
| static constexpr GLFWmonitor* initialize_param_default_monitor = nullptr; | |
| static constexpr GLFWwindow* initialize_param_default_window = nullptr; | |
| ~GLFW3_t() | |
| { | |
| while( not _dtor_hooks.empty() ) | |
| { | |
| _dtor_hooks.front()(); | |
| _dtor_hooks.pop_front(); | |
| } | |
| } | |
| auto default_initialize_params() const | |
| -> initialize_params_t | |
| { | |
| return | |
| { { initialize_param_key_width , initialize_param_default_width } | |
| , { initialize_param_key_height , initialize_param_default_height } | |
| , { initialize_param_key_title , initialize_param_default_title } | |
| , { initialize_param_key_monitor, initialize_param_default_monitor } | |
| , { initialize_param_key_window , initialize_param_default_window } | |
| }; | |
| } | |
| auto initialize( initialize_params_t&& ps ) | |
| -> void override | |
| { | |
| ps = fill_initialize_params( std::move(ps) ); | |
| { | |
| const auto r = glfwInit(); | |
| if ( not r ) | |
| throw glfw3_runtime_error_t( std::string("glfwInit failed. return value: ") + std::to_string(r) ); | |
| } | |
| _dtor_hooks.emplace_front( []{ glfwTerminate(); } ); | |
| glfwSetErrorCallback | |
| ( [](int error, const char* description) | |
| { throw glfw3_runtime_error_t | |
| ( std::string("glfw error: error = ") + std::to_string(error) | |
| + std::string(" , description = ") + std::string(description) | |
| ); | |
| } | |
| ); | |
| const auto window = _window | |
| = glfwCreateWindow | |
| ( boost::any_cast< int >( ps[initialize_param_key_width ] ) | |
| , boost::any_cast< int >( ps[initialize_param_key_height ] ) | |
| , boost::any_cast< const char* >( ps[initialize_param_key_title ] ) | |
| , boost::any_cast< GLFWmonitor* >( ps[initialize_param_key_monitor] ) | |
| , boost::any_cast< GLFWwindow* >( ps[initialize_param_key_window ] ) | |
| ); | |
| if ( not window ) | |
| throw glfw3_runtime_error_t | |
| ( "glfwCreateWindow failed. window is nullptr." ); | |
| ::window_owner_dictionary.emplace( window, shared_from_this() ); | |
| _dtor_hooks.emplace_front( [window] | |
| { | |
| ::window_owner_dictionary.erase( window ); | |
| glfwDestroyWindow( window ); | |
| }); | |
| glfwMakeContextCurrent( window ); | |
| glfwSetKeyCallback | |
| ( window | |
| , [] ( GLFWwindow* window, int key, int scancode, int action, int mods ) | |
| { | |
| ::window_owner_dictionary | |
| .at(window) | |
| .lock() | |
| -> keyboard_state(unsigned(key), bool(action)); | |
| } | |
| ); | |
| glfwSetFramebufferSizeCallback | |
| ( window | |
| , [](GLFWwindow* window, int width, int height) | |
| { glViewport(0, 0, width, height); } | |
| ); | |
| } | |
| auto after_render() | |
| -> void override | |
| { | |
| glfwSwapBuffers( _window ); | |
| glfwPollEvents(); | |
| } | |
| auto to_continue() const | |
| -> bool override | |
| { return not glfwWindowShouldClose( _window ); } | |
| auto to_continue(const bool b) | |
| -> void override | |
| { glfwSetWindowShouldClose( _window, int( not b ) ); } | |
| auto version() const | |
| -> version_t override | |
| { return { GLFW_VERSION_MAJOR , GLFW_VERSION_MINOR , GLFW_VERSION_REVISION }; } | |
| auto name() const | |
| -> std::string override | |
| { return "GLFW3"; } | |
| }; | |
| constexpr const char* GLFW3_t::initialize_param_key_width; | |
| constexpr const char* GLFW3_t::initialize_param_key_height; | |
| constexpr const char* GLFW3_t::initialize_param_key_title; | |
| constexpr const char* GLFW3_t::initialize_param_key_monitor; | |
| constexpr const char* GLFW3_t::initialize_param_key_window; | |
| constexpr int GLFW3_t::initialize_param_default_width; | |
| constexpr int GLFW3_t::initialize_param_default_height; | |
| constexpr const char* GLFW3_t::initialize_param_default_title; | |
| constexpr GLFWmonitor* GLFW3_t::initialize_param_default_monitor; | |
| constexpr GLFWwindow* GLFW3_t::initialize_param_default_window; | |
| #ifndef WRP_WONDERLAND_SUBSYSTEM_T | |
| #define WRP_WONDERLAND_SUBSYSTEM_T | |
| using subsystem_t = GLFW3_t; | |
| #endif | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifdef EMSCRIPTEN | |
| #include <emscripten/emscripten.h> | |
| #endif | |
| // define this CPP-macro if need GLFW3 before include subsystem.hxx | |
| #define WRP_WONDERLAND_SUBSYSTEM_GLFW3 | |
| // include subsystem | |
| #include "subsystem.hxx" | |
| namespace | |
| { | |
| // not need but it's demo. | |
| template<class T> | |
| auto print_initialize_params(T ips) -> void | |
| { | |
| std::cout << "\ninitialize params:\n"; | |
| for ( const auto& ip : ips ) | |
| { | |
| std::cout << " { " << ip.first << " , "; | |
| if ( ip.second.type() == typeid(int) ) | |
| std::cout << boost::any_cast<int>(ip.second); | |
| else if ( ip.second.type() == typeid(const char*) ) | |
| std::cout << boost::any_cast<const char*>(ip.second); | |
| else if ( ip.second.type() == typeid(GLFWmonitor*) ) | |
| std::cout << boost::any_cast<GLFWmonitor*>(ip.second); | |
| else if ( ip.second.type() == typeid(GLFWwindow*) ) | |
| std::cout << boost::any_cast<GLFWwindow*>(ip.second); | |
| else | |
| throw std::logic_error("unexpectedly type."); | |
| std::cout << " }\n"; | |
| } | |
| } | |
| } | |
| int main() | |
| { | |
| // using | |
| using wonder_rabbit_project::wonderland::subsystem::subsystem_t; | |
| // generate the subsystem | |
| auto subsystem = std::make_shared<subsystem_t>(); | |
| // get initialize params ( not need if initilize with default settings ) | |
| auto ips = subsystem -> default_initialize_params(); | |
| print_initialize_params(ips); | |
| // change title | |
| auto title | |
| = std::string("hello, subsystem ") + subsystem->name() | |
| + " version " + subsystem->version().to_string() | |
| ; | |
| ips[subsystem_t::initialize_param_key_title] = title.data(); | |
| print_initialize_params(ips); | |
| // initialize the subsystem | |
| subsystem -> initialize( std::move(ips) ); | |
| // invoke world pattern 1: consign main-loop to subsystem | |
| // set your world update code | |
| subsystem -> update_functors.emplace_front( [&subsystem] | |
| { | |
| /* do update your world */ | |
| if ( subsystem -> keyboard_state< GLFW_KEY_ESCAPE >() ) | |
| subsystem -> to_continue( false ); | |
| } ); | |
| // set your world render code | |
| subsystem -> render_functors.emplace_front( []{ /* do render your world */ } ); | |
| // invoke your world | |
| subsystem -> invoke(); | |
| // invoke world pattern 2: original main-loop system with use subsystem | |
| /* | |
| #ifdef EMSCRIPTEN | |
| emscripten_set_main_loop( [] | |
| #else | |
| do | |
| #endif | |
| { | |
| subsystem -> before_update(); | |
| // do update world | |
| { } | |
| subsystem -> after_update(); | |
| subsystem -> before_render(); | |
| // do render with GL(glXxx) | |
| { } | |
| subsystem -> after_render(); | |
| } | |
| #ifdef EMSCRIPTEN | |
| , 0, 1); | |
| #else | |
| while ( subsystem -> to_continue ); | |
| #endif | |
| */ | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <boost/scope_exit.hpp> | |
| #include "subsystem_base.hxx" | |
| #ifdef WRP_WONDERLAND_SUBSYSTEM_GLFW3 | |
| #include "glfw3.hxx" | |
| #elif defined(WRP_WONDERLAND_SUBSYSTEM_GLFW2) | |
| #include "glfw2.hxx" | |
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <cstdint> | |
| #include <stdexcept> | |
| #include <string> | |
| #include <memory> | |
| #include <unordered_map> | |
| #include <forward_list> | |
| #include <boost/any.hpp> | |
| namespace wonder_rabbit_project | |
| { | |
| namespace wonderland | |
| { | |
| namespace subsystem | |
| { | |
| struct subsystem_runtime_error_t | |
| : std::runtime_error | |
| { | |
| subsystem_runtime_error_t(const std::string& what) | |
| : std::runtime_error(what) | |
| { } | |
| }; | |
| struct version_t | |
| { | |
| std::uint16_t major, minor, revision; | |
| auto to_string() -> std::string | |
| { | |
| return std::to_string(major) + "." | |
| + std::to_string(minor) + "." | |
| + std::to_string(revision) | |
| ; | |
| } | |
| }; | |
| class subsystem_base_t | |
| : public std::enable_shared_from_this<subsystem_base_t> | |
| { | |
| public: | |
| using initialize_param_key_t | |
| = std::string; | |
| using initialize_param_value_t | |
| = boost::any; | |
| using initialize_params_t | |
| = std::unordered_map | |
| < initialize_param_key_t | |
| , initialize_param_value_t | |
| >; | |
| using update_functors_t | |
| = std::forward_list | |
| < std::function<void()> | |
| >; | |
| using render_functors_t | |
| = update_functors_t; | |
| using keyboard_states_t | |
| = std::vector<bool>; | |
| // by USB HID Usage code of the "MENU" key is 348. | |
| static constexpr unsigned max_keycode = 348; | |
| protected: | |
| keyboard_states_t _keyboard_states; | |
| bool _to_continue; | |
| public: | |
| update_functors_t update_functors; | |
| render_functors_t render_functors; | |
| subsystem_base_t() | |
| { | |
| _keyboard_states.resize( max_keycode ); | |
| } | |
| virtual ~subsystem_base_t() { } | |
| virtual auto default_initialize_params() const | |
| -> initialize_params_t | |
| { return initialize_params_t(); } | |
| virtual auto fill_initialize_params(initialize_params_t&& ps) const | |
| -> initialize_params_t | |
| { | |
| for ( const auto& default_param : default_initialize_params() ) | |
| { | |
| const auto& key = default_param.first; | |
| const auto& default_value = default_param.second; | |
| if | |
| ( ps.find(key) == std::end(ps) | |
| or default_value.type() not_eq ps[key].type() | |
| ) | |
| ps[key] = default_value; | |
| } | |
| return ps; | |
| } | |
| virtual auto initialize(initialize_params_t&&) -> void { } | |
| virtual auto before_update() -> void { } | |
| virtual auto after_update() -> void { } | |
| virtual auto before_render() -> void { } | |
| virtual auto after_render() -> void { } | |
| virtual auto version() const -> version_t = 0; | |
| virtual auto name() const -> std::string = 0; | |
| virtual auto update() -> void | |
| { | |
| for ( const auto& f : update_functors ) | |
| f(); | |
| } | |
| virtual auto render() -> void | |
| { | |
| for ( const auto& f : render_functors ) | |
| f(); | |
| } | |
| virtual auto to_continue() const | |
| -> bool | |
| { return _to_continue; } | |
| virtual auto to_continue(const bool b) | |
| -> void | |
| { _to_continue = b; } | |
| template<unsigned keycode> | |
| inline auto keyboard_state() const | |
| -> bool | |
| { return _keyboard_states[keycode]; } | |
| virtual auto keyboard_state(unsigned keycode) const | |
| -> bool | |
| { return _keyboard_states[keycode]; } | |
| virtual auto keyboard_state(unsigned keycode, bool action) | |
| -> void | |
| { _keyboard_states[keycode] = action; } | |
| virtual auto keyboard_states() const | |
| -> const keyboard_states_t& | |
| { return _keyboard_states; } | |
| virtual auto invoke() | |
| -> void | |
| { | |
| _to_continue = true; | |
| #ifdef EMSCRIPTEN | |
| emscripten_set_main_loop( [] | |
| #else | |
| do | |
| #endif | |
| { | |
| before_update(); | |
| update(); | |
| after_update(); | |
| before_render(); | |
| render(); | |
| after_render(); | |
| } | |
| #ifdef EMSCRIPTEN | |
| , 0, 1); | |
| #else | |
| while ( to_continue() ); | |
| #endif | |
| } | |
| }; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment