// fiko.komut.tanimla / fiko.komut.kaldir — Lua'dan calisma-zamani pencereli komut // tanimlama. Program yeniden DERLENMEDEN yeni "Pad tarzi" komut (once pencere → param // + sahneden sec → ✔ Tamam → sahne mutasyonu) eklenir. Kayit cekirdek.dinamikKomutlar() // registry'sine gider; UI katmani (dinamik_komut_penceresi) menuyu + pencereyi ureter. #include "fiko/betik/makro_motor.hpp" #include #include #include "fiko/cekirdek/cekirdek.hpp" #include "fiko/cekirdek/dinamik_komut.hpp" extern "C" { #include "lauxlib.h" #include "lua.h" } namespace fiko::betik { namespace { KomutParamTip tipCoz(const char* s) { if (!s) return KomutParamTip::Mesafe; const std::string t = s; if (t == "sayi") return KomutParamTip::Sayi; if (t == "tamsayi") return KomutParamTip::Tamsayi; if (t == "bayrak") return KomutParamTip::Bayrak; if (t == "secim") return KomutParamTip::Secim; if (t == "metin") return KomutParamTip::Metin; if (t == "nokta") return KomutParamTip::SahneNokta; if (t == "eksen") return KomutParamTip::SahneEksen; if (t == "govde") return KomutParamTip::SahneGovde; return KomutParamTip::Mesafe; // "mesafe" ve bilinmeyen } // tablo[alan] string (yoksa vars). Stack'i temizler. std::string alanStr(lua_State* L, int t, const char* alan, const char* vars = "") { lua_getfield(L, t, alan); const char* s = lua_isstring(L, -1) ? lua_tostring(L, -1) : vars; std::string r = s ? s : ""; lua_pop(L, 1); return r; } // tablo[alan] number (yoksa vars). Stack'i temizler. f64 alanNum(lua_State* L, int t, const char* alan, f64 vars = 0.0) { lua_getfield(L, t, alan); const f64 r = lua_isnumber(L, -1) ? (f64)lua_tonumber(L, -1) : vars; lua_pop(L, 1); return r; } // paramTablo (stack indeksi t) → KomutParam. secenekler alt-dizisini de okur. KomutParam paramCoz(lua_State* L, int t) { KomutParam p; p.anahtar = alanStr(L, t, "anahtar"); p.etiket = alanStr(L, t, "etiket", p.anahtar.c_str()); p.tip = tipCoz(alanStr(L, t, "tip", "mesafe").c_str()); p.varsayilan = alanNum(L, t, "varsayilan", 0.0); p.minVeya = alanNum(L, t, "min", 0.0); p.maksVeya = alanNum(L, t, "maks", 0.0); p.adim = alanNum(L, t, "adim", 0.1); p.birim = alanStr(L, t, "birim"); p.grup = alanStr(L, t, "grup"); p.metinVarsayilan = alanStr(L, t, "metinVarsayilan"); // Kosullu gorunurluk (veri yolu): kosulAnahtar + kosulDeger. p.kosulAnahtar = alanStr(L, t, "kosulAnahtar"); if (!p.kosulAnahtar.empty()) { p.kosulDeger = alanNum(L, t, "kosulDeger", 0.0); p.kosulVar = true; } // secenekler = { "A", "B", ... } lua_getfield(L, t, "secenekler"); if (lua_istable(L, -1)) { const int n = (int)lua_rawlen(L, -1); for (int i = 1; i <= n; ++i) { lua_rawgeti(L, -1, i); if (lua_isstring(L, -1)) p.secenekler.push_back(lua_tostring(L, -1)); lua_pop(L, 1); } } lua_pop(L, 1); return p; } } // namespace // fiko.komut.tanimla{ id=, ad=, simge=, grup=, aciklama=, parametreler={...}, calistir=fn } // Doner: true (kayit) / nil (gecersiz arg). calistir(p) → p tablosu doldurulmus // parametreleri (sahne ref bilesenleri dahil: anahtar_x/anahtar_y ... anahtarG/anahtarA) // icerir; return true/false ya da nil (basari varsayilir). int MakroMotor::l_komutTanimla(lua_State* L) { MakroMotor* m = kendisi(L); luaL_checktype(L, 1, LUA_TTABLE); // arg 1 tablo olmali const std::string id = alanStr(L, 1, "id"); if (id.empty()) { lua_pushnil(L); return 1; } DinamikKomut k; k.id = id; k.ad = alanStr(L, 1, "ad", id.c_str()); k.simge = alanStr(L, 1, "simge", "◆"); k.grup = alanStr(L, 1, "grup", "Eklenti"); k.aciklama = alanStr(L, 1, "aciklama"); k.kaynak = KomutKaynak::Lua; // parametreler dizisi lua_getfield(L, 1, "parametreler"); if (lua_istable(L, -1)) { const int n = (int)lua_rawlen(L, -1); for (int i = 1; i <= n; ++i) { lua_rawgeti(L, -1, i); if (lua_istable(L, -1)) k.parametreler.push_back(paramCoz(L, lua_gettop(L))); lua_pop(L, 1); } } lua_pop(L, 1); // calistir fonksiyonu → registry ref (kalici tut). Onceki ref varsa serbest birak. lua_getfield(L, 1, "calistir"); if (lua_type(L, -1) != LUA_TFUNCTION) { lua_pop(L, 1); lua_pushnil(L); return 1; } const int ref = luaL_ref(L, LUA_REGISTRYINDEX); // fonksiyonu pop'lar + ref uretir auto onceki = m->komutRefleri_.find(id); if (onceki != m->komutRefleri_.end()) luaL_unref(L, LUA_REGISTRYINDEX, onceki->second); m->komutRefleri_[id] = ref; // calistir marshaling: KomutCalismaBaglam → Lua p tablosu → saklanan fonksiyon. k.calistir = [m, ref](KomutCalismaBaglam& bg) -> bool { lua_State* Ls = m->L_; lua_rawgeti(Ls, LUA_REGISTRYINDEX, ref); if (lua_type(Ls, -1) != LUA_TFUNCTION) { lua_pop(Ls, 1); throw std::runtime_error("komut calistir fonksiyonu kayip"); } lua_createtable(Ls, 0, (int)(bg.sayilar.size() + bg.metinler.size())); for (const auto& [anahtar, deger] : bg.sayilar) { lua_pushnumber(Ls, (lua_Number)deger); lua_setfield(Ls, -2, anahtar.c_str()); } for (const auto& [anahtar, deger] : bg.metinler) { lua_pushlstring(Ls, deger.c_str(), deger.size()); lua_setfield(Ls, -2, anahtar.c_str()); } if (lua_pcall(Ls, 1, 1, 0) != LUA_OK) { const char* msg = lua_tostring(Ls, -1); std::string h = msg ? msg : "lua hatasi"; lua_pop(Ls, 1); throw std::runtime_error(h); // pencere try/catch → hata satirinda gosterir } bool ok = true; // nil → basari varsayilir if (lua_type(Ls, -1) == LUA_TBOOLEAN) ok = lua_toboolean(Ls, -1) != 0; lua_pop(Ls, 1); return ok; }; m->cekirdek_.dinamikKomutlar().ekle(std::move(k)); lua_pushboolean(L, 1); return 1; } // fiko.komut.kaldir("id") → dinamik komutu registry'den sil + Lua ref'i serbest birak. int MakroMotor::l_komutKaldir(lua_State* L) { MakroMotor* m = kendisi(L); const char* id = luaL_checkstring(L, 1); const bool ok = m->cekirdek_.dinamikKomutlar().sil(id); auto it = m->komutRefleri_.find(id); if (it != m->komutRefleri_.end()) { luaL_unref(L, LUA_REGISTRYINDEX, it->second); m->komutRefleri_.erase(it); } lua_pushboolean(L, ok ? 1 : 0); return 1; } } // namespace fiko::betik