feat: command executor (search bar) (#1029)
This commit is contained in:
parent
4af9c7f258
commit
10bbf1f4bb
@ -2,9 +2,10 @@
|
||||
|
||||
namespace big
|
||||
{
|
||||
bool_command::bool_command(const std::string& name, const std::string& label, const std::string& description, bool& toggle) :
|
||||
bool_command::bool_command(const std::string& name, const std::string& label, const std::string& description, bool& toggle, bool show_notify) :
|
||||
command(name, label, description, std::nullopt),
|
||||
m_toggle(toggle)
|
||||
m_toggle(toggle),
|
||||
m_show_notify(show_notify)
|
||||
{
|
||||
}
|
||||
|
||||
@ -15,11 +16,15 @@ namespace big
|
||||
if (is_enabled())
|
||||
{
|
||||
m_toggle = false;
|
||||
|
||||
if (m_show_notify)
|
||||
ctx->report_output(std::format("{} has been disabled", m_label));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_toggle = true;
|
||||
|
||||
if (m_show_notify)
|
||||
ctx->report_output(std::format("{} has been enabled", m_label));
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,12 @@ namespace big
|
||||
{
|
||||
protected:
|
||||
bool& m_toggle;
|
||||
bool m_show_notify;
|
||||
virtual void execute(const std::vector<std::uint64_t>& args, const std::shared_ptr<command_context> ctx = std::make_shared<default_command_context>()) override;
|
||||
virtual std::optional<std::vector<std::uint64_t>> parse_args(const std::vector<std::string>& args, const std::shared_ptr<command_context> ctx = std::make_shared<default_command_context>()) override;
|
||||
|
||||
public:
|
||||
bool_command(const std::string& name, const std::string& label, const std::string& description, bool& toggle);
|
||||
bool_command(const std::string& name, const std::string& label, const std::string& description, bool& toggle, bool show_notify = true);
|
||||
inline bool& is_enabled()
|
||||
{
|
||||
return m_toggle;
|
||||
|
@ -99,23 +99,85 @@ namespace big
|
||||
g_commands[command]->call(args, ctx);
|
||||
}
|
||||
|
||||
void command::process(const std::string& text, const std::shared_ptr<command_context> ctx)
|
||||
std::vector<command*> command::get_suggestions(std::string search, const int limit)
|
||||
{
|
||||
auto args = split(text, ' ');
|
||||
std::vector<command*> result_cmds{};
|
||||
for (auto& [hash, command] : g_commands)
|
||||
{
|
||||
if (command->get_label().length() == 0)
|
||||
continue;
|
||||
|
||||
std::string cmd_name = command->get_name();
|
||||
std::string cmd_label = command->get_label();
|
||||
|
||||
//transform all strings to lower case
|
||||
std::transform(cmd_name.begin(), cmd_name.end(), cmd_name.begin(), tolower);
|
||||
std::transform(cmd_label.begin(), cmd_label.end(), cmd_label.begin(), tolower);
|
||||
std::transform(search.begin(), search.end(), search.begin(), tolower);
|
||||
|
||||
for (auto& cmd : split(search, ';'))
|
||||
{
|
||||
std::string search_label = split(cmd, ' ')[0];
|
||||
|
||||
if (cmd_name.contains(search_label))
|
||||
result_cmds.push_back(command);
|
||||
else if (cmd_label.contains(search_label))
|
||||
result_cmds.push_back(command);
|
||||
}
|
||||
|
||||
// apply our maximum vector size..
|
||||
if (result_cmds.size() >= limit)
|
||||
break;
|
||||
}
|
||||
|
||||
return result_cmds;
|
||||
}
|
||||
|
||||
bool command::process(const std::string& text, const std::shared_ptr<command_context> ctx, bool use_best_suggestion)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
for (auto& cmd : split(text, ';'))
|
||||
{
|
||||
auto args = split(cmd, ' ');
|
||||
if (args.size() == 0 || args[0].empty())
|
||||
{
|
||||
ctx->report_error("No command to call");
|
||||
return;
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
//build the best command based on the input
|
||||
if (use_best_suggestion)
|
||||
{
|
||||
const auto cmd_suggestions = get_suggestions(args[0]);
|
||||
|
||||
//is valid suggestion
|
||||
if (cmd_suggestions.size() >= 1)
|
||||
{
|
||||
args[0] = cmd_suggestions[0]->get_name();
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->report_error(std::format("Command {} does not exist", args[0]));
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::uint32_t hash = rage::joaat(args[0]);
|
||||
if (!g_commands.contains(hash))
|
||||
{
|
||||
ctx->report_error(std::format("Command {} does not exist", args[0]));
|
||||
return;
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
args.erase(args.begin());
|
||||
call(hash, args, ctx);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
@ -39,16 +39,21 @@ namespace big
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
inline const std::optional<std::uint8_t>& get_num_args()
|
||||
{
|
||||
return m_num_args;
|
||||
}
|
||||
|
||||
void call(const std::vector<std::uint64_t>& args, const std::shared_ptr<command_context> ctx = std::make_shared<default_command_context>());
|
||||
void call(const std::vector<std::string>& args, const std::shared_ptr<command_context> ctx = std::make_shared<default_command_context>());
|
||||
static std::vector<command*> get_suggestions(std::string, int limit = 7);
|
||||
|
||||
static command* get(rage::joaat_t command);
|
||||
|
||||
static void call(rage::joaat_t command, const std::vector<std::uint64_t>& args, const std::shared_ptr<command_context> ctx = std::make_shared<default_command_context>());
|
||||
static void call(rage::joaat_t command, const std::vector<std::string>& args, const std::shared_ptr<command_context> ctx = std::make_shared<default_command_context>());
|
||||
|
||||
static void process(const std::string& text, const std::shared_ptr<command_context> ctx = std::make_shared<default_command_context>());
|
||||
static bool process(const std::string& text, const std::shared_ptr<command_context> ctx = std::make_shared<default_command_context>(), bool use_best_suggestion = false);
|
||||
};
|
||||
|
||||
inline std::unordered_map<rage::joaat_t, command*> g_commands;
|
||||
|
@ -366,4 +366,10 @@ namespace big
|
||||
{CommandAccessLevel::TOXIC, "toxic"},
|
||||
{CommandAccessLevel::ADMIN, "admin"},
|
||||
})
|
||||
|
||||
enum eKeyState : unsigned int
|
||||
{
|
||||
RELEASE = WM_KEYUP,
|
||||
DOWN = WM_KEYDOWN
|
||||
};
|
||||
}
|
||||
|
@ -64,8 +64,12 @@ namespace big
|
||||
|
||||
rage::scrThread* m_mission_creator_thread = nullptr;
|
||||
|
||||
rage::scrThread* m_modshop_thread = nullptr;
|
||||
struct cmd_executor
|
||||
{
|
||||
bool enabled = false;
|
||||
} cmd_executor{};
|
||||
|
||||
rage::scrThread* m_modshop_thread = nullptr;
|
||||
bool in_script_vm = false;
|
||||
|
||||
struct debug
|
||||
@ -377,8 +381,9 @@ namespace big
|
||||
int invisveh = 0;
|
||||
int localinvisveh = 0;
|
||||
int fast_quit = 0;
|
||||
int cmd_excecutor = 0x55; // U
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(hotkeys, editing_menu_toggle, menu_toggle, teleport_waypoint, teleport_objective, noclip, bringvehicle, invis, heal, fill_inventory, skip_cutscene, freecam, superrun, superjump, beastjump, invisveh, localinvisveh, fast_quit)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(hotkeys, editing_menu_toggle, menu_toggle, teleport_waypoint, teleport_objective, noclip, bringvehicle, invis, heal, fill_inventory, skip_cutscene, freecam, superrun, superjump, beastjump, invisveh, localinvisveh, fast_quit, cmd_excecutor)
|
||||
} hotkeys{};
|
||||
|
||||
bool dev_dlc = false;
|
||||
|
25
src/gui.cpp
25
src/gui.cpp
@ -4,6 +4,7 @@
|
||||
#include "natives.hpp"
|
||||
#include "renderer.hpp"
|
||||
#include "script.hpp"
|
||||
#include "util/is_key_pressed.hpp"
|
||||
#include "views/view.hpp"
|
||||
|
||||
#include <imgui.h>
|
||||
@ -13,14 +14,15 @@ namespace big
|
||||
gui::gui() :
|
||||
m_is_open(false)
|
||||
{
|
||||
g_renderer->add_dx_callback(view::gta_data, -1); // -1 highest priority of drawing
|
||||
g_renderer->add_dx_callback(view::notifications, -2);// second highest priority
|
||||
g_renderer->add_dx_callback(view::overlay, -3); // 3rd highest priority
|
||||
g_renderer->add_dx_callback(view::gta_data, -1);
|
||||
g_renderer->add_dx_callback(view::notifications, -2);
|
||||
g_renderer->add_dx_callback(view::overlay, -3);
|
||||
g_renderer->add_dx_callback(view::cmd_executor, -4);
|
||||
g_renderer->add_dx_callback(
|
||||
[this] {
|
||||
dx_on_tick();
|
||||
},
|
||||
-4);// 4th highest priority
|
||||
-5);
|
||||
|
||||
g_renderer->add_wndproc_callback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
wndproc(hwnd, msg, wparam, lparam);
|
||||
@ -161,6 +163,21 @@ namespace big
|
||||
PAD::DISABLE_CONTROL_ACTION(2, 262, true);
|
||||
PAD::DISABLE_CONTROL_ACTION(2, 331, true);
|
||||
}
|
||||
|
||||
//wndproc will not work here. the timing here is very difficult. mayby can we hook the creation of the pause menu?
|
||||
//this should be improved..
|
||||
if (is_key_pressed(VK_ESCAPE) && g.cmd_executor.enabled)
|
||||
{
|
||||
g_fiber_pool->queue_job([] {
|
||||
g.cmd_executor.enabled = false;
|
||||
//50 should run stable, IMPROVE THIS!!!
|
||||
for (uint8_t i = 0; i <= 50; i++)
|
||||
{
|
||||
HUD::SET_PAUSE_MENU_ACTIVE(false);
|
||||
script::get_current()->yield();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void gui::script_func()
|
||||
|
@ -172,11 +172,9 @@ namespace big
|
||||
for (const auto& cb : m_wndproc_callbacks)
|
||||
cb(hwnd, msg, wparam, lparam);
|
||||
|
||||
if (g_gui->is_open())
|
||||
{
|
||||
|
||||
ImGui_ImplWin32_WndProcHandler(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
}
|
||||
|
||||
void renderer::new_frame()
|
||||
{
|
||||
|
@ -24,6 +24,8 @@ namespace big
|
||||
register_hotkey("invisveh", g.settings.hotkeys.invisveh, RAGE_JOAAT("invisveh"));
|
||||
register_hotkey("localinvisveh", g.settings.hotkeys.localinvisveh, RAGE_JOAAT("localinvisveh"));
|
||||
register_hotkey("fastquit", g.settings.hotkeys.fast_quit, RAGE_JOAAT("fastquit"));
|
||||
register_hotkey("quicksearch", g.settings.hotkeys.cmd_excecutor, RAGE_JOAAT("cmdexecutor"));
|
||||
|
||||
|
||||
g_renderer->add_wndproc_callback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
wndproc(static_cast<eKeyState>(msg), wparam);
|
||||
@ -70,6 +72,10 @@ namespace big
|
||||
if (const auto chat_data = *g_pointers->m_chat_data; chat_data && (chat_data->m_chat_open || chat_data->m_timer_two))
|
||||
return;
|
||||
|
||||
//command executer is opened
|
||||
if (g.cmd_executor.enabled)
|
||||
return;
|
||||
|
||||
if (g_gui->is_open())
|
||||
return;
|
||||
|
||||
|
@ -1,15 +1,10 @@
|
||||
#pragma once
|
||||
#include "common.hpp"
|
||||
#include "core/enums.hpp"
|
||||
#include "hotkey.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
enum eKeyState : unsigned int
|
||||
{
|
||||
RELEASE = WM_KEYUP,
|
||||
DOWN = WM_KEYDOWN
|
||||
};
|
||||
|
||||
using hotkey_map = std::multimap<key_t, hotkey>;
|
||||
|
||||
class hotkey_service final
|
||||
|
@ -29,5 +29,6 @@ namespace big
|
||||
g_gui_service->get_selected()->func();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
72
src/views/core/view_cmd_executor.cpp
Normal file
72
src/views/core/view_cmd_executor.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include "backend/context/default_command_context.hpp"
|
||||
#include "gui.hpp"
|
||||
#include "pointers.hpp"
|
||||
#include "services/hotkey/hotkey_service.hpp"
|
||||
#include "views/view.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
void view::cmd_executor()
|
||||
{
|
||||
if (!g.cmd_executor.enabled)
|
||||
return;
|
||||
|
||||
float screen_x = (float)*g_pointers->m_resolution_x;
|
||||
float screen_y = (float)*g_pointers->m_resolution_y;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(screen_x * 0.25f, screen_y * 0.2f), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSize({screen_x * 0.5f, -1});
|
||||
|
||||
if (ImGui::Begin("cmd_executor", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
|
||||
{
|
||||
static char command_buffer[255];
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {10.f, 15.f});
|
||||
components::sub_title("CMD_EXECUTOR_TITLE"_T);
|
||||
|
||||
// set focus by default on input box
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
|
||||
ImGui::SetNextItemWidth(screen_x * 0.5f);
|
||||
components::input_text_with_hint("", "CMD_EXECUTOR_TYPE_CMD"_T, command_buffer, sizeof(command_buffer), ImGuiInputTextFlags_EnterReturnsTrue, [] {
|
||||
if (command::process(command_buffer, std::make_shared<default_command_context>(), true))
|
||||
{
|
||||
g.cmd_executor.enabled = false;
|
||||
command_buffer[0] = 0;
|
||||
}
|
||||
});
|
||||
|
||||
components::small_text("CMD_EXECUTOR_MULTIPLE_CMDS"_T);
|
||||
ImGui::Spacing();
|
||||
|
||||
auto possible_commands = command::get_suggestions(command_buffer);
|
||||
if (possible_commands.size() == 0)
|
||||
{
|
||||
ImGui::Text("CMD_EXECUTOR_NO_CMD"_T.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto cmd : possible_commands)
|
||||
{
|
||||
ImGui::Text(std::vformat("CMD_EXECUTOR_CMD_TEMPLATE"_T,
|
||||
std::make_format_args(cmd->get_name(),
|
||||
cmd->get_label(),
|
||||
cmd->get_description(),
|
||||
cmd->get_num_args() ? cmd->get_num_args().value() : 0))
|
||||
.data());
|
||||
|
||||
// check if we aren't on the last iteration
|
||||
if (cmd != possible_commands.back())
|
||||
ImGui::Separator();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool_command
|
||||
g_cmd_executor("cmdexecutor", "Toggle Command Executor", "Toggles the command executor window", g.cmd_executor.enabled, false);
|
||||
}
|
@ -35,5 +35,6 @@ namespace big
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ namespace big
|
||||
ImGui::SetNextWindowPos({10.f, 100.f * g.window.gui_scale}, ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize({300.f * g.window.gui_scale, 0.f}, ImGuiCond_Always);
|
||||
|
||||
if (ImGui::Begin("navigation", 0, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoNav))
|
||||
if (ImGui::Begin("navigation", 0, window_flags))
|
||||
{
|
||||
g_gui_service->reset_nav_size();
|
||||
for (std::pair<tabs, navigation_struct> navItem : g_gui_service->get_navigation())
|
||||
|
@ -42,6 +42,8 @@ namespace big
|
||||
g_hotkey_service->update_hotkey("localinvisveh", g.settings.hotkeys.localinvisveh);
|
||||
if (ImGui::Hotkey("Rage Quit (Like Alt + F4)", &g.settings.hotkeys.fast_quit))
|
||||
g_hotkey_service->update_hotkey("fastquit", g.settings.hotkeys.fast_quit);
|
||||
if (ImGui::Hotkey("Toggle Command Executor", &g.settings.hotkeys.cmd_excecutor))
|
||||
g_hotkey_service->update_hotkey("cmdexecutor", g.settings.hotkeys.cmd_excecutor);
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ namespace big
|
||||
static void player_kick();
|
||||
static void player_toxic();
|
||||
static void player_misc();
|
||||
static void cmd_executor();
|
||||
static void player_vehicle();
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user