This commit is contained in:
briaguya 2024-06-21 15:54:37 -04:00 committed by GitHub
commit 06793d6f86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 133 additions and 38 deletions

View File

@ -41,7 +41,7 @@
data-for="input_bindings, i : inputs.array" data-for="input_bindings, i : inputs.array"
data-event-mouseover="set_input_row_focus(i)" data-event-mouseover="set_input_row_focus(i)"
data-class-control-option--active="get_input_enum_name(i)==cur_input_row" data-class-control-option--active="get_input_enum_name(i)==cur_input_row"
data-if="!input_device_is_keyboard || get_input_enum_name(i) != 'TOGGLE_MENU'" data-if="!input_device_is_keyboard || (get_input_enum_name(i) != 'TOGGLE_MENU' && get_input_enum_name(i) != 'ACCEPT_MENU' && get_input_enum_name(i) != 'APPLY_MENU')"
> >
<label <label
class="control-option__label" class="control-option__label"
@ -67,6 +67,7 @@
</button> </button>
</div> </div>
<button <button
data-if="get_input_enum_name(i) != 'TOGGLE_MENU' && get_input_enum_name(i) != 'ACCEPT_MENU'"
data-event-blur="set_input_row_focus(-1)" data-event-blur="set_input_row_focus(-1)"
data-event-focus="set_input_row_focus(i)" data-event-focus="set_input_row_focus(i)"
data-event-click="clear_input_bindings(i)" data-event-click="clear_input_bindings(i)"
@ -75,6 +76,16 @@
> >
<svg src="icons/Trash.svg" /> <svg src="icons/Trash.svg" />
</button> </button>
<button
data-if="get_input_enum_name(i) == 'TOGGLE_MENU' || get_input_enum_name(i) == 'ACCEPT_MENU'"
data-event-blur="set_input_row_focus(-1)"
data-event-focus="set_input_row_focus(i)"
data-event-click="reset_single_input_binding_to_default(i)"
class="icon-button icon-button--danger"
data-attr-style="i == 0 ? 'nav-up:#cont_kb_toggle' : 'nav-up:auto'"
>
<svg src="icons/Reset.svg" />
</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -316,7 +316,7 @@
id="apply_button" id="apply_button"
style="nav-up:#hr_original" style="nav-up:#hr_original"
> >
<div class="button__label">Apply <span class="prompt-font-sm">{{gfx_help__apply}}</span></div> <div class="button__label">Apply<span class="prompt-font-sm">{{gfx_help__apply}}</span></div>
</button> </button>
</div> </div>
</div> </div>

1
assets/icons/Reset.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="40px" viewBox="0 -960 960 960" width="40px" fill="#e8eaed"><path d="M480-160q-133.33 0-226.67-93.33Q160-346.67 160-480q0-133.33 93.33-226.67Q346.67-800 480-800q79.67 0 143.33 32.5 63.67 32.5 110 90.17V-800H800v262.67H537.33V-604h168q-36-58.67-93.83-94T480-733.33q-106 0-179.67 73.66Q226.67-586 226.67-480q0 106 73.66 179.67Q374-226.67 480-226.67q81 0 147.67-46.33 66.66-46.33 93-122.33H790Q761.33-290 675.33-225q-86 65-195.33 65Z"/></svg>

After

Width:  |  Height:  |  Size: 486 B

View File

@ -40,7 +40,9 @@ namespace recomp {
DEFINE_INPUT(X_AXIS_POS, 0, "Right") \ DEFINE_INPUT(X_AXIS_POS, 0, "Right") \
#define DEFINE_RECOMP_UI_INPUTS() \ #define DEFINE_RECOMP_UI_INPUTS() \
DEFINE_INPUT(TOGGLE_MENU, 0, "Toggle Menu") DEFINE_INPUT(TOGGLE_MENU, 0, "Toggle Menu") \
DEFINE_INPUT(ACCEPT_MENU, 0, "Accept (Menu)") \
DEFINE_INPUT(APPLY_MENU, 0, "Apply (Menu)")
#define DEFINE_ALL_INPUTS() \ #define DEFINE_ALL_INPUTS() \
DEFINE_N64_BUTTON_INPUTS() \ DEFINE_N64_BUTTON_INPUTS() \
@ -113,6 +115,8 @@ namespace recomp {
std::vector<InputField> analog_down; std::vector<InputField> analog_down;
std::vector<InputField> toggle_menu; std::vector<InputField> toggle_menu;
std::vector<InputField> accept_menu;
std::vector<InputField> apply_menu;
}; };
constexpr const std::vector<InputField>& get_default_mapping_for_input(const DefaultN64Mappings& defaults, const GameInput input) { constexpr const std::vector<InputField>& get_default_mapping_for_input(const DefaultN64Mappings& defaults, const GameInput input) {
@ -136,6 +140,8 @@ namespace recomp {
case GameInput::Y_AXIS_POS: return defaults.analog_up; case GameInput::Y_AXIS_POS: return defaults.analog_up;
case GameInput::Y_AXIS_NEG: return defaults.analog_down; case GameInput::Y_AXIS_NEG: return defaults.analog_down;
case GameInput::TOGGLE_MENU: return defaults.toggle_menu; case GameInput::TOGGLE_MENU: return defaults.toggle_menu;
case GameInput::ACCEPT_MENU: return defaults.accept_menu;
case GameInput::APPLY_MENU: return defaults.apply_menu;
default: return std::vector<InputField>(); default: return std::vector<InputField>();
} }
} }

View File

@ -4,6 +4,7 @@
#include <filesystem> #include <filesystem>
#include <string_view> #include <string_view>
#include "ultramodern/config.hpp" #include "ultramodern/config.hpp"
#include "recomp_input.h"
namespace zelda64 { namespace zelda64 {
constexpr std::u8string_view program_id = u8"Zelda64Recompiled"; constexpr std::u8string_view program_id = u8"Zelda64Recompiled";
@ -16,6 +17,7 @@ namespace zelda64 {
void reset_input_bindings(); void reset_input_bindings();
void reset_cont_input_bindings(); void reset_cont_input_bindings();
void reset_kb_input_bindings(); void reset_kb_input_bindings();
void reset_single_input_binding(recomp::InputDevice device, recomp::GameInput input);
std::filesystem::path get_app_folder_path(); std::filesystem::path get_app_folder_path();

View File

@ -286,7 +286,10 @@ void assign_all_mappings(recomp::InputDevice device, const recomp::DefaultN64Map
assign_mapping_complete(device, recomp::GameInput::X_AXIS_POS, values.analog_right); assign_mapping_complete(device, recomp::GameInput::X_AXIS_POS, values.analog_right);
assign_mapping_complete(device, recomp::GameInput::Y_AXIS_NEG, values.analog_down); assign_mapping_complete(device, recomp::GameInput::Y_AXIS_NEG, values.analog_down);
assign_mapping_complete(device, recomp::GameInput::Y_AXIS_POS, values.analog_up); assign_mapping_complete(device, recomp::GameInput::Y_AXIS_POS, values.analog_up);
assign_mapping_complete(device, recomp::GameInput::TOGGLE_MENU, values.toggle_menu); assign_mapping_complete(device, recomp::GameInput::TOGGLE_MENU, values.toggle_menu);
assign_mapping_complete(device, recomp::GameInput::ACCEPT_MENU, values.accept_menu);
assign_mapping_complete(device, recomp::GameInput::APPLY_MENU, values.apply_menu);
}; };
void zelda64::reset_input_bindings() { void zelda64::reset_input_bindings() {
@ -302,6 +305,19 @@ void zelda64::reset_kb_input_bindings() {
assign_all_mappings(recomp::InputDevice::Keyboard, recomp::default_n64_keyboard_mappings); assign_all_mappings(recomp::InputDevice::Keyboard, recomp::default_n64_keyboard_mappings);
} }
void zelda64::reset_single_input_binding(recomp::InputDevice device, recomp::GameInput input) {
assign_mapping_complete(
device,
input,
recomp::get_default_mapping_for_input(
device == recomp::InputDevice::Keyboard ?
recomp::default_n64_keyboard_mappings :
recomp::default_n64_controller_mappings,
input
)
);
}
void reset_graphics_options() { void reset_graphics_options() {
ultramodern::renderer::GraphicsConfig new_config{}; ultramodern::renderer::GraphicsConfig new_config{};
new_config.res_option = res_default; new_config.res_option = res_default;

View File

@ -333,6 +333,12 @@ const recomp::DefaultN64Mappings recomp::default_n64_keyboard_mappings = {
.toggle_menu = { .toggle_menu = {
{.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_ESCAPE} {.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_ESCAPE}
}, },
.accept_menu = {
{.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_RETURN}
},
.apply_menu = {
{.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_F}
}
}; };
const recomp::DefaultN64Mappings recomp::default_n64_controller_mappings = { const recomp::DefaultN64Mappings recomp::default_n64_controller_mappings = {
@ -397,6 +403,13 @@ const recomp::DefaultN64Mappings recomp::default_n64_controller_mappings = {
.toggle_menu = { .toggle_menu = {
{.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_BACK}, {.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_BACK},
}, },
.accept_menu = {
{.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_SOUTH},
},
.apply_menu = {
{.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_WEST},
{.input_type = (uint32_t)InputType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_START}
}
}; };
void recomp::poll_inputs() { void recomp::poll_inputs() {
@ -678,35 +691,35 @@ bool recomp::all_input_disabled() {
std::string controller_button_to_string(SDL_GameControllerButton button) { std::string controller_button_to_string(SDL_GameControllerButton button) {
switch (button) { switch (button) {
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_A: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_A:
return "\u21A7"; return PF_GAMEPAD_A;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_B: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_B:
return "\u21A6"; return PF_GAMEPAD_B;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_X: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_X:
return "\u21A4"; return PF_GAMEPAD_X;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_Y: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_Y:
return "\u21A5"; return PF_GAMEPAD_Y;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_BACK: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_BACK:
return "\u21FA"; return PF_XBOX_VIEW;
// case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_GUIDE: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_GUIDE:
// return ""; return PF_GAMEPAD_HOME;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_START: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_START:
return "\u21FB"; return PF_XBOX_MENU;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_LEFTSTICK: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_LEFTSTICK:
return "\u21BA"; return PF_ANALOG_L_CLICK;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_RIGHTSTICK: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_RIGHTSTICK:
return "\u21BB"; return PF_ANALOG_R_CLICK;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_LEFTSHOULDER: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
return "\u2198"; return PF_XBOX_LEFT_SHOULDER;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
return "\u2199"; return PF_XBOX_RIGHT_SHOULDER;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_UP: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_UP:
return "\u219F"; return PF_DPAD_UP;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_DOWN: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_DOWN:
return "\u21A1"; return PF_DPAD_DOWN;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_LEFT: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_LEFT:
return "\u219E"; return PF_DPAD_LEFT;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_RIGHT: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
return "\u21A0"; return PF_DPAD_RIGHT;
// case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_MISC1: // case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_MISC1:
// return ""; // return "";
// case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_PADDLE1: // case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_PADDLE1:
@ -718,7 +731,7 @@ std::string controller_button_to_string(SDL_GameControllerButton button) {
// case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_PADDLE4: // case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_PADDLE4:
// return ""; // return "";
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_TOUCHPAD: case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_TOUCHPAD:
return "\u21E7"; return PF_SONY_TOUCHPAD;
default: default:
return "Button " + std::to_string(button); return "Button " + std::to_string(button);
} }
@ -794,6 +807,8 @@ std::unordered_map<SDL_Scancode, std::string> scancode_codepoints {
{SDL_SCANCODE_RETURN, PF_KEYBOARD_ENTER}, {SDL_SCANCODE_RETURN, PF_KEYBOARD_ENTER},
{SDL_SCANCODE_CAPSLOCK, PF_KEYBOARD_CAPS}, {SDL_SCANCODE_CAPSLOCK, PF_KEYBOARD_CAPS},
{SDL_SCANCODE_NUMLOCKCLEAR, PF_KEYBOARD_NUM_LOCK}, {SDL_SCANCODE_NUMLOCKCLEAR, PF_KEYBOARD_NUM_LOCK},
{SDL_SCANCODE_LSHIFT, "L" PF_KEYBOARD_SHIFT},
{SDL_SCANCODE_RSHIFT, "R" PF_KEYBOARD_SHIFT},
}; };
std::string keyboard_input_to_string(SDL_Scancode key) { std::string keyboard_input_to_string(SDL_Scancode key) {

View File

@ -170,6 +170,9 @@ void recomp::finish_scanning_input(recomp::InputField scanned_field) {
controls_model_handle.DirtyVariable("inputs"); controls_model_handle.DirtyVariable("inputs");
controls_model_handle.DirtyVariable("active_binding_input"); controls_model_handle.DirtyVariable("active_binding_input");
controls_model_handle.DirtyVariable("active_binding_slot"); controls_model_handle.DirtyVariable("active_binding_slot");
nav_help_model_handle.DirtyVariable("nav_help__accept");
nav_help_model_handle.DirtyVariable("nav_help__exit");
graphics_model_handle.DirtyVariable("gfx_help__apply");
} }
void recomp::cancel_scanning_input() { void recomp::cancel_scanning_input() {
@ -179,6 +182,9 @@ void recomp::cancel_scanning_input() {
controls_model_handle.DirtyVariable("inputs"); controls_model_handle.DirtyVariable("inputs");
controls_model_handle.DirtyVariable("active_binding_input"); controls_model_handle.DirtyVariable("active_binding_input");
controls_model_handle.DirtyVariable("active_binding_slot"); controls_model_handle.DirtyVariable("active_binding_slot");
nav_help_model_handle.DirtyVariable("nav_help__accept");
nav_help_model_handle.DirtyVariable("nav_help__exit");
graphics_model_handle.DirtyVariable("gfx_help__apply");
} }
void recomp::config_menu_set_cont_or_kb(bool cont_interacted) { void recomp::config_menu_set_cont_or_kb(bool cont_interacted) {
@ -687,9 +693,17 @@ public:
constructor.BindFunc("gfx_help__apply", [](Rml::Variant& out) { constructor.BindFunc("gfx_help__apply", [](Rml::Variant& out) {
if (cont_active) { if (cont_active) {
out = PF_GAMEPAD_X " " PF_GAMEPAD_START; out = \
(recomp::get_input_binding(recomp::GameInput::APPLY_MENU, 0, recomp::InputDevice::Controller).to_string() != "" ?
" " + recomp::get_input_binding(recomp::GameInput::APPLY_MENU, 0, recomp::InputDevice::Controller).to_string() :
""
) + \
(recomp::get_input_binding(recomp::GameInput::APPLY_MENU, 1, recomp::InputDevice::Controller).to_string() != "" ?
" " + recomp::get_input_binding(recomp::GameInput::APPLY_MENU, 1, recomp::InputDevice::Controller).to_string() :
""
);
} else { } else {
out = PF_KEYBOARD_F; out = " " PF_KEYBOARD_F;
} }
}); });
@ -735,6 +749,9 @@ public:
zelda64::reset_kb_input_bindings(); zelda64::reset_kb_input_bindings();
} }
model_handle.DirtyAllVariables(); model_handle.DirtyAllVariables();
nav_help_model_handle.DirtyVariable("nav_help__accept");
nav_help_model_handle.DirtyVariable("nav_help__exit");
graphics_model_handle.DirtyVariable("gfx_help__apply");
}); });
constructor.BindEventCallback("clear_input_bindings", constructor.BindEventCallback("clear_input_bindings",
@ -744,6 +761,16 @@ public:
recomp::set_input_binding(input, binding_index, cur_device, recomp::InputField{}); recomp::set_input_binding(input, binding_index, cur_device, recomp::InputField{});
} }
model_handle.DirtyVariable("inputs"); model_handle.DirtyVariable("inputs");
graphics_model_handle.DirtyVariable("gfx_help__apply");
});
constructor.BindEventCallback("reset_single_input_binding_to_default",
[](Rml::DataModelHandle model_handle, Rml::Event& event, const Rml::VariantList& inputs) {
recomp::GameInput input = static_cast<recomp::GameInput>(inputs.at(0).Get<size_t>());
zelda64::reset_single_input_binding(cur_device, input);
model_handle.DirtyVariable("inputs");
nav_help_model_handle.DirtyVariable("nav_help__accept");
nav_help_model_handle.DirtyVariable("nav_help__exit");
}); });
constructor.BindEventCallback("set_input_row_focus", constructor.BindEventCallback("set_input_row_focus",
@ -868,7 +895,9 @@ public:
constructor.BindFunc("nav_help__accept", [](Rml::Variant& out) { constructor.BindFunc("nav_help__accept", [](Rml::Variant& out) {
if (cont_active) { if (cont_active) {
out = PF_GAMEPAD_A; out = \
recomp::get_input_binding(recomp::GameInput::ACCEPT_MENU, 0, recomp::InputDevice::Controller).to_string() + \
recomp::get_input_binding(recomp::GameInput::ACCEPT_MENU, 1, recomp::InputDevice::Controller).to_string();
} else { } else {
out = PF_KEYBOARD_ENTER; out = PF_KEYBOARD_ENTER;
} }
@ -876,7 +905,9 @@ public:
constructor.BindFunc("nav_help__exit", [](Rml::Variant& out) { constructor.BindFunc("nav_help__exit", [](Rml::Variant& out) {
if (cont_active) { if (cont_active) {
out = PF_XBOX_VIEW; out = \
recomp::get_input_binding(recomp::GameInput::TOGGLE_MENU, 0, recomp::InputDevice::Controller).to_string() + \
recomp::get_input_binding(recomp::GameInput::TOGGLE_MENU, 1, recomp::InputDevice::Controller).to_string();
} else { } else {
out = PF_KEYBOARD_ESCAPE; out = PF_KEYBOARD_ESCAPE;
} }

View File

@ -1183,19 +1183,21 @@ std::atomic<recompui::Menu> open_menu = recompui::Menu::Launcher;
std::atomic<recompui::ConfigSubmenu> open_config_submenu = recompui::ConfigSubmenu::Count; std::atomic<recompui::ConfigSubmenu> open_config_submenu = recompui::ConfigSubmenu::Count;
int cont_button_to_key(SDL_ControllerButtonEvent& button) { int cont_button_to_key(SDL_ControllerButtonEvent& button) {
switch (button.button) { // Configurable accept button in menu
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_UP: auto menuAcceptBinding0 = recomp::get_input_binding(recomp::GameInput::ACCEPT_MENU, 0, recomp::InputDevice::Controller);
return SDLK_UP; auto menuAcceptBinding1 = recomp::get_input_binding(recomp::GameInput::ACCEPT_MENU, 1, recomp::InputDevice::Controller);
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_DOWN: // note - magic number: 0 is InputType::None
return SDLK_DOWN; if ((menuAcceptBinding0.input_type != 0 && button.button == menuAcceptBinding0.input_id) ||
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_LEFT: (menuAcceptBinding1.input_type != 0 && button.button == menuAcceptBinding1.input_id)) {
return SDLK_LEFT;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
return SDLK_RIGHT;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_A:
return SDLK_RETURN; return SDLK_RETURN;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_X: }
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_START:
// Configurable apply button in menu
auto menuApplyBinding0 = recomp::get_input_binding(recomp::GameInput::APPLY_MENU, 0, recomp::InputDevice::Controller);
auto menuApplyBinding1 = recomp::get_input_binding(recomp::GameInput::APPLY_MENU, 1, recomp::InputDevice::Controller);
// note - magic number: 0 is InputType::None
if ((menuApplyBinding0.input_type != 0 && button.button == menuApplyBinding0.input_id) ||
(menuApplyBinding1.input_type != 0 && button.button == menuApplyBinding1.input_id)) {
return SDLK_f; return SDLK_f;
} }
@ -1208,6 +1210,17 @@ int cont_button_to_key(SDL_ControllerButtonEvent& button) {
return SDLK_ESCAPE; return SDLK_ESCAPE;
} }
switch (button.button) {
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_UP:
return SDLK_UP;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_DOWN:
return SDLK_DOWN;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_LEFT:
return SDLK_LEFT;
case SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
return SDLK_RIGHT;
}
return 0; return 0;
} }