commit
01064f49b5
@ -64,12 +64,14 @@ namespace asset_list
|
|||||||
ImGui::InputText("asset name", &assets_name_filter[type]);
|
ImGui::InputText("asset name", &assets_name_filter[type]);
|
||||||
ImGui::BeginChild("assets list");
|
ImGui::BeginChild("assets list");
|
||||||
|
|
||||||
fastfiles::enum_assets(type, [type](const game::XAssetHeader header)
|
const auto lowercase_filter = utils::string::to_lower(assets_name_filter[type]);
|
||||||
|
|
||||||
|
fastfiles::enum_assets(type, [&lowercase_filter, type](const game::XAssetHeader header)
|
||||||
{
|
{
|
||||||
const auto asset = game::XAsset{type, header};
|
const auto asset = game::XAsset{type, header};
|
||||||
const auto* const asset_name = game::DB_GetXAssetName(&asset);
|
const auto* const asset_name = game::DB_GetXAssetName(&asset);
|
||||||
|
|
||||||
if (utils::string::find_lower(asset_name, assets_name_filter[type]) && ImGui::Button(asset_name))
|
if (strstr(asset_name, lowercase_filter.data()) && ImGui::Button(asset_name))
|
||||||
{
|
{
|
||||||
gui::copy_to_clipboard(asset_name);
|
gui::copy_to_clipboard(asset_name);
|
||||||
}
|
}
|
||||||
|
@ -25,32 +25,62 @@ namespace gui_debug
|
|||||||
enum object_type
|
enum object_type
|
||||||
{
|
{
|
||||||
square,
|
square,
|
||||||
|
circle,
|
||||||
|
circle_fill,
|
||||||
cube,
|
cube,
|
||||||
cube_mesh
|
cube_mesh
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum entity_type
|
||||||
|
{
|
||||||
|
other,
|
||||||
|
trigger_radius,
|
||||||
|
generic_trigger,
|
||||||
|
actor,
|
||||||
|
count
|
||||||
|
};
|
||||||
|
|
||||||
float camera[3] = {};
|
float camera[3] = {};
|
||||||
float axis[3][3] = {};
|
float axis[3][3] = {};
|
||||||
|
|
||||||
struct draw_settings
|
struct draw_settings
|
||||||
{
|
{
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool native_rendering;
|
|
||||||
bool camera_locked;
|
bool camera_locked;
|
||||||
float camera[3] = {};
|
|
||||||
float range = 500.f;
|
|
||||||
float color[4] = {1.f, 0.f, 0.f, 1.f};
|
|
||||||
float mesh_thickness = 1.f;
|
|
||||||
float size = 10.f;
|
|
||||||
object_type type;
|
object_type type;
|
||||||
|
float mesh_thickness = 1.f;
|
||||||
|
float range = 500.f;
|
||||||
|
float camera[3] = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct : draw_settings
|
struct : draw_settings
|
||||||
{
|
{
|
||||||
|
bool draw_node_links;
|
||||||
|
float size = 10.f;
|
||||||
float link_thickness = 1.f;
|
float link_thickness = 1.f;
|
||||||
bool draw_linked_nodes;
|
float color[4] = {1.f, 0.f, 0.f, 1.f};
|
||||||
} path_node_settings{};
|
} path_node_settings{};
|
||||||
|
|
||||||
|
struct : draw_settings
|
||||||
|
{
|
||||||
|
bool enabled_types[entity_type::count];
|
||||||
|
float type_colors[entity_type::count][4] =
|
||||||
|
{
|
||||||
|
{0.f, 0.5f, 1.f, 0.3f},
|
||||||
|
{0.f, 1.f, 0.f, 0.3f},
|
||||||
|
{1.0f, 1.f, 0.f, 0.3f},
|
||||||
|
{1.f, 0.5f, 1.f, 0.3f},
|
||||||
|
};
|
||||||
|
bool mesh_only = false;
|
||||||
|
int point_count = 30;
|
||||||
|
} entity_bound_settings{};
|
||||||
|
|
||||||
|
struct point
|
||||||
|
{
|
||||||
|
ImVec2 point;
|
||||||
|
bool valid;
|
||||||
|
};
|
||||||
|
|
||||||
float vector_dot(float* a, float* b)
|
float vector_dot(float* a, float* b)
|
||||||
{
|
{
|
||||||
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
|
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
|
||||||
@ -72,7 +102,7 @@ namespace gui_debug
|
|||||||
vector_dot(local, axis[0])
|
vector_dot(local, axis[0])
|
||||||
};
|
};
|
||||||
|
|
||||||
if (transform[2] < 0.1f)
|
if (transform[2] < 0.01f)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -147,7 +177,8 @@ namespace gui_debug
|
|||||||
window->DrawList->AddConvexPolyFilled(points, 4, color_);
|
window->DrawList->AddConvexPolyFilled(points, 4, color_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_square_from_points(float* p1, float* p2, float* p3, float* p4, float* color)
|
void draw_square_from_points(float* p1, float* p2, float* p3, float* p4, float* color,
|
||||||
|
float thickness, bool mesh_only)
|
||||||
{
|
{
|
||||||
float p1_screen[2] = {};
|
float p1_screen[2] = {};
|
||||||
float p2_screen[2] = {};
|
float p2_screen[2] = {};
|
||||||
@ -176,10 +207,25 @@ namespace gui_debug
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto color_ = ImGui::GetColorU32({color[0], color[1], color[2], color[3]});
|
const auto color_ = ImGui::GetColorU32({color[0], color[1], color[2], color[3]});
|
||||||
window->DrawList->AddConvexPolyFilled(points, 4, color_);
|
|
||||||
|
window->DrawList->PathClear();
|
||||||
|
window->DrawList->PathLineTo(ImVec2(p1_screen[0], p1_screen[1]));
|
||||||
|
window->DrawList->PathLineTo(ImVec2(p2_screen[0], p2_screen[1]));
|
||||||
|
window->DrawList->PathLineTo(ImVec2(p3_screen[0], p3_screen[1]));
|
||||||
|
window->DrawList->PathLineTo(ImVec2(p4_screen[0], p4_screen[1]));
|
||||||
|
window->DrawList->PathLineTo(ImVec2(p1_screen[0], p1_screen[1]));
|
||||||
|
|
||||||
|
if (mesh_only)
|
||||||
|
{
|
||||||
|
window->DrawList->PathStroke(color_, 0, thickness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->DrawList->PathFillConvex(color_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_cube(float* origin, float width, float* color)
|
void draw_cube(float* origin, float width, float* color, float thickness, bool mesh_only)
|
||||||
{
|
{
|
||||||
const auto half = width / 2.f;
|
const auto half = width / 2.f;
|
||||||
|
|
||||||
@ -193,94 +239,174 @@ namespace gui_debug
|
|||||||
float p3_top[3] = {p3[0], p3[1], origin[2] + width};
|
float p3_top[3] = {p3[0], p3[1], origin[2] + width};
|
||||||
float p4_top[3] = {p4[0], p4[1], origin[2] + width};
|
float p4_top[3] = {p4[0], p4[1], origin[2] + width};
|
||||||
|
|
||||||
draw_square_from_points(p1, p2, p3, p4, color);
|
draw_square_from_points(p1, p2, p3, p4, color, thickness, mesh_only);
|
||||||
draw_square_from_points(p1_top, p2_top, p3_top, p4_top, color);
|
draw_square_from_points(p1_top, p2_top, p3_top, p4_top, color, thickness, mesh_only);
|
||||||
|
|
||||||
draw_square_from_points(p3, p2, p2_top, p3_top, color);
|
draw_square_from_points(p3, p2, p2_top, p3_top, color, thickness, mesh_only);
|
||||||
draw_square_from_points(p4, p1, p1_top, p4_top, color);
|
draw_square_from_points(p4, p1, p1_top, p4_top, color, thickness, mesh_only);
|
||||||
|
|
||||||
draw_square_from_points(p1, p2, p2_top, p1_top, color);
|
draw_square_from_points(p1, p2, p2_top, p1_top, color, thickness, mesh_only);
|
||||||
draw_square_from_points(p4, p3, p3_top, p4_top, color);
|
draw_square_from_points(p4, p3, p3_top, p4_top, color, thickness, mesh_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_cube_mesh(float* origin, float width, float* color, float thickness)
|
float get_pi()
|
||||||
{
|
{
|
||||||
const auto half = width / 2.f;
|
static const auto pi = static_cast<float>(atan(1)) * 4.f;
|
||||||
|
return pi;
|
||||||
float p1[3] = {origin[0] - half, origin[1] + half, origin[2]};
|
|
||||||
float p2[3] = {origin[0] + half, origin[1] + half, origin[2]};
|
|
||||||
float p3[3] = {origin[0] + half, origin[1] - half, origin[2]};
|
|
||||||
float p4[3] = {origin[0] - half, origin[1] - half, origin[2]};
|
|
||||||
|
|
||||||
float p1_top[3] = {p1[0], p1[1], origin[2] + width};
|
|
||||||
float p2_top[3] = {p2[0], p2[1], origin[2] + width};
|
|
||||||
float p3_top[3] = {p3[0], p3[1], origin[2] + width};
|
|
||||||
float p4_top[3] = {p4[0], p4[1], origin[2] + width};
|
|
||||||
|
|
||||||
draw_line(p1, p2, color, thickness);
|
|
||||||
draw_line(p2, p3, color, thickness);
|
|
||||||
draw_line(p3, p4, color, thickness);
|
|
||||||
draw_line(p4, p1, color, thickness);
|
|
||||||
|
|
||||||
draw_line(p1_top, p2_top, color, thickness);
|
|
||||||
draw_line(p2_top, p3_top, color, thickness);
|
|
||||||
draw_line(p3_top, p4_top, color, thickness);
|
|
||||||
draw_line(p4_top, p1_top, color, thickness);
|
|
||||||
|
|
||||||
draw_line(p1, p1_top, color, thickness);
|
|
||||||
draw_line(p2, p2_top, color, thickness);
|
|
||||||
draw_line(p3, p3_top, color, thickness);
|
|
||||||
draw_line(p4, p4_top, color, thickness);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_square_native(float* origin, float width, float* color)
|
void draw_cylinder(float* center, float radius, float height, int point_count, float* color,
|
||||||
|
float thickness, bool mesh_only)
|
||||||
{
|
{
|
||||||
const auto half = width / 2.f;
|
const auto pi = get_pi();
|
||||||
|
|
||||||
float p1[3] = {origin[0] - half, origin[1] + half, origin[2]};
|
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||||
float p2[3] = {origin[0] + half, origin[1] + half, origin[2]};
|
const auto color_ = ImGui::GetColorU32({color[0], color[1], color[2], color[3]});
|
||||||
float p3[3] = {origin[0] + half, origin[1] - half, origin[2]};
|
|
||||||
float p4[3] = {origin[0] - half, origin[1] - half, origin[2]};
|
|
||||||
|
|
||||||
float p1_screen[2] = {};
|
point_count = std::max(0, std::min(point_count, 360));
|
||||||
float p2_screen[2] = {};
|
const auto step = 360.f / point_count;
|
||||||
float p3_screen[2] = {};
|
|
||||||
float p4_screen[2] = {};
|
point points_top[360];
|
||||||
|
point points_bottom[360];
|
||||||
|
|
||||||
|
auto point_index = 0;
|
||||||
|
for (auto angle = 0.f; angle < 360.f; angle += step)
|
||||||
|
{
|
||||||
|
const auto x = center[0] + radius * cos(static_cast<float>(angle) * pi / 180.f);
|
||||||
|
const auto y = center[1] + radius * sin(static_cast<float>(angle) * pi / 180.f);
|
||||||
|
|
||||||
|
float point[3] = {x, y, center[2]};
|
||||||
|
float point_top[3] = {x, y, center[2] + height};
|
||||||
|
|
||||||
|
float point_screen[2] = {};
|
||||||
|
float point_top_screen[2] = {};
|
||||||
|
|
||||||
|
const auto index = point_index++;
|
||||||
|
|
||||||
auto result = 1;
|
auto result = 1;
|
||||||
result *= world_pos_to_screen_pos(p1, p1_screen);
|
result *= world_pos_to_screen_pos(point, point_screen);
|
||||||
result *= world_pos_to_screen_pos(p2, p2_screen);
|
result *= world_pos_to_screen_pos(point_top, point_top_screen);
|
||||||
result *= world_pos_to_screen_pos(p3, p3_screen);
|
|
||||||
result *= world_pos_to_screen_pos(p4, p4_screen);
|
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return;
|
points_bottom[index] = {{}, false};
|
||||||
|
points_top[index] = {{}, false};
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::rectangle rect;
|
points_bottom[index] = {ImVec2(point_screen[0], point_screen[1]), true};
|
||||||
rect.p0.x = p1_screen[0];
|
points_top[index] = {ImVec2(point_top_screen[0], point_top_screen[1]), true};
|
||||||
rect.p0.y = p1_screen[1];
|
}
|
||||||
rect.p0.f2 = 0.f;
|
|
||||||
rect.p0.f3 = 1.f;
|
|
||||||
|
|
||||||
rect.p1.x = p2_screen[0];
|
window->DrawList->PathClear();
|
||||||
rect.p1.y = p2_screen[1];
|
for (auto i = 0; i < point_count; i++)
|
||||||
rect.p1.f2 = 0.f;
|
{
|
||||||
rect.p1.f3 = 1.f;
|
if (!points_bottom[i].valid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
rect.p2.x = p3_screen[0];
|
window->DrawList->PathLineTo(points_bottom[i].point);
|
||||||
rect.p2.y = p3_screen[1];
|
}
|
||||||
rect.p2.f2 = 0.f;
|
|
||||||
rect.p2.f3 = 1.f;
|
|
||||||
|
|
||||||
rect.p3.x = p4_screen[0];
|
if (mesh_only)
|
||||||
rect.p3.y = p4_screen[1];
|
{
|
||||||
rect.p3.f2 = 0.f;
|
window->DrawList->PathStroke(color_, 0, thickness);
|
||||||
rect.p3.f3 = 1.f;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->DrawList->PathFillConvex(color_);
|
||||||
|
}
|
||||||
|
|
||||||
const auto material = game::Material_RegisterHandle("white");
|
window->DrawList->PathClear();
|
||||||
game::R_DrawRectangle(&rect, 0.f, 0.f, 1.f, 1.f, color, material);
|
for (auto i = 0; i < point_count; i++)
|
||||||
|
{
|
||||||
|
if (!points_top[i].valid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->DrawList->PathLineTo(points_top[i].point);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh_only)
|
||||||
|
{
|
||||||
|
window->DrawList->PathStroke(color_, 0, thickness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->DrawList->PathFillConvex(color_);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < point_count; i++)
|
||||||
|
{
|
||||||
|
window->DrawList->PathClear();
|
||||||
|
|
||||||
|
if (!points_bottom[i].valid ||
|
||||||
|
!points_top[i].valid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->DrawList->PathLineTo(points_bottom[i].point);
|
||||||
|
|
||||||
|
if (i == point_count - 1)
|
||||||
|
{
|
||||||
|
if (!points_bottom[0].valid || !points_top[0].valid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->DrawList->PathLineTo(points_bottom[0].point);
|
||||||
|
window->DrawList->PathLineTo(points_top[0].point);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!points_bottom[i + 1].valid || !points_top[i + 1].valid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->DrawList->PathLineTo(points_bottom[i + 1].point);
|
||||||
|
window->DrawList->PathLineTo(points_top[i + 1].point);
|
||||||
|
}
|
||||||
|
|
||||||
|
window->DrawList->PathLineTo(points_top[i].point);
|
||||||
|
|
||||||
|
if (mesh_only)
|
||||||
|
{
|
||||||
|
window->DrawList->PathStroke(color_, 0, thickness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->DrawList->PathFillConvex(color_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_rectangular_prism(float* center, game::Bounds bounds, float* color, float thickness, bool mesh_only)
|
||||||
|
{
|
||||||
|
float vertices[8][3] =
|
||||||
|
{
|
||||||
|
{center[0] - bounds.halfSize[0], center[1] - bounds.halfSize[1], center[2] - bounds.halfSize[2]},
|
||||||
|
{center[0] - bounds.halfSize[0], center[1] + bounds.halfSize[1], center[2] - bounds.halfSize[2]},
|
||||||
|
{center[0] + bounds.halfSize[0], center[1] + bounds.halfSize[1], center[2] - bounds.halfSize[2]},
|
||||||
|
{center[0] + bounds.halfSize[0], center[1] - bounds.halfSize[1], center[2] - bounds.halfSize[2]},
|
||||||
|
|
||||||
|
{center[0] - bounds.halfSize[0], center[1] - bounds.halfSize[1], center[2] + bounds.halfSize[2]},
|
||||||
|
{center[0] - bounds.halfSize[0], center[1] + bounds.halfSize[1], center[2] + bounds.halfSize[2]},
|
||||||
|
{center[0] + bounds.halfSize[0], center[1] + bounds.halfSize[1], center[2] + bounds.halfSize[2]},
|
||||||
|
{center[0] + bounds.halfSize[0], center[1] - bounds.halfSize[1], center[2] + bounds.halfSize[2]},
|
||||||
|
};
|
||||||
|
|
||||||
|
draw_square_from_points(vertices[0], vertices[1], vertices[2], vertices[3], color, thickness, mesh_only);
|
||||||
|
draw_square_from_points(vertices[4], vertices[5], vertices[6], vertices[7], color, thickness, mesh_only);
|
||||||
|
|
||||||
|
draw_square_from_points(vertices[0], vertices[4], vertices[5], vertices[1], color, thickness, mesh_only);
|
||||||
|
draw_square_from_points(vertices[7], vertices[6], vertices[2], vertices[3], color, thickness, mesh_only);
|
||||||
|
|
||||||
|
draw_square_from_points(vertices[6], vertices[5], vertices[1], vertices[2], color, thickness, mesh_only);
|
||||||
|
draw_square_from_points(vertices[7], vertices[4], vertices[0], vertices[3], color, thickness, mesh_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_window()
|
void draw_window()
|
||||||
@ -295,12 +421,9 @@ namespace gui_debug
|
|||||||
if (ImGui::TreeNode("Path nodes"))
|
if (ImGui::TreeNode("Path nodes"))
|
||||||
{
|
{
|
||||||
ImGui::Checkbox("Draw", &path_node_settings.enabled);
|
ImGui::Checkbox("Draw", &path_node_settings.enabled);
|
||||||
ImGui::Checkbox("Native rendering", &path_node_settings.native_rendering);
|
|
||||||
ImGui::Checkbox("Lock camera", &path_node_settings.camera_locked);
|
ImGui::Checkbox("Lock camera", &path_node_settings.camera_locked);
|
||||||
|
|
||||||
if (!path_node_settings.native_rendering)
|
ImGui::Checkbox("Draw node links", &path_node_settings.draw_node_links);
|
||||||
{
|
|
||||||
ImGui::Checkbox("Draw linked nodes", &path_node_settings.draw_linked_nodes);
|
|
||||||
|
|
||||||
if (ImGui::TreeNode("Object type"))
|
if (ImGui::TreeNode("Object type"))
|
||||||
{
|
{
|
||||||
@ -310,12 +433,11 @@ namespace gui_debug
|
|||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SliderFloat("range", &path_node_settings.range, 0.f, 10000.f);
|
ImGui::SliderFloat("range", &path_node_settings.range, 0.f, 10000.f);
|
||||||
ImGui::SliderFloat("size", &path_node_settings.size, 5.f, 100.f);
|
ImGui::SliderFloat("size", &path_node_settings.size, 5.f, 100.f);
|
||||||
|
|
||||||
if (path_node_settings.draw_linked_nodes)
|
if (path_node_settings.draw_node_links)
|
||||||
{
|
{
|
||||||
ImGui::SliderFloat("link thickness", &path_node_settings.link_thickness, 1.f, 20.f);
|
ImGui::SliderFloat("link thickness", &path_node_settings.link_thickness, 1.f, 20.f);
|
||||||
}
|
}
|
||||||
@ -334,6 +456,51 @@ namespace gui_debug
|
|||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::TreeNode("Entity bounds"))
|
||||||
|
{
|
||||||
|
ImGui::Checkbox("Draw", &entity_bound_settings.enabled);
|
||||||
|
ImGui::Checkbox("Lock camera", &entity_bound_settings.camera_locked);
|
||||||
|
|
||||||
|
if (ImGui::TreeNode("Types"))
|
||||||
|
{
|
||||||
|
ImGui::Checkbox("trigger_radius", &entity_bound_settings.enabled_types[entity_type::trigger_radius]);
|
||||||
|
if (entity_bound_settings.enabled_types[entity_type::trigger_radius] && ImGui::TreeNode("Color picker"))
|
||||||
|
{
|
||||||
|
ImGui::ColorPicker4("color", entity_bound_settings.type_colors[entity_type::trigger_radius]);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Checkbox("generic trigger", &entity_bound_settings.enabled_types[entity_type::generic_trigger]);
|
||||||
|
if (entity_bound_settings.enabled_types[entity_type::generic_trigger] && ImGui::TreeNode("Color picker"))
|
||||||
|
{
|
||||||
|
ImGui::ColorPicker4("color", entity_bound_settings.type_colors[entity_type::generic_trigger]);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Checkbox("actor", &entity_bound_settings.enabled_types[entity_type::actor]);
|
||||||
|
if (entity_bound_settings.enabled_types[entity_type::actor] && ImGui::TreeNode("Color picker"))
|
||||||
|
{
|
||||||
|
ImGui::ColorPicker4("color", entity_bound_settings.type_colors[entity_type::actor]);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Checkbox("other entities", &entity_bound_settings.enabled_types[entity_type::other]);
|
||||||
|
if (entity_bound_settings.enabled_types[entity_type::other] && ImGui::TreeNode("Color picker"))
|
||||||
|
{
|
||||||
|
ImGui::ColorPicker4("color", entity_bound_settings.type_colors[entity_type::other]);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SliderFloat("range", &entity_bound_settings.range, 0.f, 10000.f);
|
||||||
|
ImGui::SliderFloat("mesh thickness", &entity_bound_settings.mesh_thickness, 1.f, 20.f);
|
||||||
|
ImGui::Checkbox("mesh only", &entity_bound_settings.mesh_only);
|
||||||
|
ImGui::SliderInt("circle max points", &entity_bound_settings.point_count, 3, 360);
|
||||||
|
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +518,7 @@ namespace gui_debug
|
|||||||
game::PathNode_WorldifyPosFromParent(node, out);
|
game::PathNode_WorldifyPosFromParent(node, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_linked_nodes(game::pathnode_t* node, float* origin)
|
void draw_node_links(game::pathnode_t* node, float* origin)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < node->totalLinkCount; i++)
|
for (unsigned int i = 0; i < node->totalLinkCount; i++)
|
||||||
{
|
{
|
||||||
@ -368,31 +535,8 @@ namespace gui_debug
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_node_object(float* origin)
|
void begin_render_window()
|
||||||
{
|
{
|
||||||
switch (path_node_settings.type)
|
|
||||||
{
|
|
||||||
case object_type::square:
|
|
||||||
draw_square(origin, path_node_settings.size, path_node_settings.color);
|
|
||||||
break;
|
|
||||||
case object_type::cube:
|
|
||||||
draw_cube(origin, path_node_settings.size, path_node_settings.color);
|
|
||||||
break;
|
|
||||||
case object_type::cube_mesh:
|
|
||||||
draw_cube_mesh(origin, path_node_settings.size, path_node_settings.color,
|
|
||||||
path_node_settings.mesh_thickness);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_nodes()
|
|
||||||
{
|
|
||||||
if (!game::SV_Loaded() || path_node_settings.native_rendering ||
|
|
||||||
!path_node_settings.enabled || cl_paused->current.integer)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& io = ImGui::GetIO();
|
const auto& io = ImGui::GetIO();
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
@ -402,6 +546,24 @@ namespace gui_debug
|
|||||||
|
|
||||||
ImGui::SetWindowPos(ImVec2(0, 0), ImGuiCond_Always);
|
ImGui::SetWindowPos(ImVec2(0, 0), ImGuiCond_Always);
|
||||||
ImGui::SetWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y), ImGuiCond_Always);
|
ImGui::SetWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y), ImGuiCond_Always);
|
||||||
|
}
|
||||||
|
|
||||||
|
void end_render_window()
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||||
|
window->DrawList->PushClipRectFullScreen();
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::PopStyleVar(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_nodes()
|
||||||
|
{
|
||||||
|
if (!path_node_settings.enabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < game::pathData->nodeCount; i++)
|
for (unsigned int i = 0; i < game::pathData->nodeCount; i++)
|
||||||
{
|
{
|
||||||
@ -414,19 +576,88 @@ namespace gui_debug
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_node_object(origin);
|
switch (path_node_settings.type)
|
||||||
if (path_node_settings.draw_linked_nodes)
|
|
||||||
{
|
{
|
||||||
draw_linked_nodes(node, origin);
|
case object_type::square:
|
||||||
|
draw_square(origin, path_node_settings.size, path_node_settings.color);
|
||||||
|
break;
|
||||||
|
case object_type::cube_mesh:
|
||||||
|
case object_type::cube:
|
||||||
|
draw_cube(origin, path_node_settings.size, path_node_settings.color,
|
||||||
|
path_node_settings.mesh_thickness, path_node_settings.type == object_type::cube_mesh);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_node_settings.draw_node_links)
|
||||||
|
{
|
||||||
|
draw_node_links(node, origin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
entity_type get_entity_type(const char* classname)
|
||||||
window->DrawList->PushClipRectFullScreen();
|
{
|
||||||
|
if (strstr(classname, "trigger_radius"))
|
||||||
|
{
|
||||||
|
return entity_type::trigger_radius;
|
||||||
|
}
|
||||||
|
else if (strstr(classname, "trigger"))
|
||||||
|
{
|
||||||
|
return entity_type::generic_trigger;
|
||||||
|
}
|
||||||
|
else if (strstr(classname, "actor"))
|
||||||
|
{
|
||||||
|
return entity_type::actor;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::End();
|
return entity_type::other;
|
||||||
ImGui::PopStyleColor();
|
}
|
||||||
ImGui::PopStyleVar(2);
|
|
||||||
|
void draw_triggers()
|
||||||
|
{
|
||||||
|
if (!entity_bound_settings.enabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < *game::num_entities; i++)
|
||||||
|
{
|
||||||
|
const auto entity = &game::g_entities[i];
|
||||||
|
const auto origin = entity->origin;
|
||||||
|
|
||||||
|
const auto distance = distance_2d(entity_bound_settings.camera, origin);
|
||||||
|
const auto* classname = game::SL_ConvertToString(entity->script_classname);
|
||||||
|
|
||||||
|
if (distance > entity_bound_settings.range || !classname)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto type = get_entity_type(classname);
|
||||||
|
if (!entity_bound_settings.enabled_types[type])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case entity_type::trigger_radius:
|
||||||
|
{
|
||||||
|
const auto radius = entity->box.halfSize[0];
|
||||||
|
const auto height = entity->box.halfSize[2] * 2.f;
|
||||||
|
|
||||||
|
draw_cylinder(origin, radius, height, entity_bound_settings.point_count,
|
||||||
|
entity_bound_settings.type_colors[type], entity_bound_settings.mesh_thickness, entity_bound_settings.mesh_only);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
draw_rectangular_prism(origin, entity->box, entity_bound_settings.type_colors[type],
|
||||||
|
entity_bound_settings.mesh_thickness, entity_bound_settings.mesh_only);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_camera()
|
void update_camera()
|
||||||
@ -453,32 +684,12 @@ namespace gui_debug
|
|||||||
path_node_settings.camera[1] = camera[1];
|
path_node_settings.camera[1] = camera[1];
|
||||||
path_node_settings.camera[2] = camera[2];
|
path_node_settings.camera[2] = camera[2];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void draw_nodes_native()
|
if (!entity_bound_settings.camera_locked)
|
||||||
{
|
{
|
||||||
if (!game::SV_Loaded() || !path_node_settings.enabled || cl_paused->current.integer)
|
entity_bound_settings.camera[0] = camera[0];
|
||||||
{
|
entity_bound_settings.camera[1] = camera[1];
|
||||||
return;
|
entity_bound_settings.camera[2] = camera[2];
|
||||||
}
|
|
||||||
|
|
||||||
update_camera();
|
|
||||||
|
|
||||||
if (!path_node_settings.native_rendering)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < game::pathData->nodeCount; i++)
|
|
||||||
{
|
|
||||||
float origin[3] = {};
|
|
||||||
const auto node = &game::pathData->nodes[i];
|
|
||||||
|
|
||||||
get_pathnode_origin(node, origin);
|
|
||||||
if (distance_2d(path_node_settings.camera, origin) < path_node_settings.range)
|
|
||||||
{
|
|
||||||
draw_square_native(origin, path_node_settings.size, path_node_settings.color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,14 +700,33 @@ namespace gui_debug
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
gui::on_frame(draw_window);
|
gui::on_frame(draw_window);
|
||||||
gui::on_frame(draw_nodes, true);
|
gui::on_frame([]()
|
||||||
|
{
|
||||||
|
if (!game::SV_Loaded() || cl_paused->current.integer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
scheduler::on_game_initialized([]()
|
begin_render_window();
|
||||||
|
draw_nodes();
|
||||||
|
draw_triggers();
|
||||||
|
end_render_window();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
scheduler::once([]()
|
||||||
{
|
{
|
||||||
cl_paused = game::Dvar_FindVar("cl_paused");
|
cl_paused = game::Dvar_FindVar("cl_paused");
|
||||||
});
|
}, scheduler::pipeline::main);
|
||||||
|
|
||||||
scheduler::loop(draw_nodes_native, scheduler::pipeline::renderer);
|
scheduler::loop([]()
|
||||||
|
{
|
||||||
|
if (!game::SV_Loaded() || cl_paused->current.integer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_camera();
|
||||||
|
}, scheduler::pipeline::renderer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -666,7 +666,7 @@ namespace entity_list
|
|||||||
ImGui::Text("Fields");
|
ImGui::Text("Fields");
|
||||||
|
|
||||||
auto index = 0;
|
auto index = 0;
|
||||||
for (auto i = data.filters.fields.begin(); i != data.filters.fields.end(); ++i)
|
for (auto i = data.filters.fields.begin(); i != data.filters.fields.end();)
|
||||||
{
|
{
|
||||||
if (ImGui::TreeNode(utils::string::va("Filter #%i", index++)))
|
if (ImGui::TreeNode(utils::string::va("Filter #%i", index++)))
|
||||||
{
|
{
|
||||||
@ -675,12 +675,15 @@ namespace entity_list
|
|||||||
|
|
||||||
if (ImGui::Button("Erase"))
|
if (ImGui::Button("Erase"))
|
||||||
{
|
{
|
||||||
data.filters.fields.erase(i);
|
i = data.filters.fields.erase(i);
|
||||||
--i;
|
ImGui::TreePop();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Button("Add field filter"))
|
if (ImGui::Button("Add field filter"))
|
||||||
|
@ -12,7 +12,7 @@ namespace game
|
|||||||
{
|
{
|
||||||
char __pad0[0x8C];
|
char __pad0[0x8C];
|
||||||
vec3_t velocity;
|
vec3_t velocity;
|
||||||
char __pad1[59504];
|
char __pad1[0xE870];
|
||||||
char flags;
|
char flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,23 +56,44 @@ namespace game
|
|||||||
char entityNum;
|
char entityNum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum scr_string_t
|
||||||
|
{
|
||||||
|
scr_string_t_dummy = 0x0,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Bounds
|
||||||
|
{
|
||||||
|
vec3_t midPoint;
|
||||||
|
vec3_t halfSize;
|
||||||
|
};
|
||||||
|
|
||||||
struct gentity_s
|
struct gentity_s
|
||||||
{
|
{
|
||||||
EntityState s;
|
EntityState s;
|
||||||
char __pad0[0x1B];
|
char __pad0[0x1B];
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
char __pad1[0xF0];
|
char __pad1[0x98];
|
||||||
|
Bounds box;
|
||||||
|
char __pad2[0x4];
|
||||||
|
Bounds absBox;
|
||||||
|
char __pad3[0x24];
|
||||||
gclient_s* client;
|
gclient_s* client;
|
||||||
char __pad2[0x4C];
|
char __pad4[0x30];
|
||||||
|
scr_string_t script_classname;
|
||||||
|
char __pad5[0x18];
|
||||||
char flags;
|
char flags;
|
||||||
char __pad3[392];
|
char __pad6[0x188];
|
||||||
}; // size = 760
|
}; // size = 760
|
||||||
|
|
||||||
|
//auto a = sizeof(gentity_s);
|
||||||
|
|
||||||
|
static_assert(sizeof(gentity_s) == 760);
|
||||||
|
|
||||||
struct pathlink_s
|
struct pathlink_s
|
||||||
{
|
{
|
||||||
char __pad0[4];
|
char __pad0[0x4];
|
||||||
unsigned __int16 nodeNum;
|
unsigned __int16 nodeNum;
|
||||||
char __pad[6];
|
char __pad[0x6];
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(pathlink_s) == 12);
|
static_assert(sizeof(pathlink_s) == 12);
|
||||||
@ -87,12 +108,12 @@ namespace game
|
|||||||
unsigned int target;
|
unsigned int target;
|
||||||
unsigned int animscript;
|
unsigned int animscript;
|
||||||
int animscriptfunc;
|
int animscriptfunc;
|
||||||
float vLocalOrigin[3];
|
float vLocalOrigin[0x3];
|
||||||
char __pad0[28];
|
char __pad0[0x1C];
|
||||||
unsigned __int16 totalLinkCount;
|
unsigned __int16 totalLinkCount;
|
||||||
char __pad1[2];
|
char __pad1[0x2];
|
||||||
pathlink_s* Links;
|
pathlink_s* Links;
|
||||||
char __pad2[104];
|
char __pad2[0x68];
|
||||||
}; // size = 192
|
}; // size = 192
|
||||||
|
|
||||||
static_assert(sizeof(pathnode_t) == 192);
|
static_assert(sizeof(pathnode_t) == 192);
|
||||||
@ -701,11 +722,6 @@ namespace game
|
|||||||
int freeFlags;
|
int freeFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum scr_string_t
|
|
||||||
{
|
|
||||||
scr_string_t_dummy = 0x0,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct scr_entref_t
|
struct scr_entref_t
|
||||||
{
|
{
|
||||||
unsigned short entnum;
|
unsigned short entnum;
|
||||||
@ -964,12 +980,6 @@ namespace game
|
|||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Bounds
|
|
||||||
{
|
|
||||||
vec3_t midPoint;
|
|
||||||
vec3_t halfSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pmove_t
|
struct pmove_t
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
@ -153,6 +153,7 @@ namespace game
|
|||||||
WEAK symbol<int> g_poolSize{0xBF2E40};
|
WEAK symbol<int> g_poolSize{0xBF2E40};
|
||||||
|
|
||||||
WEAK symbol<gentity_s> g_entities{0x52DDDA0};
|
WEAK symbol<gentity_s> g_entities{0x52DDDA0};
|
||||||
|
WEAK symbol<int> num_entities{0x55CC738};
|
||||||
WEAK symbol<PathData> pathData{0x52CCDA0};
|
WEAK symbol<PathData> pathData{0x52CCDA0};
|
||||||
|
|
||||||
WEAK symbol<DWORD> threadIds{0xB11DC80};
|
WEAK symbol<DWORD> threadIds{0xB11DC80};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user