Add ability to select multiple things in editor

This commit is contained in:
KP 2024-07-30 21:19:10 -05:00
parent 7cd5cb59d3
commit 62dd36d7d6
6 changed files with 194 additions and 57 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View file

@ -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

View file

@ -60,11 +60,16 @@ bool SectorContains(const kp3d::Sector& outer, const kp3d::Sector& inner, Sector
// kind of ugly the way this works... // kind of ugly the way this works...
kp3d::uint ShouldHighlight(const kp3d::RenderBatch3D& batch) kp3d::uint ShouldHighlight(const kp3d::RenderBatch3D& batch)
{ {
if (!kp3d::editor_hovered_batch) using namespace kp3d;
if (editor_hovered_batch.empty())
return 0xFFFFFFFF; 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; return 0xFFFFFFFF;
kp3d::BatchSectorInfo info = std::any_cast<kp3d::BatchSectorInfo>(batch.userdata); // if (!kp3d::editor_hovered_batch)
// return 0xFFFFFFFF;
// if (&batch != kp3d::editor_hovered_batch)
// return 0xFFFFFFFF;
BatchSectorInfo info = std::any_cast<BatchSectorInfo>(batch.userdata);
if (info.sector) if (info.sector)
return 0x5555FFFF; return 0x5555FFFF;
} }
@ -73,7 +78,7 @@ kp3d::uint ShouldHighlight(const kp3d::RenderBatch3D& batch)
namespace kp3d { namespace kp3d {
RenderBatch3D* editor_hovered_batch = nullptr; std::vector<RenderBatch3D*> editor_hovered_batch;
Map::Map() Map::Map()
{ {

View file

@ -173,6 +173,6 @@ private:
}; };
extern RenderBatch3D* editor_hovered_batch; // hack extern std::vector<RenderBatch3D*> editor_hovered_batch; // hack
} }

View file

@ -3,6 +3,7 @@
#include <imgui.h> #include <imgui.h>
#include "KP3D_Renderer3D.h" #include "KP3D_Renderer3D.h"
#include "KP3D_StaticMesh.h"
#include "KP3D_Raycast.h" #include "KP3D_Raycast.h"
#include "KP3D_Math.h" #include "KP3D_Math.h"
#include "KP3D_Geometry.h" #include "KP3D_Geometry.h"
@ -59,6 +60,9 @@ void Editor::Update()
KEY_SHORTCUT(V, m_mode = MODE_BUILD); KEY_SHORTCUT(V, m_mode = MODE_BUILD);
KEY_SHORTCUT(C, m_mode = MODE_SECTOR_EDIT); KEY_SHORTCUT(C, m_mode = MODE_SECTOR_EDIT);
if (anything_hovered)
return;
if (m_mode == MODE_BUILD) if (m_mode == MODE_BUILD)
{ {
UpdateModeBuild(); UpdateModeBuild();
@ -66,6 +70,8 @@ void Editor::Update()
} }
// Raycast through everything on the map // Raycast through everything on the map
if (sandbox->IsMouseButtonDown(kp3d::MOUSE_BUTTON_LEFT))
{
using namespace kp3d; using namespace kp3d;
struct Target struct Target
{ {
@ -74,12 +80,12 @@ void Editor::Update()
RenderBatch3D* b; RenderBatch3D* b;
}; };
std::vector<Target> targets; std::vector<Target> targets;
for (RenderBatch3D& b: sandbox->map.GetMeshRef().GetBatchesRef()) for (RenderBatch3D& b : sandbox->map.GetMeshRef().GetBatchesRef())
{ {
for (size_t i = 0; i < b.vertex_data.size(); i += 3) for (size_t i = 0; i < b.vertex_data.size(); i += 3)
{ {
Vec3 pos; Vec3 pos;
Triangle tri = {b.vertex_data[i].position, b.vertex_data[i + 1].position, b.vertex_data[i + 2].position}; Triangle tri = { b.vertex_data[i].position, b.vertex_data[i + 1].position, b.vertex_data[i + 2].position };
auto ray = GetRayFromCamera(sandbox->camera); auto ray = GetRayFromCamera(sandbox->camera);
bool raycast = RayIntersectsTriangle(ray[0], ray[1], &tri, pos); bool raycast = RayIntersectsTriangle(ray[0], ray[1], &tri, pos);
if (raycast) if (raycast)
@ -89,19 +95,52 @@ void Editor::Update()
pow(pos.y - sandbox->camera.position.y, 2) + pow(pos.y - sandbox->camera.position.y, 2) +
pow(pos.z - sandbox->camera.position.z, 2) pow(pos.z - sandbox->camera.position.z, 2)
); );
targets.push_back({pos, dist, &b}); targets.push_back({ pos, dist, &b });
} }
} }
if (!targets.empty()) if (!targets.empty())
{ {
std::sort(targets.begin(), targets.end(), [&](const Target& a, const Target& b) { return a.distance > b.distance; }); std::sort(targets.begin(), targets.end(), [&](const Target& a, const Target& b) { return a.distance > b.distance; });
const Target& target = targets.back(); const Target& target = targets.back();
editor_hovered_batch = target.b; 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 else
editor_hovered_batch = nullptr; {
try
{
const auto& info = std::any_cast<kp3d::BatchSectorInfo>(kp3d::editor_hovered_batch[0]->userdata);
const auto& target_info = std::any_cast<kp3d::BatchSectorInfo>(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();
}
}
}
sandbox->MouseButtonReset(kp3d::MOUSE_BUTTON_LEFT);
} }
} }
void Editor::RenderMap() void Editor::RenderMap()
@ -292,11 +331,11 @@ void Editor::RenderUI()
} }
else else
{ {
if (kp3d::editor_hovered_batch) if (!kp3d::editor_hovered_batch.empty())
{ {
try try
{ {
const auto& info = std::any_cast<kp3d::BatchSectorInfo>(kp3d::editor_hovered_batch->userdata); const auto& info = std::any_cast<kp3d::BatchSectorInfo>(kp3d::editor_hovered_batch[0]->userdata);
ImGui::SeparatorText("Type"); ImGui::SeparatorText("Type");
ImGui::Text(info.wall ? "Wall" : "Flat/Sector"); ImGui::Text(info.wall ? "Wall" : "Flat/Sector");
if (info.wall) if (info.wall)
@ -309,9 +348,9 @@ void Editor::RenderUI()
ImGui::CheckboxFlags("Double-sided", (unsigned*)&info.wall->user_flags, kp3d::Wall::UFLAG_DOUBLESIDED); ImGui::CheckboxFlags("Double-sided", (unsigned*)&info.wall->user_flags, kp3d::Wall::UFLAG_DOUBLESIDED);
ImGui::SeparatorText("Materials"); ImGui::SeparatorText("Materials");
RenderUIMaterialSelect("Middle", &info.wall->materials[kp3d::TEX_FRONT]); RenderUIMaterialSelect("Middle", MAT_MIDDLE_TEX, &info.wall->materials[kp3d::TEX_FRONT]);
RenderUIMaterialSelect("Upper", &info.wall->materials[kp3d::TEX_UPPER]); RenderUIMaterialSelect("Upper", MAT_UPPER_TEX, &info.wall->materials[kp3d::TEX_UPPER]);
RenderUIMaterialSelect("Lower", &info.wall->materials[kp3d::TEX_LOWER]); RenderUIMaterialSelect("Lower", MAT_LOWER_TEX, &info.wall->materials[kp3d::TEX_LOWER]);
} }
else if (info.sector) else if (info.sector)
{ {
@ -331,8 +370,8 @@ void Editor::RenderUI()
if (changed) if (changed)
sandbox->map.Rebuild(kp3d::GEN_NORMALS); sandbox->map.Rebuild(kp3d::GEN_NORMALS);
ImGui::SeparatorText("Materials"); ImGui::SeparatorText("Materials");
RenderUIMaterialSelect("Floor", &info.sector->floor.material); RenderUIMaterialSelect("Floor", MAT_FLOOR_TEX, &info.sector->floor.material);
RenderUIMaterialSelect("Ceiling", &info.sector->ceiling.material); RenderUIMaterialSelect("Ceiling", MAT_CEILING_TEX, &info.sector->ceiling.material);
} }
} }
catch (std::bad_any_cast& e) catch (std::bad_any_cast& e)
@ -340,16 +379,20 @@ void Editor::RenderUI()
KP3D_LOG_ERROR("Bad any cast: {}", e.what()); KP3D_LOG_ERROR("Bad any cast: {}", e.what());
} }
} }
else
{
ImGui::Text("No selection");
}
} }
ImGui::End(); ImGui::End();
} }
} }
//ImGui::ShowDemoWindow(); if (!m_materials_to_update.empty())
if (m_material_to_update)
RenderUIMaterialModal(); RenderUIMaterialModal();
anything_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) || ImGui::IsAnyItemHovered();
} }
void Editor::RenderUIInfo() 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); ImGui::Text("%s:", name);
if (material && *material) 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})) 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<kp3d::BatchSectorInfo>(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; should_show_material_modal = true;
} }
ImGui::PopID(); ImGui::PopID();
@ -496,7 +564,8 @@ void Editor::RenderUIMaterialModal()
// Should we rebuild the map when we change stuff? I guess. // Should we rebuild the map when we change stuff? I guess.
if (should_remove_texture) if (should_remove_texture)
{ {
*m_material_to_update = nullptr; //*m_material_to_update = nullptr;
m_materials_to_update.clear();
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
should_show_material_modal = false; should_show_material_modal = false;
sandbox->map.Rebuild(kp3d::GEN_NORMALS); sandbox->map.Rebuild(kp3d::GEN_NORMALS);
@ -511,7 +580,9 @@ void Editor::RenderUIMaterialModal()
if (should_update_texture) 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(); ImGui::CloseCurrentPopup();
should_show_material_modal = false; should_show_material_modal = false;
sandbox->map.Rebuild(kp3d::GEN_NORMALS); sandbox->map.Rebuild(kp3d::GEN_NORMALS);
@ -526,16 +597,19 @@ void Editor::OnScrollWheel(const kp3d::ScrollWheelEvent* e)
{ {
using namespace kp3d; using namespace kp3d;
if (!editor_hovered_batch) if (editor_hovered_batch.empty())
return; return;
auto factor = (2.0f / 128.0f) * e->length; auto factor = (2.0f / 128.0f) * e->length;
auto info = std::any_cast<BatchSectorInfo>(editor_hovered_batch->userdata); for (auto* batch: editor_hovered_batch)
{
auto info = std::any_cast<BatchSectorInfo>(batch->userdata);
if (info.flat) if (info.flat)
{ {
info.flat->base_height += factor; info.flat->base_height += factor;
sandbox->map.Rebuild(GEN_NORMALS); sandbox->map.Rebuild(GEN_NORMALS);
} }
}
} }
void Editor::OnKeyPress(const kp3d::KeyPressEvent* e) void Editor::OnKeyPress(const kp3d::KeyPressEvent* e)

View file

@ -12,6 +12,15 @@ enum EditMode
MODE_SECTOR_EDIT MODE_SECTOR_EDIT
}; };
enum MaterialType
{
MAT_FLOOR_TEX,
MAT_CEILING_TEX,
MAT_UPPER_TEX,
MAT_LOWER_TEX,
MAT_MIDDLE_TEX
};
class Editor class Editor
{ {
public: public:
@ -31,7 +40,7 @@ public:
void RenderUI(); void RenderUI();
void RenderUIInfo(); void RenderUIInfo();
void RenderUIAbout(); 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 RenderUIMaterialModal();
void OnScrollWheel(const kp3d::ScrollWheelEvent* e); void OnScrollWheel(const kp3d::ScrollWheelEvent* e);
@ -52,6 +61,7 @@ private:
bool show_about_view = false; bool show_about_view = false;
bool should_show_material_modal = false; bool should_show_material_modal = false;
char m_tex_filter_buf[512]; char m_tex_filter_buf[512];
const kp3d::Material** m_material_to_update = nullptr; bool anything_hovered = false;
std::vector<const kp3d::Material**> m_materials_to_update;
}; };