[lua] Add object.properties("extID") syntax to get extension properties

This commit is contained in:
David Capello 2023-01-03 08:34:14 -03:00
parent 9138592e98
commit b9537dbbe0
4 changed files with 65 additions and 12 deletions

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2018-2023 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -150,7 +150,7 @@ namespace app {
void push_layers(lua_State* L, const doc::ObjectIds& layers);
void push_palette(lua_State* L, doc::Palette* palette);
void push_plugin(lua_State* L, Extension* ext);
void push_properties(lua_State* L, doc::WithUserData* userData);
void push_properties(lua_State* L, doc::WithUserData* userData, const std::string& extID);
void push_sprite_cel(lua_State* L, doc::Cel* cel);
void push_sprite_events(lua_State* L, doc::Sprite* sprite);
void push_sprite_frame(lua_State* L, doc::Sprite* sprite, doc::frame_t frame);

View File

@ -23,7 +23,13 @@ namespace {
struct Properties {
doc::ObjectId id = 0;
Properties(doc::ObjectId id) : id(id) { }
std::string extID;
Properties(doc::ObjectId id,
const std::string& extID)
: id(id)
, extID(extID) {
}
};
using PropertiesIterator = doc::UserData::Properties::iterator;
@ -35,7 +41,7 @@ int Properties_len(lua_State* L)
if (!obj)
return luaL_error(L, "the object with these properties was destroyed");
auto& properties = obj->userData().properties();
auto& properties = obj->userData().properties(propObj->extID);
lua_pushinteger(L, properties.size());
return 1;
}
@ -51,7 +57,7 @@ int Properties_index(lua_State* L)
if (!obj)
return luaL_error(L, "the object with these properties was destroyed");
auto& properties = obj->userData().properties();
auto& properties = obj->userData().properties(propObj->extID);
auto it = properties.find(field);
if (it != properties.end()) {
push_value_to_lua(L, (*it).second);
@ -73,7 +79,7 @@ int Properties_newindex(lua_State* L)
if (!obj)
return luaL_error(L, "the object with these properties was destroyed");
auto& properties = obj->userData().properties();
auto& properties = obj->userData().properties(propObj->extID);
// TODO add undo information
switch (lua_type(L, 3)) {
@ -91,6 +97,30 @@ int Properties_newindex(lua_State* L)
properties[field] = get_value_from_lua<doc::UserData::Variant>(L, 3);
break;
}
return 0;
}
int Properties_call(lua_State* L)
{
auto propObj = get_obj<Properties>(L, 1);
const char* extID = lua_tostring(L, 2);
if (!extID)
return luaL_error(L, "extensionID in 'properties(\"extensionID\")' must be a string");
// Special syntax to change the full extension properties using:
//
// object.property("extension", { ...})
//
if (lua_istable(L, 3)) {
auto obj = static_cast<doc::WithUserData*>(get_object(propObj->id));
if (!obj)
return luaL_error(L, "the object with these properties was destroyed");
auto& properties = obj->userData().properties(extID);
properties = get_value_from_lua<doc::UserData::Properties>(L, 3);
}
push_new<Properties>(L, propObj->id, extID);
return 1;
}
@ -101,7 +131,7 @@ int Properties_pairs_next(lua_State* L)
if (!obj)
return luaL_error(L, "the object with these properties was destroyed");
auto& properties = obj->userData().properties();
auto& properties = obj->userData().properties(propObj->extID);
auto& it = *get_obj<PropertiesIterator>(L, lua_upvalueindex(1));
if (it == properties.end())
return 0;
@ -118,7 +148,7 @@ int Properties_pairs(lua_State* L)
if (!obj)
return luaL_error(L, "the object with these properties was destroyed");
auto& properties = obj->userData().properties();
auto& properties = obj->userData().properties(propObj->extID);
push_obj(L, properties.begin());
lua_pushcclosure(L, Properties_pairs_next, 1);
@ -134,6 +164,7 @@ int PropertiesIterator_gc(lua_State* L)
const luaL_Reg Properties_methods[] = {
{ "__len", Properties_len },
{ "__call", Properties_call },
{ "__index", Properties_index },
{ "__newindex", Properties_newindex },
{ "__pairs", Properties_pairs },
@ -156,9 +187,11 @@ void register_properties_class(lua_State* L)
REG_CLASS(L, PropertiesIterator);
}
void push_properties(lua_State* L, doc::WithUserData* userData)
void push_properties(lua_State* L,
doc::WithUserData* userData,
const std::string& extID)
{
push_obj<Properties>(L, userData->id());
push_new<Properties>(L, userData->id(), extID);
}
} // namespace script

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018-2020 Igara Studio S.A.
// Copyright (C) 2018-2023 Igara Studio S.A.
// Copyright (C) 2018 David Capello
//
// This program is distributed under the terms of
@ -54,7 +54,7 @@ int UserData_get_color(lua_State* L) {
template<typename T>
int UserData_get_properties(lua_State* L) {
auto obj = get_docobj<T>(L, 1);
push_properties(L, get_WithUserData<T>(obj));
push_properties(L, get_WithUserData<T>(obj), std::string());
return 1;
}

View File

@ -72,4 +72,24 @@ do
assert(m.g.y == 4)
assert(m.g.width == 6)
assert(m.g.height == 8)
-- Extension properties
spr.properties.a = 10
spr.properties("ext1").a = 20
assert(spr.properties.a == 10)
assert(spr.properties("ext1").a == 20)
spr.properties("ext1", { a=30, b=35 })
assert(spr.properties("ext1").a == 30)
assert(spr.properties("ext1").b == 35)
local ext1 = spr.properties("ext1")
ext1.a = 40
ext1.b = 45
assert(spr.properties("ext1").a == 40)
assert(spr.properties("ext1").b == 45)
spr.properties("", { a=50, b=60 }) -- Empty extension is the user properties
assert(spr.properties.a == 50)
assert(spr.properties.b == 60)
end