# HG changeset patch # User David Demelier # Date 1544207470 -3600 # Node ID 1599919b5de6eebd4e3924c2ea0f781e053b6591 # Parent b788b6a20eea759046b755a5b5eb1c0775038a91 client: allow starting a Javascript file diff -r b788b6a20eea -r 1599919b5de6 libmlk-client-js/malikania/client/js/painter_js_api.cpp --- 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(ctx, 0); w) + self(ctx).use(*w); + else if (auto* t = mlk::js::duk::get(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 } }; diff -r b788b6a20eea -r 1599919b5de6 libmlk-client-js/malikania/client/js/texture_js_api.cpp --- 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::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(ptr); } +auto type_traits::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(ptr); +} + } // !mlk::js::duk diff -r b788b6a20eea -r 1599919b5de6 libmlk-client-js/malikania/client/js/texture_js_api.hpp --- 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 { + /** + * 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 diff -r b788b6a20eea -r 1599919b5de6 libmlk-client-js/malikania/client/js/window_js_api.cpp --- 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 +#include +#include #include @@ -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(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::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(ptr); } +auto type_traits::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(ptr); +} + } // !mlk::js::duk diff -r b788b6a20eea -r 1599919b5de6 libmlk-client-js/malikania/client/js/window_js_api.hpp --- 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 { + /** + * 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 diff -r b788b6a20eea -r 1599919b5de6 mlk-client/CMakeLists.txt --- 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 ) diff -r b788b6a20eea -r 1599919b5de6 mlk-client/main.cpp --- 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 +#include +#include #include -#include -#include +#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include +#if 0 +#include +#endif +#include +#include +#include -using namespace std::chrono_literals; +#include +#include +#include +#include +#include +#if 0 +#include +#endif +#include +#include +#include +#include -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(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(input.rdbuf()), + std::istreambuf_iterator() + ); - 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;