Mercurial > malikania
changeset 210:1599919b5de6
client: allow starting a Javascript file
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 07 Dec 2018 19:31:10 +0100 |
parents | b788b6a20eea |
children | ac99f440ee44 |
files | libmlk-client-js/malikania/client/js/painter_js_api.cpp libmlk-client-js/malikania/client/js/texture_js_api.cpp libmlk-client-js/malikania/client/js/texture_js_api.hpp libmlk-client-js/malikania/client/js/window_js_api.cpp libmlk-client-js/malikania/client/js/window_js_api.hpp mlk-client/CMakeLists.txt mlk-client/main.cpp |
diffstat | 7 files changed, 177 insertions(+), 76 deletions(-) [+] |
line wrap: on
line diff
--- a/libmlk-client-js/malikania/client/js/painter_js_api.cpp Tue Dec 18 12:38:21 2018 +0100 +++ b/libmlk-client-js/malikania/client/js/painter_js_api.cpp Fri Dec 07 19:31:10 2018 +0100 @@ -95,6 +95,22 @@ return 0; } +auto Painter_prototype_use(duk_context* ctx) -> duk_ret_t +{ + try { + if (auto* w = mlk::js::duk::get<window>(ctx, 0); w) + self(ctx).use(*w); + else if (auto* t = mlk::js::duk::get<texture>(ctx, 0); t) + self(ctx).use(*t); + else + throw std::runtime_error("expected Window or Texture"); + } catch (const std::exception& ex) { + duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what()); + } + + return 0; +} + auto Painter_prototype_present(duk_context* ctx) -> duk_ret_t { try { @@ -175,14 +191,15 @@ } // !namespace const duk_function_list_entry methods[] = { - { "clear", Painter_prototype_clear, 0 }, - { "drawingColor", Painter_prototype_drawingColor, 0 }, - { "drawLine", Painter_prototype_drawLine, 1 }, - { "drawPoint", Painter_prototype_drawPoint, 1 }, - { "drawRectangle", Painter_prototype_drawRectangle, 1 }, - { "fillRectangle", Painter_prototype_fillRectangle, 1 }, - { "present", Painter_prototype_present, 0 }, - { "setDrawingColor", Painter_prototype_setDrawingColor, 1 }, + { "clear", Painter_prototype_clear, 0 }, + { "use", Painter_prototype_use, 1 }, + { "drawingColor", Painter_prototype_drawingColor, 0 }, + { "drawLine", Painter_prototype_drawLine, 1 }, + { "drawPoint", Painter_prototype_drawPoint, 1 }, + { "drawRectangle", Painter_prototype_drawRectangle, 1 }, + { "fillRectangle", Painter_prototype_fillRectangle, 1 }, + { "present", Painter_prototype_present, 0 }, + { "setDrawingColor", Painter_prototype_setDrawingColor, 1 }, { nullptr, nullptr, 0 } };
--- a/libmlk-client-js/malikania/client/js/texture_js_api.cpp Tue Dec 18 12:38:21 2018 +0100 +++ b/libmlk-client-js/malikania/client/js/texture_js_api.cpp Fri Dec 07 19:31:10 2018 +0100 @@ -123,13 +123,7 @@ auto type_traits<mlk::client::texture>::require(duk_context* ctx, duk_idx_t index) -> mlk::client::texture& { - assert(ctx); - - mlk::js::duk::stack_guard sa(ctx); - - duk_get_prop_string(ctx, index, mlk::client::js::signature.data()); - auto ptr = duk_to_pointer(ctx, -1); - duk_pop(ctx); + auto ptr = get(ctx, index); if (!ptr) duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Texture object"); @@ -137,4 +131,17 @@ return *static_cast<mlk::client::texture*>(ptr); } +auto type_traits<mlk::client::texture>::get(duk_context* ctx, duk_idx_t index) -> mlk::client::texture* +{ + assert(ctx); + + stack_guard sa(ctx); + + duk_get_prop_string(ctx, index, mlk::client::js::signature.data()); + auto ptr = duk_to_pointer(ctx, -1); + duk_pop(ctx); + + return static_cast<mlk::client::texture*>(ptr); +} + } // !mlk::js::duk
--- a/libmlk-client-js/malikania/client/js/texture_js_api.hpp Tue Dec 18 12:38:21 2018 +0100 +++ b/libmlk-client-js/malikania/client/js/texture_js_api.hpp Fri Dec 07 19:31:10 2018 +0100 @@ -36,17 +36,38 @@ */ void load_texture_api(duk_context* ctx); -} // !client +} // !js -} // !js +} // !client } // !mlk namespace mlk::js::duk { +/** + * \brief Specialize type_traits with mlk::client::texture. + */ template <> struct type_traits<client::texture> { + /** + * Require a texture at the given index or throw a Javascript error + * instead. + * + * \param ctx the context + * \param index the index + * \return the texture + */ static auto require(duk_context* ctx, duk_idx_t index) -> client::texture&; + + /** + * Get a texture or return nullptr if not. + * + * \param ctx the context + * \param index the index + * \return the texture + * \warning don't delete the texture + */ + static auto get(duk_context* ctx, duk_idx_t index) -> client::texture*; }; } // !mlk::js::duk
--- a/libmlk-client-js/malikania/client/js/window_js_api.cpp Tue Dec 18 12:38:21 2018 +0100 +++ b/libmlk-client-js/malikania/client/js/window_js_api.cpp Fri Dec 07 19:31:10 2018 +0100 @@ -17,6 +17,8 @@ */ #include <cassert> +#include <chrono> +#include <thread> #include <malikania/client/window.hpp> @@ -64,6 +66,18 @@ return 0; } +auto Window_prototype_sleep(duk_context* ctx) -> duk_ret_t +{ + std::this_thread::sleep_for(std::chrono::seconds(mlk::js::duk::get<unsigned>(ctx, 0))); + + return 0; +} + +const duk_function_list_entry methods[] = { + { "sleep", Window_prototype_sleep, 1 }, + { nullptr, nullptr, 0 } +}; + } // !namespace void load_window_api(duk_context* ctx) @@ -73,9 +87,7 @@ duk_get_global_string(ctx, "Malikania"); duk_push_c_function(ctx, Window_constructor, 0); duk_push_object(ctx); -#if 0 duk_put_function_list(ctx, -1, methods); -#endif duk_put_prop_string(ctx, -2, "prototype"); duk_put_prop_string(ctx, -2, "Window"); duk_pop(ctx); @@ -87,13 +99,7 @@ auto type_traits<mlk::client::window>::require(duk_context* ctx, duk_idx_t index) -> mlk::client::window& { - assert(ctx); - - mlk::js::duk::stack_guard sa(ctx); - - duk_get_prop_string(ctx, index, mlk::client::js::signature.data()); - auto ptr = duk_to_pointer(ctx, -1); - duk_pop(ctx); + auto ptr = get(ctx, index); if (!ptr) duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Window object"); @@ -101,4 +107,17 @@ return *static_cast<mlk::client::window*>(ptr); } +auto type_traits<mlk::client::window>::get(duk_context* ctx, duk_idx_t index) -> mlk::client::window* +{ + assert(ctx); + + stack_guard sa(ctx); + + duk_get_prop_string(ctx, index, mlk::client::js::signature.data()); + auto ptr = duk_to_pointer(ctx, -1); + duk_pop(ctx); + + return static_cast<mlk::client::window*>(ptr); +} + } // !mlk::js::duk
--- a/libmlk-client-js/malikania/client/js/window_js_api.hpp Tue Dec 18 12:38:21 2018 +0100 +++ b/libmlk-client-js/malikania/client/js/window_js_api.hpp Fri Dec 07 19:31:10 2018 +0100 @@ -36,17 +36,38 @@ */ void load_window_api(duk_context* ctx); -} // !client +} // !js -} // !js +} // !client } // !mlk namespace mlk::js::duk { +/** + * \brief Specialize type_traits with mlk::client::window. + */ template <> struct type_traits<client::window> { + /** + * Require a window at the given index or throw a Javascript error + * instead. + * + * \param ctx the context + * \param index the index + * \return the window + */ static auto require(duk_context* ctx, duk_idx_t index) -> client::window&; + + /** + * Get a texture or return nullptr if not. + * + * \param ctx the context + * \param index the index + * \return the texture + * \warning don't delete the texture + */ + static auto get(duk_context* ctx, duk_idx_t index) -> client::window*; }; } // !mlk::js::duk
--- a/mlk-client/CMakeLists.txt Tue Dec 18 12:38:21 2018 +0100 +++ b/mlk-client/CMakeLists.txt Fri Dec 07 19:31:10 2018 +0100 @@ -32,5 +32,6 @@ LIBRARIES ${SDL2MAIN_LIBRARIES} Threads::Threads - libmlk-client + libmlk-js + libmlk-client-js )
--- a/mlk-client/main.cpp Tue Dec 18 12:38:21 2018 +0100 +++ b/mlk-client/main.cpp Fri Dec 07 19:31:10 2018 +0100 @@ -16,64 +16,79 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <cerrno> +#include <cstring> +#include <fstream> #include <iostream> -#include <chrono> -#include <thread> +#include <iterator> -#include <malikania/client/color.hpp> -#include <malikania/client/button.hpp> -#include <malikania/client/window.hpp> -#include <malikania/client/sprite.hpp> -#include <malikania/client/theme.hpp> -#include <malikania/client/painter.hpp> - -#include <assets/ui.hpp> +#include <malikania/js/elapsed_timer_js_api.hpp> +#include <malikania/js/line_js_api.hpp> +#if 0 +#include <malikania/js/loader_js_api.hpp> +#endif +#include <malikania/js/point_js_api.hpp> +#include <malikania/js/rectangle_js_api.hpp> +#include <malikania/js/size_js_api.hpp> -using namespace std::chrono_literals; +#include <malikania/client/js/animation_js_api.hpp> +#include <malikania/client/js/animator_js_api.hpp> +#include <malikania/client/js/color_js_api.hpp> +#include <malikania/client/js/font_js_api.hpp> +#include <malikania/client/js/image_js_api.hpp> +#if 0 +#include <malikania/client/js/loader_js_api.hpp> +#endif +#include <malikania/client/js/painter_js_api.hpp> +#include <malikania/client/js/sprite_js_api.hpp> +#include <malikania/client/js/texture_js_api.hpp> +#include <malikania/client/js/window_js_api.hpp> -int main(int, char**) +int main(int argc, char** argv) { - mlk::client::window win(1920/2, 1080/2, "Hello"); - mlk::client::image image(std::string(ui, sizeof (ui))); - mlk::client::sprite sprite(std::move(image), {16, 16}); - mlk::client::painter painter(win); - - for (;;) { - while (auto ev = win.poll()) { - if (std::holds_alternative<mlk::client::quit_event>(ev)) - return 0; - } + -- argc; + ++ argv; - painter.clear(); - painter.set_drawing_color(mlk::client::color::from_hex(0xffffffff)); + if (argc == 0) { + std::cerr << "usage: mlk-client main.js" << std::endl; + return 1; + } - const auto width = 200; - const auto height = 150; + try { + mlk::js::duk::context ctx; - // top - sprite.draw(painter, 0, mlk::point{10, 10}); - sprite.draw(painter, 1, mlk::rectangle{10 + 16, 10, width, 16}); - sprite.draw(painter, 2, mlk::point{10 + 16 + width, 10}); + mlk::js::load_elapsed_timer_api(ctx); + mlk::js::load_line_api(ctx); + mlk::js::load_point_api(ctx); + mlk::js::load_rectangle_api(ctx); + mlk::js::load_size_api(ctx); - // middle - sprite.draw(painter, 32, mlk::rectangle{10, 10 + 16, 16, height}); - sprite.draw(painter, 33, mlk::rectangle{10 + 16, 10 + 16, width, height}); - sprite.draw(painter, 34, mlk::rectangle{10 + 16 + width, 10 + 16, 16, height}); - - // bottom - sprite.draw(painter, 64, mlk::point{10, 10 + 16 + height}); - sprite.draw(painter, 65, mlk::rectangle{10 + 16, 10 + 16 + height, width, 16}); - sprite.draw(painter, 66, mlk::point{10 + 16 + width, 10 + 16 + height}); + mlk::client::js::load_animation_api(ctx); + mlk::client::js::load_animator_api(ctx); + mlk::client::js::load_color_api(ctx); + mlk::client::js::load_image_api(ctx); + mlk::client::js::load_painter_api(ctx); + mlk::client::js::load_sprite_api(ctx); + mlk::client::js::load_texture_api(ctx); + mlk::client::js::load_window_api(ctx); - // input - sprite.draw(painter, 3, mlk::point{10 + 8, 10 + 8}); - sprite.draw(painter, 4, mlk::rectangle{10 + 8 + 16, 10 + 8, width - 16, 16}); - sprite.draw(painter, 5, mlk::point{10 + 8 + width, 10 + 8}); - sprite.draw(painter, 35, mlk::point{10 + 8, 10 + 8 + 16}); - sprite.draw(painter, 36, mlk::rectangle{10 + 8 + 16, 10 + 8 + 16, width - 16, 16}); - sprite.draw(painter, 37, mlk::point{10 + 8 + width, 10 + 8 + 16}); + std::ifstream input(argv[0]); + std::string script( + std::istreambuf_iterator<char>(input.rdbuf()), + std::istreambuf_iterator<char>() + ); - painter.present(); + if (!input) + throw std::runtime_error(std::strerror(errno)); + if (duk_peval_string(ctx, script.c_str())) + throw mlk::js::duk::get_stack(ctx, -1); + } catch (const mlk::js::duk::stack_info& ex) { + std::cerr << argv[0] << ":" << ex.get_line_number() << ": " << ex.what() << std::endl; + std::cerr << ex.get_stack() << std::endl; + return 1; + } catch (const std::exception& ex) { + std::cerr << "abort: " << ex.what() << std::endl; + return 1; } return 0;