1 | // Aseprite |
2 | // Copyright (C) 2019-2022 Igara Studio S.A. |
3 | // Copyright (C) 2018 David Capello |
4 | // |
5 | // This program is distributed under the terms of |
6 | // the End-User License Agreement for Aseprite. |
7 | |
8 | #ifdef HAVE_CONFIG_H |
9 | #include "config.h" |
10 | #endif |
11 | |
12 | #include "app/app.h" |
13 | #include "app/commands/command.h" |
14 | #include "app/commands/commands.h" |
15 | #include "app/commands/new_params.h" |
16 | #include "app/commands/params.h" |
17 | #include "app/context.h" |
18 | #include "app/script/luacpp.h" |
19 | |
20 | namespace app { |
21 | namespace script { |
22 | |
23 | namespace { |
24 | |
25 | struct AppCommand { }; |
26 | |
27 | int Command_call(lua_State* L) |
28 | { |
29 | app::Context* ctx = App::instance()->context(); |
30 | if (!ctx) |
31 | return 0; |
32 | |
33 | auto command = get_ptr<Command>(L, 1); |
34 | Params params; |
35 | |
36 | if (auto commandLua = dynamic_cast<CommandWithNewParamsBase*>(command)) { |
37 | commandLua->loadParamsFromLuaTable(L, 2); |
38 | } |
39 | else { |
40 | if (lua_istable(L, 2)) { |
41 | lua_pushnil(L); |
42 | while (lua_next(L, 2) != 0) { |
43 | if (const char* k = lua_tostring(L, -2)) { |
44 | const char* v = luaL_tolstring(L, -1, nullptr); |
45 | if (v) |
46 | params.set(k, v); |
47 | lua_pop(L, 1); // pop the value generated by luaL_tolstring() |
48 | } |
49 | lua_pop(L, 1); // pop the value lua_next(), leave the key in the stack |
50 | } |
51 | } |
52 | } |
53 | |
54 | ctx->executeCommand(command, params); |
55 | |
56 | if (ctx->commandResult().type() == CommandResult::kOk) { |
57 | lua_pushboolean(L, true); |
58 | } |
59 | else { |
60 | // TODO rollback/cancel the whole current transaction? |
61 | // or just throw an luaL_error()? |
62 | lua_pushboolean(L, false); |
63 | } |
64 | return 1; |
65 | } |
66 | |
67 | int AppCommand_index(lua_State* L) |
68 | { |
69 | const char* id = lua_tostring(L, 2); |
70 | if (!id) |
71 | return luaL_error(L, "id in app.command.id() must be a string" ); |
72 | |
73 | Command* cmd = Commands::instance()->byId(id); |
74 | if (!cmd) |
75 | return luaL_error(L, "command '%s' not found" , id); |
76 | |
77 | push_ptr(L, cmd); |
78 | return 1; |
79 | } |
80 | |
81 | const luaL_Reg Command_methods[] = { |
82 | { "__call" , Command_call }, |
83 | { nullptr, nullptr } |
84 | }; |
85 | |
86 | const luaL_Reg AppCommand_methods[] = { |
87 | { "__index" , AppCommand_index }, |
88 | { nullptr, nullptr } |
89 | }; |
90 | |
91 | } // anonymous namespace |
92 | |
93 | DEF_MTNAME(Command); |
94 | DEF_MTNAME(AppCommand); |
95 | |
96 | void register_app_command_object(lua_State* L) |
97 | { |
98 | REG_CLASS(L, Command); |
99 | REG_CLASS(L, AppCommand); |
100 | |
101 | lua_getglobal(L, "app" ); |
102 | lua_pushstring(L, "command" ); |
103 | push_new<AppCommand>(L); |
104 | lua_rawset(L, -3); |
105 | lua_pop(L, 1); |
106 | } |
107 | |
108 | } // namespace script |
109 | } // namespace app |
110 | |