From 428db9a1361f3c7d2d9ec3cc1b175f0b3b5ff1d8 Mon Sep 17 00:00:00 2001 From: KP Date: Fri, 2 Aug 2024 01:11:53 -0500 Subject: [PATCH] Add ability to fill in selections with Lisp code --- Data/sandbox-log.txt | 36 --------- KP3Dii/ext/src/imgui/TextEditor.cpp | 4 +- KP3Dii/ext/src/poly2tri/sweep_context.cc | 1 + KP3Dii/src/KP3D_Console.cpp | 11 ++- KP3Dii/src/KP3D_Console.h | 1 + KP3Dii/src/KP3D_Game.cpp | 1 + KP3Dii/src/ksi/KSI_Core.cpp | 2 +- KP3Dii/src/ksi/KSI_Environment.cpp | 72 +++++++++++++++++- KP3Dii/src/ksi/KSI_Utils.cpp | 14 +++- Sandbox/src/Editor.cpp | 95 +++++++++++++++++++++++- 10 files changed, 190 insertions(+), 47 deletions(-) diff --git a/Data/sandbox-log.txt b/Data/sandbox-log.txt index 35bdb47..e69de29 100644 --- a/Data/sandbox-log.txt +++ b/Data/sandbox-log.txt @@ -1,36 +0,0 @@ -[06:58:04 AM] Info: Starting... - - KP3D version 2 -=============================== - Copyright (C) kpworld.xyz 2018-2024 - Contact me! @kp_cftsz - -[06:58:04 AM] Info: Initializing SDL -[06:58:05 AM] Info: Initializing OpenGL -[06:58:05 AM] Info: OpenGL version: 4.6.0 NVIDIA 536.23 -[06:58:05 AM] Info: Initializing GLEW -[06:58:05 AM] Info: Initializing SDL_mixer -[06:58:05 AM] Info: Reticulating splines... -[06:58:05 AM] Info: Ready! -[06:58:05 AM] Info: Loading material resource: block.png -[06:58:05 AM] Info: Found normal map texture: materials/block_n.png -[06:58:05 AM] Info: Loading material resource: brick2.jpg -[06:58:05 AM] Info: Found normal map texture: materials/brick2_n.jpg -[06:58:05 AM] Info: Loading material resource: bricks.jpg -[06:58:05 AM] Info: Found normal map texture: materials/bricks_n.jpg -[06:58:05 AM] Info: Loading material resource: FLAT5_7.png -[06:58:05 AM] Info: Found normal map texture: materials/FLAT5_7_n.png -[06:58:05 AM] Info: Loading material resource: floor0.png -[06:58:05 AM] Info: Found normal map texture: materials/floor0_n.png -[06:58:05 AM] Info: Loading material resource: floor1.png -[06:58:05 AM] Info: Found normal map texture: materials/floor1_n.png -[06:58:05 AM] Info: Loading material resource: GRASS2.png -[06:58:05 AM] Info: Found normal map texture: materials/GRASS2_n.png -[06:58:05 AM] Info: Loading material resource: hardwood.jpg -[06:58:05 AM] Info: Found normal map texture: materials/hardwood_n.jpg -[06:58:05 AM] Info: Map init -[06:58:05 AM] Info: Finalized mesh with 49 batches -[06:58:10 AM] Info: $ make-sector-from-points 0 4 ((30 30) (35 30) (35 35) (30 35)) -[06:58:10 AM] Info: Finalized mesh with 54 batches -[06:58:10 AM] Info: $ 7.000000 -[06:58:32 AM] Info: Finalized mesh with 60 batches diff --git a/KP3Dii/ext/src/imgui/TextEditor.cpp b/KP3Dii/ext/src/imgui/TextEditor.cpp index 1e84708..0fd0db6 100644 --- a/KP3Dii/ext/src/imgui/TextEditor.cpp +++ b/KP3Dii/ext/src/imgui/TextEditor.cpp @@ -2998,14 +2998,14 @@ const TextEditor::LanguageDefinition& TextEditor::LanguageDefinition::Lisp() if (!inited) { static const char* const keywords[] = { - "define", "set!", "let*", "lambda", "if", "do", "progn", "quote", "dump-env" + "define", "set!", "let*", "lambda", "if", "do", "progn", "quote", "dump-env", }; for (auto& k : keywords) langDef.mKeywords.insert(k); static const char* const identifiers[] = { - "sin", "cos", "sqrt", "abs", "log", "log10", "floor", "ceil", "atan2", "PI", "E", "car", "cdr", "cons", "list", "list-ref", "print", "exit" + "sin", "cos", "sqrt", "abs", "log", "log10", "floor", "ceil", "atan2", "PI", "E", "car", "cdr", "cons", "list", "list-ref", "print", "exit", "+1", "-1", "null?" }; for (auto& k : identifiers) { diff --git a/KP3Dii/ext/src/poly2tri/sweep_context.cc b/KP3Dii/ext/src/poly2tri/sweep_context.cc index 70ae07c..30fbabe 100644 --- a/KP3Dii/ext/src/poly2tri/sweep_context.cc +++ b/KP3Dii/ext/src/poly2tri/sweep_context.cc @@ -122,6 +122,7 @@ void SweepContext::AddToMap(Triangle* triangle) Node& SweepContext::LocateNode(Point& point) { // TODO implement search tree + // TODO [kp3d]: how about better fucking error handling for this shit? return *front_->LocateNode(point.x); } diff --git a/KP3Dii/src/KP3D_Console.cpp b/KP3Dii/src/KP3D_Console.cpp index 407ccf0..6cdc74a 100644 --- a/KP3Dii/src/KP3D_Console.cpp +++ b/KP3Dii/src/KP3D_Console.cpp @@ -130,14 +130,19 @@ void Render() void SendCommand(const std::string& command) { - std::string parens = "(" + command + ")"; + // SendKSI(command); + SendKSI("(" + command + ")"); +} + +void SendKSI(const std::string& ksi) +{ reader.Clear(); - reader.Tokenize(parens); + reader.Tokenize(ksi); ksi::Cell c = reader.ReadForm(); ksi::Cell e = Eval(c, environment); if (!ksi::last_output.empty()) KP3D_LOG_INFO("$ : {}", str::Trim(ksi::last_output)); - KP3D_LOG_INFO("$ {}", ksi::Print(e)); + // KP3D_LOG_INFO("$ {}", ksi::Print(e)); } } // namespace kp3d::console diff --git a/KP3Dii/src/KP3D_Console.h b/KP3Dii/src/KP3D_Console.h index a460f3a..a2d1fba 100644 --- a/KP3Dii/src/KP3D_Console.h +++ b/KP3Dii/src/KP3D_Console.h @@ -9,6 +9,7 @@ namespace kp3d::console { void Init(); void Render(); void SendCommand(const std::string& command); +void SendKSI(const std::string& ksi); extern bool open; extern ksi::Environment environment; diff --git a/KP3Dii/src/KP3D_Game.cpp b/KP3Dii/src/KP3D_Game.cpp index 748d746..1326ebf 100644 --- a/KP3Dii/src/KP3D_Game.cpp +++ b/KP3Dii/src/KP3D_Game.cpp @@ -209,6 +209,7 @@ Game::Game(std::string path, std::string cfg_path, std::string log_path): font_cfg.FontNo = 2; ImGui::GetIO().Fonts->AddFontFromFileTTF((sys::GetFontDir() + ".kp3d/msgothic.ttc").c_str(), 13.0f, &font_cfg); font_cfg.FontNo = 0; + font_cfg.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_Bold; ImGui::GetIO().Fonts->AddFontFromFileTTF((sys::GetFontDir() + ".kp3d/msgothic.ttc").c_str(), 13.0f, &font_cfg); ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange; ImGui::GetIO().ConfigWindowsMoveFromTitleBarOnly = true; diff --git a/KP3Dii/src/ksi/KSI_Core.cpp b/KP3Dii/src/ksi/KSI_Core.cpp index e6c7240..5ffa15b 100644 --- a/KP3Dii/src/ksi/KSI_Core.cpp +++ b/KP3Dii/src/ksi/KSI_Core.cpp @@ -16,7 +16,7 @@ Cell EvalAst(Cell ast, Environment& env) return *found; else { - last_output += "Unbound symbol\n"; + last_output += "Unbound symbol: '" + sym_name + "'\n"; return {}; // Abort("Unbound symbol"); } diff --git a/KP3Dii/src/ksi/KSI_Environment.cpp b/KP3Dii/src/ksi/KSI_Environment.cpp index 956fffc..d3cbf47 100644 --- a/KP3Dii/src/ksi/KSI_Environment.cpp +++ b/KP3Dii/src/ksi/KSI_Environment.cpp @@ -54,6 +54,59 @@ ksi::Cell FArithmetic() return cell; } +template +ksi::Cell FCrement() +{ + using namespace ksi; + + Cell cell; + cell.type = CELL_FUNCTION_CPP; + cell.data = [](std::list args) -> Cell + { + Cell res = {CELL_NUMBER}; + if (args.empty()) + { + res.data = 0.0f; + + return res; + } + + // The way the arithemtic functions work is you start with the first in the list (car, + // or in this case `a`) and add/subtract/multiply/divide it by the rest/cdr + // + // e.g. (- 10 5 2 2) = 1. 10 - 5 = 5, 5 - 2 = 3, 3 - 2 = 1 + // + // std::visit([&](auto&& t){if constexpr (std::is_same_v) {std::cout << + // "asdfijasijodjoiasdf\n";}else{std::cout <<"Not the same?" << typeid(t).name() << "\n";}}, args.front().data); + // float a = std::get(args.front().data); + float a = FromCell(args.front()); + switch (OpCode) + { + case '+': a += 1; break; + case '-': a -= 1; break; + } + + res.data = a; // Exception for -, e.g. (- a) = -a + + return res; + }; + + return cell; +} + +ksi::Cell FPow() +{ + using namespace ksi; + + Cell cell; + cell.type = CELL_FUNCTION_CPP; + cell.data = [](std::list args) -> Cell { + return {CELL_NUMBER, powf(FromCell(args.front()), FromCell(args.back()))}; + }; + + return cell; +} + ksi::Cell FSin() { using namespace ksi; @@ -188,6 +241,17 @@ ksi::Cell FCons() return cell; } +ksi::Cell FNull() +{ + using namespace ksi; + + Cell cell; + cell.type = CELL_FUNCTION_CPP; + cell.data = [](std::list args) -> Cell { return {args.front().type == CELL_NIL ? CELL_TRUE : CELL_FALSE}; }; + + return cell; +} + ksi::Cell FList() { using namespace ksi; @@ -520,6 +584,9 @@ void Environment::Init() Set("-", FArithmetic<'-'>()); Set("*", FArithmetic<'*'>()); Set("/", FArithmetic<'/'>()); + Set("+1", FCrement<'+'>()); + Set("-1", FCrement<'-'>()); + Set("**", FPow()); Set("sin", FSin()); Set("cos", FCos()); Set("sqrt", FSqrt()); @@ -540,7 +607,10 @@ void Environment::Init() // The way cons/list work in this is kind of a hack, I guess I'll address it // whenever I rewrite it for KP3D Set("list", FList()); - Set("list-ref", FListRef()); + Set("cons", FCons()); + + // Whatever else + Set("null?", FNull()); // Da Essentials Set("=", FEquals()); diff --git a/KP3Dii/src/ksi/KSI_Utils.cpp b/KP3Dii/src/ksi/KSI_Utils.cpp index 3178edb..6e7acb4 100644 --- a/KP3Dii/src/ksi/KSI_Utils.cpp +++ b/KP3Dii/src/ksi/KSI_Utils.cpp @@ -73,7 +73,19 @@ Cell Cons(Cell a, Cell b) // Maybe setup some kinda pointer cell type instead of having this garbage std::list cons_list; cons_list.push_back(a); - cons_list.push_back(b); + + if (b.type == CELL_LIST) + { + std::list data = std::get>(b.data); + for (Cell& c: data) + { + cons_list.push_back(c); + } + } + else + { + cons_list.push_back(b); + } Cell cons = {CELL_LIST}; cons.data = cons_list; diff --git a/Sandbox/src/Editor.cpp b/Sandbox/src/Editor.cpp index bf8ccbe..ee82af4 100644 --- a/Sandbox/src/Editor.cpp +++ b/Sandbox/src/Editor.cpp @@ -47,6 +47,9 @@ ksi::Cell FMakeSectorFromPoints() Cell c_ceiling_height = *it++; Cell c_pt_list = *it++; + float floor_height = FromCell(c_floor_height); + float ceiling_height = FromCell(c_ceiling_height); + std::vector pts; std::list pt_list = FromCell>(c_pt_list); for (const Cell& c: pt_list) @@ -61,8 +64,8 @@ ksi::Cell FMakeSectorFromPoints() s->ceiling.material = res::material_cache["block.png"].get(); s->floor.material = res::material_cache["block.png"].get(); s->floor.floor = true; - s->floor.base_height = 0.0f; - s->ceiling.base_height = 4.0f; + s->floor.base_height = floor_height; + s->ceiling.base_height = ceiling_height; s->id = sandbox->map.sectors.size() + 1; s->parent_id = 0; s->inverted = false; @@ -90,6 +93,83 @@ ksi::Cell FMakeSectorFromPoints() return cell; } +ksi::Cell FFillSelection() +{ + using namespace ksi; + using namespace kp3d; + + Cell cell; + cell.type = CELL_FUNCTION_CPP; + cell.data = [](std::list args) -> Cell { + if (points.size() < 4 || args.empty()) + return {CELL_NIL}; + + Cell lambda = args.front(); + Cell params = Car(Cdr(lambda)); + Cell body = Car(Cdr(Cdr(lambda))); + + ksi::Environment e(kp3d::console::environment); + std::list param_list = FromCell>(params); + + XYf p1 = {points[0].x, points[0].z}; + XYf p2 = {points[2].x, points[2].z}; + XYf p3 = {points[1].x, points[1].z}; + XYf p4 = {points[3].x, points[3].z}; + + float nh1 = 0.0f; + float nh2 = 4.0f; + for (const auto& sp: sandbox->map.sectors) + { + for (const Wall& l: sp->walls) + { + if (PointInLine(p1, l.start, l.end) || + PointInLine(p3, l.start, l.end) || + FloatCmp(p1.x, l.start.x) || + FloatCmp(p1.y, l.start.y) || + FloatCmp(p3.x, l.start.x) || + FloatCmp(p3.y, l.start.y) || + FloatCmp(p1.x, l.end.x) || + FloatCmp(p1.y, l.end.y) || + FloatCmp(p3.x, l.end.x) || + FloatCmp(p3.y, l.end.y)) + nh1 = sp->floor.base_height; + else if (PointInLine(p2, l.start, l.end) || + PointInLine(p4, l.start, l.end) || + FloatCmp(p2.x, l.start.x) || + FloatCmp(p2.y, l.start.y) || + FloatCmp(p4.x, l.start.x) || + FloatCmp(p4.y, l.start.y) || + FloatCmp(p2.x, l.end.x) || + FloatCmp(p2.y, l.end.y) || + FloatCmp(p4.x, l.end.x) || + FloatCmp(p4.y, l.end.y)) + nh2 = sp->floor.base_height; + } + } + + KP3D_LOG_INFO("[Editor] Filling selection; sector heights {}, {}", nh1, nh2); + + float v_params[] = { + p1.x, // x1 + p1.y, // y1 + p2.x, // x2 + p2.y, // y2 + nh1, // nh1 + nh2, // nh2 + }; + + size_t i = 0; + for (Cell& c: param_list) + e.Set(FromCell(c), { CELL_NUMBER, v_params[i++]}); + + body = Eval(body, e); + + return body; + }; + + return cell; +} + } Editor::Editor() @@ -108,6 +188,7 @@ Editor::Editor() // Put in our fancy Lisp integration stuff kp3d::console::environment.Set("make-sector-from-points", FMakeSectorFromPoints()); + kp3d::console::environment.Set("fill-selection", FFillSelection()); } Editor::~Editor() @@ -305,8 +386,16 @@ void Editor::RenderModeBuild() if (ImGui::Button("build-slope")) {} ImGui::SeparatorText("Custom Routine"); - ImGui::Button("Evaluate"); + if (ImGui::Button("Evaluate")) + { + std::string txt = build_text_editor.GetText(); + kp3d::str::ReplaceAll(txt, "\n", ""); + kp3d::console::SendKSI(txt); + // KP3D_LOG_INFO("EVAL: {}", txt); + } + ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]); build_text_editor.Render("Lisp:"); + ImGui::PopFont(); ImGui::End(); }