Some fixes + set entity field window

This commit is contained in:
fed 2021-12-20 09:59:57 +01:00
parent 5c31d10e1f
commit 6e7e1c57ec
3 changed files with 333 additions and 172 deletions

View File

@ -72,15 +72,8 @@ namespace gui
{
if (ImGui::BeginMenu("Windows"))
{
if (ImGui::MenuItem("Asset list"))
{
toggle_menu("asset_list");
}
if (ImGui::MenuItem("Entity list"))
{
toggle_menu("entity_list");
}
ImGui::Checkbox("Asset list", &enabled_menus["asset_list"]);
ImGui::Checkbox("Entity list", &enabled_menus["entity_list"]);
ImGui::EndMenu();
}

View File

@ -19,6 +19,8 @@ namespace entity_list
{
namespace
{
game::dvar_t* sv_running = nullptr;
enum entity_type
{
type_any,
@ -70,6 +72,7 @@ namespace entity_list
std::chrono::milliseconds interval{};
std::chrono::high_resolution_clock::time_point last_call{};
std::vector<entity_info_t> entity_info{};
std::vector<std::function<void()>> tasks;
std::unordered_map<std::string, bool> selected_fields =
{
{"code_classname", false},
@ -277,6 +280,19 @@ namespace entity_list
};
utils::concurrency::container<data_t> data_;
unsigned int selected_entity{};
bool set_field_window{};
int selected_type = game::SCRIPT_INTEGER;
bool is_sv_running()
{
if (!sv_running)
{
return false;
}
return sv_running->current.enabled;
}
bool verify_entity(unsigned int id)
{
@ -368,6 +384,13 @@ namespace entity_list
{
data_.access([](data_t& data)
{
for (const auto& task : data.tasks)
{
task();
}
data.tasks = {};
const auto now = std::chrono::high_resolution_clock::now();
if (!data.force_update && (!data.auto_update || (now - data.last_call < data.interval)))
{
@ -455,9 +478,9 @@ namespace entity_list
});
}
void teleport_to(unsigned int id)
void teleport_to(data_t& data, unsigned int id)
{
scheduler::once([id]()
data.tasks.push_back([id]()
{
if (!verify_entity(id))
{
@ -473,12 +496,12 @@ namespace entity_list
const auto player = value.as<scripting::entity>();
player.call("setorigin", {dest.get("origin")});
}, scheduler::pipeline::server);
});
}
void teleport_to_reverse(unsigned int id)
void teleport_to_reverse(data_t& data, unsigned int id)
{
scheduler::once([id]()
data.tasks.push_back([id]()
{
if (!verify_entity(id))
{
@ -494,12 +517,12 @@ namespace entity_list
const auto player = value.as<scripting::entity>();
dest.set("origin", player.get("origin"));
}, scheduler::pipeline::server);
});
}
void delete_entity(unsigned int id)
void delete_entity(data_t& data, unsigned int id)
{
scheduler::once([id]()
data.tasks.push_back([id]()
{
if (!verify_entity(id))
{
@ -508,18 +531,129 @@ namespace entity_list
const auto target = scripting::entity{id};
target.call("delete");
}, scheduler::pipeline::server);
});
}
void on_frame()
void set_entity_field(data_t& data, unsigned int id,
const std::string& name, const std::string& string_value, int type)
{
if (!gui::enabled_menus["entity_list"])
data.tasks.push_back([id, name, type, string_value, &data]()
{
if (!verify_entity(id))
{
return;
}
data_.access([](data_t& data)
scripting::script_value value{};
if (type == game::SCRIPT_INTEGER)
{
value = atoi(string_value.data());
}
if (type == game::SCRIPT_FLOAT)
{
value = atof(string_value.data());
}
if (type == game::SCRIPT_STRING)
{
value = string_value;
}
try
{
scripting::set_entity_field(id, name, value);
data.force_update = true;
}
catch (...)
{
}
});
}
void set_entity_field_vector(data_t& data, unsigned int id,
const std::string& name, const scripting::vector& value)
{
data.tasks.push_back([id, name, value, &data]()
{
if (!verify_entity(id))
{
return;
}
try
{
scripting::set_entity_field(id, name, value);
data.force_update = true;
}
catch (...)
{
}
});
}
void show_set_field_window(data_t& data)
{
static char name[0x100]{};
static char value[0x100]{};
static char x[0x100]{};
static char y[0x100]{};
static char z[0x100]{};
ImGui::SetNextWindowSizeConstraints(ImVec2(300, 300), ImVec2(300, 300));
ImGui::Begin("Set entity field", &set_field_window);
ImGui::SetWindowSize(ImVec2(300, 300));
ImGui::Text(utils::string::va("Entity id %i", selected_entity));
if (ImGui::TreeNode("Type"))
{
ImGui::RadioButton("integer", &selected_type, game::SCRIPT_INTEGER);
ImGui::RadioButton("float", &selected_type, game::SCRIPT_FLOAT);
ImGui::RadioButton("vector", &selected_type, game::SCRIPT_VECTOR);
ImGui::RadioButton("string", &selected_type, game::SCRIPT_STRING);
ImGui::TreePop();
}
ImGui::InputText("name", name, IM_ARRAYSIZE(name));
if (selected_type == game::SCRIPT_VECTOR)
{
ImGui::InputText("x", x, IM_ARRAYSIZE(x));
ImGui::InputText("y", y, IM_ARRAYSIZE(y));
ImGui::InputText("z", z, IM_ARRAYSIZE(z));
}
else
{
ImGui::InputText("value", value, IM_ARRAYSIZE(value));
}
if (ImGui::Button("set", ImVec2(300, 0)))
{
if (selected_type == game::SCRIPT_VECTOR)
{
const scripting::vector vector
{
static_cast<float>(atof(x)),
static_cast<float>(atof(y)),
static_cast<float>(atof(z))
};
set_entity_field_vector(data, selected_entity, name, vector);
}
else
{
set_entity_field(data, selected_entity, name, value, selected_type);
}
}
ImGui::End();
}
void show_entity_list_window(data_t& data)
{
ImGui::SetNextWindowSizeConstraints(ImVec2(500, 500), ImVec2(1000, 1000));
ImGui::Begin("Entity list", &gui::enabled_menus["entity_list"]);
if (ImGui::Button("Update list"))
@ -619,21 +753,27 @@ namespace entity_list
{
ImGui::Text("Commands");
if (ImGui::Button("Set field"))
{
set_field_window = true;
selected_entity = info.id;
}
if (ImGui::Button("Teleport to"))
{
teleport_to(info.id);
teleport_to(data, info.id);
data.force_update = true;
}
if (ImGui::Button("Teleport to you"))
{
teleport_to_reverse(info.id);
teleport_to_reverse(data, info.id);
data.force_update = true;
}
if (info.num != 0 && ImGui::Button("Delete"))
{
delete_entity(info.id);
delete_entity(data, info.id);
data.force_update = true;
}
@ -679,6 +819,29 @@ namespace entity_list
}
ImGui::End();
}
void on_frame()
{
if (!gui::enabled_menus["entity_list"])
{
return;
}
data_.access([](data_t& data)
{
if (!is_sv_running())
{
selected_entity = 0;
data.entity_info = {};
data.tasks = {};
}
show_entity_list_window(data);
if (selected_entity && set_field_window)
{
show_set_field_window(data);
}
});
}
}
@ -688,6 +851,11 @@ namespace entity_list
public:
void post_unpack() override
{
scheduler::on_game_initialized([]()
{
sv_running = game::Dvar_FindVar("sv_running");
});
gui::on_frame(on_frame);
scheduler::loop(update_entity_list, scheduler::pipeline::server, 0ms);
}