diff --git a/Data/resources/textures/.kp3d/banner.png b/Data/resources/textures/.kp3d/banner.png index 970cf7c..0a8f10e 100644 Binary files a/Data/resources/textures/.kp3d/banner.png and b/Data/resources/textures/.kp3d/banner.png differ diff --git a/Data/sandbox-log.txt b/Data/sandbox-log.txt index e69de29..4a20554 100644 --- a/Data/sandbox-log.txt +++ b/Data/sandbox-log.txt @@ -0,0 +1,48 @@ +[09:17:25 PM] Info: Starting... + + KP3D version 2 +=============================== + Copyright (C) kpworld.xyz 2018-2024 + Contact me! @kp_cftsz + +[09:17:25 PM] Info: Initializing SDL +[09:17:25 PM] Info: Initializing OpenGL +[09:17:25 PM] Info: OpenGL version: 4.6.0 NVIDIA 536.23 +[09:17:25 PM] Info: Initializing GLEW +[09:17:25 PM] Info: Initializing SDL_mixer +[09:17:25 PM] Info: Reticulating splines... +[09:17:25 PM] Info: Ready! +[09:17:25 PM] Info: Loading material resource: block.png +[09:17:25 PM] Info: Found normal map texture: materials/block_n.png +[09:17:25 PM] Info: Loading material resource: FLAT5_7.png +[09:17:25 PM] Info: Found normal map texture: materials/FLAT5_7_n.png +[09:17:25 PM] Info: Loading material resource: floor0.png +[09:17:25 PM] Info: Found normal map texture: materials/floor0_n.png +[09:17:25 PM] Info: Loading material resource: floor1.png +[09:17:25 PM] Info: Found normal map texture: materials/floor1_n.png +[09:17:25 PM] Info: Loading material resource: GRASS2.png +[09:17:25 PM] Info: Found normal map texture: materials/GRASS2_n.png +[09:17:25 PM] Info: Map init +[09:17:25 PM] Info: Finalized mesh with 45 batches +[09:17:30 PM] Info: Finalized mesh with 50 batches +[09:17:39 PM] Info: Finalized mesh with 50 batches +[09:17:42 PM] Info: Finalized mesh with 50 batches +[09:17:47 PM] Info: Finalized mesh with 50 batches +[09:17:53 PM] Info: Finalized mesh with 50 batches +[09:17:54 PM] Info: Finalized mesh with 50 batches +[09:18:05 PM] Info: Finalized mesh with 52 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:07 PM] Info: Finalized mesh with 56 batches +[09:18:12 PM] Info: Finalized mesh with 56 batches diff --git a/KP3Dii/src/KP3D_Map.cpp b/KP3Dii/src/KP3D_Map.cpp index afb610a..37194fd 100644 --- a/KP3Dii/src/KP3D_Map.cpp +++ b/KP3Dii/src/KP3D_Map.cpp @@ -60,11 +60,16 @@ bool SectorContains(const kp3d::Sector& outer, const kp3d::Sector& inner, Sector // kind of ugly the way this works... kp3d::uint ShouldHighlight(const kp3d::RenderBatch3D& batch) { - if (!kp3d::editor_hovered_batch) + using namespace kp3d; + if (editor_hovered_batch.empty()) return 0xFFFFFFFF; - if (&batch != kp3d::editor_hovered_batch) + if (std::find(editor_hovered_batch.begin(), editor_hovered_batch.end(), &batch) == editor_hovered_batch.end()) return 0xFFFFFFFF; - kp3d::BatchSectorInfo info = std::any_cast(batch.userdata); + // if (!kp3d::editor_hovered_batch) + // return 0xFFFFFFFF; + // if (&batch != kp3d::editor_hovered_batch) + // return 0xFFFFFFFF; + BatchSectorInfo info = std::any_cast(batch.userdata); if (info.sector) return 0x5555FFFF; } @@ -73,7 +78,7 @@ kp3d::uint ShouldHighlight(const kp3d::RenderBatch3D& batch) namespace kp3d { -RenderBatch3D* editor_hovered_batch = nullptr; +std::vector editor_hovered_batch; Map::Map() { diff --git a/KP3Dii/src/KP3D_Map.h b/KP3Dii/src/KP3D_Map.h index 5b2faa5..132a6ef 100644 --- a/KP3Dii/src/KP3D_Map.h +++ b/KP3Dii/src/KP3D_Map.h @@ -173,6 +173,6 @@ private: }; -extern RenderBatch3D* editor_hovered_batch; // hack +extern std::vector editor_hovered_batch; // hack } diff --git a/Sandbox/src/Editor.cpp b/Sandbox/src/Editor.cpp index d0a0090..c2c722c 100644 --- a/Sandbox/src/Editor.cpp +++ b/Sandbox/src/Editor.cpp @@ -3,6 +3,7 @@ #include #include "KP3D_Renderer3D.h" +#include "KP3D_StaticMesh.h" #include "KP3D_Raycast.h" #include "KP3D_Math.h" #include "KP3D_Geometry.h" @@ -59,6 +60,9 @@ void Editor::Update() KEY_SHORTCUT(V, m_mode = MODE_BUILD); KEY_SHORTCUT(C, m_mode = MODE_SECTOR_EDIT); + if (anything_hovered) + return; + if (m_mode == MODE_BUILD) { UpdateModeBuild(); @@ -66,42 +70,77 @@ void Editor::Update() } // Raycast through everything on the map - using namespace kp3d; - struct Target + if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_LEFT)) { - Vec3 position; - float distance; - RenderBatch3D* b; - }; - std::vector targets; - for (RenderBatch3D& b: sandbox->map.GetMeshRef().GetBatchesRef()) - { - for (size_t i = 0; i < b.vertex_data.size(); i += 3) + using namespace kp3d; + struct Target { - Vec3 pos; - Triangle tri = {b.vertex_data[i].position, b.vertex_data[i + 1].position, b.vertex_data[i + 2].position}; - auto ray = GetRayFromCamera(sandbox->camera); - bool raycast = RayIntersectsTriangle(ray[0], ray[1], &tri, pos); - if (raycast) + Vec3 position; + float distance; + RenderBatch3D* b; + }; + std::vector targets; + for (RenderBatch3D& b : sandbox->map.GetMeshRef().GetBatchesRef()) + { + for (size_t i = 0; i < b.vertex_data.size(); i += 3) { - float dist = sqrtf( - pow(pos.x - sandbox->camera.position.x, 2) + - pow(pos.y - sandbox->camera.position.y, 2) + - pow(pos.z - sandbox->camera.position.z, 2) - ); - targets.push_back({pos, dist, &b}); + Vec3 pos; + Triangle tri = { b.vertex_data[i].position, b.vertex_data[i + 1].position, b.vertex_data[i + 2].position }; + auto ray = GetRayFromCamera(sandbox->camera); + bool raycast = RayIntersectsTriangle(ray[0], ray[1], &tri, pos); + if (raycast) + { + float dist = sqrtf( + pow(pos.x - sandbox->camera.position.x, 2) + + pow(pos.y - sandbox->camera.position.y, 2) + + pow(pos.z - sandbox->camera.position.z, 2) + ); + targets.push_back({ pos, dist, &b }); + } + } + if (!targets.empty()) + { + std::sort(targets.begin(), targets.end(), [&](const Target& a, const Target& b) { return a.distance > b.distance; }); + const Target& target = targets.back(); + if (editor_hovered_batch.empty()) + { + if (std::find(editor_hovered_batch.begin(), editor_hovered_batch.end(), target.b) == editor_hovered_batch.end()) + editor_hovered_batch.push_back(target.b); + } + else + { + try + { + const auto& info = std::any_cast(kp3d::editor_hovered_batch[0]->userdata); + const auto& target_info = std::any_cast(target.b->userdata); + if (info.wall && target_info.wall) + { + if (std::find(editor_hovered_batch.begin(), editor_hovered_batch.end(), target.b) == editor_hovered_batch.end()) + editor_hovered_batch.push_back(target.b); + } + else if (info.flat && target_info.flat) + { + if (std::find(editor_hovered_batch.begin(), editor_hovered_batch.end(), target.b) == editor_hovered_batch.end()) + editor_hovered_batch.push_back(target.b); + } + } + catch (std::bad_any_cast& e) + { + KP3D_LOG_ERROR("Bad any cast: {}", e.what()); + } + } + } + else + { + // editor_hovered_batch = nullptr; + if (!sandbox->IsKeyDown(kp3d::KEY_LSHIFT)) + { + editor_hovered_batch.clear(); + } } } - if (!targets.empty()) - { - std::sort(targets.begin(), targets.end(), [&](const Target& a, const Target& b) { return a.distance > b.distance; }); - const Target& target = targets.back(); - editor_hovered_batch = target.b; - } - else - editor_hovered_batch = nullptr; + sandbox->MouseButtonReset(kp3d::MOUSE_BUTTON_LEFT); } - } void Editor::RenderMap() @@ -292,11 +331,11 @@ void Editor::RenderUI() } else { - if (kp3d::editor_hovered_batch) + if (!kp3d::editor_hovered_batch.empty()) { try { - const auto& info = std::any_cast(kp3d::editor_hovered_batch->userdata); + const auto& info = std::any_cast(kp3d::editor_hovered_batch[0]->userdata); ImGui::SeparatorText("Type"); ImGui::Text(info.wall ? "Wall" : "Flat/Sector"); if (info.wall) @@ -309,9 +348,9 @@ void Editor::RenderUI() ImGui::CheckboxFlags("Double-sided", (unsigned*)&info.wall->user_flags, kp3d::Wall::UFLAG_DOUBLESIDED); ImGui::SeparatorText("Materials"); - RenderUIMaterialSelect("Middle", &info.wall->materials[kp3d::TEX_FRONT]); - RenderUIMaterialSelect("Upper", &info.wall->materials[kp3d::TEX_UPPER]); - RenderUIMaterialSelect("Lower", &info.wall->materials[kp3d::TEX_LOWER]); + RenderUIMaterialSelect("Middle", MAT_MIDDLE_TEX, &info.wall->materials[kp3d::TEX_FRONT]); + RenderUIMaterialSelect("Upper", MAT_UPPER_TEX, &info.wall->materials[kp3d::TEX_UPPER]); + RenderUIMaterialSelect("Lower", MAT_LOWER_TEX, &info.wall->materials[kp3d::TEX_LOWER]); } else if (info.sector) { @@ -331,8 +370,8 @@ void Editor::RenderUI() if (changed) sandbox->map.Rebuild(kp3d::GEN_NORMALS); ImGui::SeparatorText("Materials"); - RenderUIMaterialSelect("Floor", &info.sector->floor.material); - RenderUIMaterialSelect("Ceiling", &info.sector->ceiling.material); + RenderUIMaterialSelect("Floor", MAT_FLOOR_TEX, &info.sector->floor.material); + RenderUIMaterialSelect("Ceiling", MAT_CEILING_TEX, &info.sector->ceiling.material); } } catch (std::bad_any_cast& e) @@ -340,16 +379,20 @@ void Editor::RenderUI() KP3D_LOG_ERROR("Bad any cast: {}", e.what()); } } + else + { + ImGui::Text("No selection"); + } } ImGui::End(); } } - //ImGui::ShowDemoWindow(); - - if (m_material_to_update) + if (!m_materials_to_update.empty()) RenderUIMaterialModal(); + + anything_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) || ImGui::IsAnyItemHovered(); } void Editor::RenderUIInfo() @@ -403,15 +446,40 @@ void Editor::RenderUIAbout() } } -void Editor::RenderUIMaterialSelect(const char* name, const kp3d::Material** material) +void Editor::RenderUIMaterialSelect(const char* name, int type, const kp3d::Material** material) { ImGui::Text("%s:", name); if (material && *material) { - ImGui::PushID(material); // not safe, not ideal + ImGui::PushID(name + type); // not safe, not ideal if (ImGui::ImageButton((ImTextureID)(*material)->textures[kp3d::MAT_TEX_DIFFUSE].GetGLID(), {96, 96})) { - m_material_to_update = material; + //m_material_to_update = material; + // m_materials_to_update.push_back(material); + for (auto* batch: kp3d::editor_hovered_batch) + { + try + { + auto info = std::any_cast(batch->userdata); + if (info.wall) + { + switch (type) + { + case MAT_UPPER_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_UPPER]); + case MAT_LOWER_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_LOWER]); + case MAT_MIDDLE_TEX: m_materials_to_update.push_back(&info.wall->materials[kp3d::TEX_FRONT]); + } + } + else if (info.flat) + { + m_materials_to_update.push_back(&info.flat->material); + } + } + catch (std::bad_any_cast& e) + { + // ... + } + } should_show_material_modal = true; } ImGui::PopID(); @@ -496,7 +564,8 @@ void Editor::RenderUIMaterialModal() // Should we rebuild the map when we change stuff? I guess. if (should_remove_texture) { - *m_material_to_update = nullptr; + //*m_material_to_update = nullptr; + m_materials_to_update.clear(); ImGui::CloseCurrentPopup(); should_show_material_modal = false; sandbox->map.Rebuild(kp3d::GEN_NORMALS); @@ -511,7 +580,9 @@ void Editor::RenderUIMaterialModal() if (should_update_texture) { - *m_material_to_update = chosen_tex; + for (auto mats: m_materials_to_update) + *mats = chosen_tex; + m_materials_to_update.clear(); ImGui::CloseCurrentPopup(); should_show_material_modal = false; sandbox->map.Rebuild(kp3d::GEN_NORMALS); @@ -526,15 +597,18 @@ void Editor::OnScrollWheel(const kp3d::ScrollWheelEvent* e) { using namespace kp3d; - if (!editor_hovered_batch) + if (editor_hovered_batch.empty()) return; auto factor = (2.0f / 128.0f) * e->length; - auto info = std::any_cast(editor_hovered_batch->userdata); - if (info.flat) + for (auto* batch: editor_hovered_batch) { - info.flat->base_height += factor; - sandbox->map.Rebuild(GEN_NORMALS); + auto info = std::any_cast(batch->userdata); + if (info.flat) + { + info.flat->base_height += factor; + sandbox->map.Rebuild(GEN_NORMALS); + } } } diff --git a/Sandbox/src/Editor.h b/Sandbox/src/Editor.h index c0fe3d4..07b2a7c 100644 --- a/Sandbox/src/Editor.h +++ b/Sandbox/src/Editor.h @@ -12,6 +12,15 @@ enum EditMode MODE_SECTOR_EDIT }; +enum MaterialType +{ + MAT_FLOOR_TEX, + MAT_CEILING_TEX, + MAT_UPPER_TEX, + MAT_LOWER_TEX, + MAT_MIDDLE_TEX +}; + class Editor { public: @@ -31,7 +40,7 @@ public: void RenderUI(); void RenderUIInfo(); void RenderUIAbout(); - void RenderUIMaterialSelect(const char* name, const kp3d::Material** material); + void RenderUIMaterialSelect(const char* name, int type, const kp3d::Material** material); void RenderUIMaterialModal(); void OnScrollWheel(const kp3d::ScrollWheelEvent* e); @@ -52,6 +61,7 @@ private: bool show_about_view = false; bool should_show_material_modal = false; char m_tex_filter_buf[512]; - const kp3d::Material** m_material_to_update = nullptr; + bool anything_hovered = false; + std::vector m_materials_to_update; };