CONTROLS SETTINGS LJG:LSFGLH:JNSGFL:JHKSHJ:LFK:SHLJKF

This commit is contained in:
Issac332 2026-06-25 20:52:46 +03:00
parent 6606bb2b4c
commit 547343f4d3
14 changed files with 1194 additions and 89 deletions

View file

@ -284,6 +284,7 @@ set(BINDING_HEADERS
binding-mri/sceneelement-binding.h binding-mri/sceneelement-binding.h
binding-mri/viewportelement-binding.h binding-mri/viewportelement-binding.h
binding-mri/flashable-binding.h binding-mri/flashable-binding.h
binding-mri/keybindings-binding.h
) )
set(BINDING_SOURCE set(BINDING_SOURCE
binding-mri/binding-mri.cpp binding-mri/binding-mri.cpp
@ -311,6 +312,7 @@ set(BINDING_SOURCE
binding-mri/time-binding.cpp binding-mri/time-binding.cpp
binding-mri/shader-binging.cpp binding-mri/shader-binging.cpp
binding-mri/modloader-binding.cpp binding-mri/modloader-binding.cpp
binding-mri/keybindings-binding.cpp
) )
source_group("Binding Source" FILES ${BINDING_SOURCE} ${BINDING_HEADERS}) source_group("Binding Source" FILES ${BINDING_SOURCE} ${BINDING_HEADERS})

View file

@ -138,6 +138,7 @@ void SunshineBindingInit();
void steamBindingInit(); void steamBindingInit();
void shaderBindingInit(); void shaderBindingInit();
void ModLoaderBindingInit(); void ModLoaderBindingInit();
void keybindingsBindingInit();
RB_METHOD(mriPrint); RB_METHOD(mriPrint);
RB_METHOD(mriP); RB_METHOD(mriP);
@ -174,6 +175,7 @@ static void mriBindingInit(){
steamBindingInit(); steamBindingInit();
shaderBindingInit(); shaderBindingInit();
ModLoaderBindingInit(); ModLoaderBindingInit();
keybindingsBindingInit();
_rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain); _rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain);
_rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop); _rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop);

View file

@ -24,6 +24,13 @@
#include "exception.h" #include "exception.h"
#include "binding-util.h" #include "binding-util.h"
#include "util.h" #include "util.h"
#include "eventthread.h"
#include "keybindings-binding.h"
#include <SDL3/SDL_keyboard.h>
#include <SDL3/SDL_gamepad.h>
#include <vector>
RB_METHOD(inputUpdate){ RB_METHOD(inputUpdate){
RB_UNUSED_PARAM; RB_UNUSED_PARAM;
@ -109,39 +116,198 @@ RB_METHOD(inputWheelFlipped) {
return rb_bool_new(shState->input().wheelFlipped()); return rb_bool_new(shState->input().wheelFlipped());
} }
RB_METHOD(inputQuit){ RB_METHOD(inputQuit) {
RB_UNUSED_PARAM; RB_UNUSED_PARAM;
return rb_bool_new(shState->input().hasQuit()); return rb_bool_new(shState->input().hasQuit());
} }
// keyboard
RB_METHOD(getKeyName) {
RB_UNUSED_PARAM;
int key = 0;
rb_get_args(argc, argv, "i", &key RB_ARG_END);
if (key >= 0 && key < SDL_Scancode::SDL_SCANCODE_COUNT)
return rb_utf8_str_new_cstr(SDL_GetKeyName(SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(key), SDL_KMOD_NONE, false)));
return rb_utf8_str_new_cstr(SDL_GetKeyName(SDLK_UNKNOWN));
}
RB_METHOD(keyPress) {
RB_UNUSED_PARAM;
int key = 0;
rb_get_args(argc, argv, "i", &key RB_ARG_END);
if (key >= 0 && key < SDL_Scancode::SDL_SCANCODE_COUNT)
return rb_bool_new(EventThread::keyStates[key]);
return rb_bool_new(false);
}
RB_METHOD(getPressedKey) {
RB_UNUSED_PARAM;
short pressedKey = 0;
for(; pressedKey < SDL_Scancode::SDL_SCANCODE_COUNT && !EventThread::keyStates[pressedKey]; pressedKey++);
return pressedKey == SDL_Scancode::SDL_SCANCODE_COUNT ? Qnil : rb_fix_new(pressedKey);
}
RB_METHOD(getKeyFromName) {
RB_UNUSED_PARAM;
const char *name;
rb_get_args(argc, argv, "z", &name RB_ARG_END);
return rb_fix_new(SDL_GetScancodeFromName(name));
}
// gamepad buttons
RB_METHOD(getGamepadButtonName) {
RB_UNUSED_PARAM;
int key = 0;
rb_get_args(argc, argv, "i", &key RB_ARG_END);
if (key >= 0 && key < SDL_GamepadButton::SDL_GAMEPAD_BUTTON_COUNT)
return rb_utf8_str_new_cstr(SDL_GetGamepadStringForButton(static_cast<SDL_GamepadButton>(key)));
return rb_utf8_str_new_cstr("Invalid");
}
RB_METHOD(gamepadButtonPress) {
RB_UNUSED_PARAM;
int key = 0;
rb_get_args(argc, argv, "i", &key RB_ARG_END);
if (key >= 0 && key < SDL_GamepadButton::SDL_GAMEPAD_BUTTON_COUNT)
return rb_bool_new(EventThread::gcState.buttons[key]);
return rb_bool_new(false);
}
RB_METHOD(getPressedGamepadButton) {
RB_UNUSED_PARAM;
short pressedKey = 0;
for(; pressedKey < SDL_GamepadButton::SDL_GAMEPAD_BUTTON_COUNT && !EventThread::gcState.buttons[pressedKey]; pressedKey++);
return pressedKey == SDL_GamepadButton::SDL_GAMEPAD_BUTTON_COUNT ? Qnil : rb_fix_new(pressedKey);
}
RB_METHOD(getGamepadButtonFromName) {
RB_UNUSED_PARAM;
const char *name;
rb_get_args(argc, argv, "z", &name RB_ARG_END);
return rb_fix_new(SDL_GetGamepadButtonFromString(name));
}
// gamepad axes
RB_METHOD(getGamepadAxisName) {
RB_UNUSED_PARAM;
int key = 0;
rb_get_args(argc, argv, "i", &key RB_ARG_END);
if (key >= 0 && key < SDL_GamepadAxis::SDL_GAMEPAD_AXIS_COUNT)
return rb_utf8_str_new_cstr(SDL_GetGamepadStringForAxis(static_cast<SDL_GamepadAxis>(key)));
return rb_utf8_str_new_cstr("Invalid");
}
RB_METHOD(getGamepadAxisPressure) {
RB_UNUSED_PARAM;
int key = 0;
rb_get_args(argc, argv, "i", &key RB_ARG_END);
if (key >= 0 && key < SDL_GamepadAxis::SDL_GAMEPAD_AXIS_COUNT)
return rb_fix_new(EventThread::gcState.axes[key]);
return rb_fix_new(0);
}
RB_METHOD(getActiveGamepadAxis) {
RB_UNUSED_PARAM;
int deadzone = 16000;
rb_get_args(argc, argv, "|i", &deadzone RB_ARG_END);
short pressedKey = 0;
for(; pressedKey < SDL_GamepadAxis::SDL_GAMEPAD_AXIS_COUNT && (EventThread::gcState.axes[pressedKey] <= -32768 || std::abs(EventThread::gcState.axes[pressedKey]) < deadzone); pressedKey++);
return pressedKey == SDL_GamepadAxis::SDL_GAMEPAD_AXIS_COUNT ? Qnil : rb_fix_new(pressedKey);
}
RB_METHOD(getGamepadAxisFromName) {
RB_UNUSED_PARAM;
const char *name;
rb_get_args(argc, argv, "z", &name RB_ARG_END);
return rb_fix_new(SDL_GetGamepadAxisFromString(name));
}
static VALUE setBinding(VALUE self, VALUE rb_arr, VALUE rb_target){
Check_Type(rb_arr, T_ARRAY);
int target = FIX2INT(rb_target);
long count = RARRAY_LEN(rb_arr);
std::vector<SourceDesc> result;
result.reserve(count);
for (size_t i = 0; i < count; ++i)
{
VALUE rb_binding = rb_ary_entry(rb_arr, i);
//printf("bind\n");
if (!rb_typeddata_is_kind_of(rb_binding, &sourceDesc_type))
continue;
//printf("bind ok\n");
SourceDesc* src;
TypedData_Get_Struct(rb_binding, SourceDesc, &sourceDesc_type, src);
result.push_back(*src);
}
shState->input().setBinding(result, static_cast<Input::ButtonCode>(target));
return Qnil;
}
struct{ struct{
const char *str; const char *str;
Input::ButtonCode val; Input::ButtonCode val;
} }
static buttonCodes[] = { static buttonCodes[] = {
{ "DOWN", Input::Down }, { "NONE", Input::None },
{ "LEFT", Input::Left },
{ "RIGHT", Input::Right },
{ "UP", Input::Up },
{ "ACTION", Input::Action }, { "DOWN", Input::Down },
{ "CANCEL", Input::Cancel }, { "LEFT", Input::Left },
{ "MENU", Input::Menu }, { "RIGHT", Input::Right },
{ "ITEMS", Input::Items }, { "UP", Input::Up },
{ "RUN", Input::Run },
{ "DEACTIVATE", Input::Deactivate },
{ "DEBUGACTION",Input::DebugAction},
{ "L", Input::L }, { "ACTION", Input::Action },
{ "R", Input::R }, { "CANCEL", Input::Cancel },
{ "MENU", Input::Menu },
{ "ITEMS", Input::Items },
{ "RUN", Input::Run },
{ "DEACTIVATE", Input::Deactivate },
{ "F5", Input::F5 }, { "DEBUGACTION", Input::DebugAction },
{ "F6", Input::F6 },
{ "F7", Input::F7 }, { "L", Input::L },
{ "F8", Input::F8 }, { "R", Input::R },
{ "F9", Input::F9 },
{ "F5", Input::F5 },
{ "F6", Input::F6 },
{ "F7", Input::F7 },
{ "F8", Input::F8 },
{ "F9", Input::F9 },
{ "MOUSELEFT", Input::MouseLeft }, { "MOUSELEFT", Input::MouseLeft },
{ "MOUSEMIDDLE", Input::MouseMiddle }, { "MOUSEMIDDLE", Input::MouseMiddle },
@ -154,6 +320,7 @@ void inputBindingInit(){
printf("[inputBindingInit] Initializing Input binding\n"); printf("[inputBindingInit] Initializing Input binding\n");
VALUE module = rb_define_module("Input"); VALUE module = rb_define_module("Input");
// mkxp's input
_rb_define_module_function(module, "update", inputUpdate); _rb_define_module_function(module, "update", inputUpdate);
_rb_define_module_function(module, "press?", inputPress); _rb_define_module_function(module, "press?", inputPress);
_rb_define_module_function(module, "trigger?", inputTrigger); _rb_define_module_function(module, "trigger?", inputTrigger);
@ -161,6 +328,30 @@ void inputBindingInit(){
_rb_define_module_function(module, "dir4", inputDir4); _rb_define_module_function(module, "dir4", inputDir4);
_rb_define_module_function(module, "dir8", inputDir8); _rb_define_module_function(module, "dir8", inputDir8);
// keyboard keys
_rb_define_module_function(module, "key_name", getKeyName);
_rb_define_module_function(module, "key_press?", keyPress);
_rb_define_module_function(module, "pressed_key", getPressedKey);
_rb_define_module_function(module, "key_from_name", getKeyFromName);
rb_const_set(module, rb_intern("KEYS_COUNT"), SDL_Scancode::SDL_SCANCODE_COUNT - 1);
// gamepad buttons
_rb_define_module_function(module, "c_button_name", getGamepadButtonName);
_rb_define_module_function(module, "c_button_press?", gamepadButtonPress);
_rb_define_module_function(module, "pressed_c_button", getPressedGamepadButton);
_rb_define_module_function(module, "c_button_from_name", getGamepadButtonFromName);
rb_const_set(module, rb_intern("GAMEPAD_BUTTONS_COUNT"), SDL_GamepadButton::SDL_GAMEPAD_BUTTON_COUNT - 1);
// gamepad axes
_rb_define_module_function(module, "c_axis_name", getGamepadAxisName);
_rb_define_module_function(module, "c_axis_pressure", getGamepadAxisPressure);
_rb_define_module_function(module, "active_c_axis", getActiveGamepadAxis);
_rb_define_module_function(module, "c_axis_from_name", getGamepadAxisFromName);
rb_const_set(module, rb_intern("GAMEPAD_AXIS_COUNT"), SDL_GamepadAxis::SDL_GAMEPAD_AXIS_COUNT - 1);
rb_define_module_function(module, "set_binding", RUBY_METHOD_FUNC(setBinding), 2);
// mouse
_rb_define_module_function(module, "mouse_x", inputMouseX); _rb_define_module_function(module, "mouse_x", inputMouseX);
_rb_define_module_function(module, "mouse_y", inputMouseY); _rb_define_module_function(module, "mouse_y", inputMouseY);

View file

@ -0,0 +1,258 @@
#include "input.h"
#include "sharedstate.h"
#include "binding-util.h"
#include "keybindings-binding.h"
void sourceDesc_free(void* ptr)
{
SourceDesc* kb = (SourceDesc*)ptr;
delete kb;
}
const rb_data_type_t sourceDesc_type = { "SourceDesc", {0, sourceDesc_free, 0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY };
static VALUE sourceDesc_alloc(VALUE klass)
{
SourceDesc* ptr = ALLOC(SourceDesc);
return TypedData_Wrap_Struct(klass, &sourceDesc_type, ptr);
}
// fabrics
static VALUE rb_source_key(VALUE klass, VALUE scan)
{
SourceDesc* s = new SourceDesc();
s->type = Key;
s->d.scan = static_cast<SDL_Scancode>(NUM2INT(scan));
return TypedData_Wrap_Struct(klass, &sourceDesc_type, s);
}
static VALUE rb_source_caxis(VALUE klass, VALUE axis, VALUE dir)
{
SourceDesc* s = new SourceDesc();
s->type = CAxis;
s->d.ja.axis = NUM2INT(axis);
s->d.ja.dir = static_cast<AxisDir>(NUM2INT(dir));
return TypedData_Wrap_Struct(klass, &sourceDesc_type, s);
}
static VALUE rb_source_cbutton(VALUE klass, VALUE button)
{
SourceDesc* s = new SourceDesc();
s->type = CButton;
s->d.jb = NUM2INT(button);
return TypedData_Wrap_Struct(klass, &sourceDesc_type, s);
}
static VALUE rb_source_jaxis(VALUE klass, VALUE axis, VALUE dir)
{
SourceDesc* s = new SourceDesc();
s->type = JAxis;
s->d.ja.axis = NUM2INT(axis);
s->d.ja.dir = static_cast<AxisDir>(NUM2INT(dir));
return TypedData_Wrap_Struct(klass, &sourceDesc_type, s);
}
static VALUE rb_source_jhat(VALUE klass, VALUE hat, VALUE pos)
{
SourceDesc* s = new SourceDesc();
s->type = JHat;
s->d.jh.hat = NUM2INT(hat);
s->d.jh.pos = NUM2INT(pos);
return TypedData_Wrap_Struct(klass, &sourceDesc_type, s);
}
static VALUE rb_source_jbutton(VALUE klass, VALUE button)
{
SourceDesc* s = new SourceDesc();
s->type = JButton;
s->d.jb = NUM2INT(button);
return TypedData_Wrap_Struct(klass, &sourceDesc_type, s);
}
// getters
#define SOURCE_DESC \
SourceDesc* src; \
TypedData_Get_Struct(self, SourceDesc, &sourceDesc_type, src);
#define TYPE_IS src->type == SourceType
static VALUE rb_source_type(VALUE self)
{
SOURCE_DESC
return INT2NUM(src->type);
}
static VALUE rb_source_scancode(VALUE self)
{
SOURCE_DESC
if (TYPE_IS::Key)
return INT2NUM(src->d.scan);
return Qnil;
}
static VALUE rb_source_button(VALUE self)
{
SOURCE_DESC
if (TYPE_IS::CButton || TYPE_IS::JButton)
return INT2NUM(src->d.jb);
return Qnil;
}
static VALUE rb_source_axis(VALUE self)
{
SOURCE_DESC
if (TYPE_IS::CAxis || TYPE_IS::JAxis)
return INT2NUM(src->d.ja.axis);
return Qnil;
}
static VALUE rb_source_dir(VALUE self)
{
SOURCE_DESC
if (TYPE_IS::CAxis || TYPE_IS::JAxis)
return INT2NUM(src->d.ja.dir);
return Qnil;
}
static VALUE rb_source_hat(VALUE self)
{
SOURCE_DESC
if (TYPE_IS::JHat)
return INT2NUM(src->d.jh.hat);
return Qnil;
}
static VALUE rb_source_pos(VALUE self)
{
SOURCE_DESC
if (TYPE_IS::JHat)
return INT2NUM(src->d.jh.pos);
return Qnil;
}
static VALUE rb_source_marshal_dump(VALUE self)
{
SourceDesc* src;
TypedData_Get_Struct(self, SourceDesc, &sourceDesc_type, src);
VALUE arr = rb_ary_new();
rb_ary_push(arr, INT2NUM(src->type));
switch (src->type)
{
case SourceType::Key:
rb_ary_push(arr, INT2NUM(src->d.scan));
break;
case SourceType::CButton:
case SourceType::JButton:
rb_ary_push(arr, INT2NUM(src->d.jb));
break;
case SourceType::CAxis:
case SourceType::JAxis:
rb_ary_push(arr, INT2NUM(src->d.ja.axis));
rb_ary_push(arr, INT2NUM(src->d.ja.dir));
break;
case SourceType::JHat:
rb_ary_push(arr, INT2NUM(src->d.jh.hat));
rb_ary_push(arr, INT2NUM(src->d.jh.pos));
break;
default:
break;
}
return arr;
}
static VALUE rb_source_marshal_load(VALUE self, VALUE data)
{
SourceDesc* src;
TypedData_Get_Struct(self, SourceDesc, &sourceDesc_type, src);
Check_Type(data, T_ARRAY);
VALUE type = rb_ary_entry(data, 0);
src->type = static_cast<SourceType>(NUM2INT(type));
switch (src->type)
{
case SourceType::Key:
src->d.scan = static_cast<SDL_Scancode>(NUM2INT(rb_ary_entry(data, 1)));
break;
case SourceType::CButton:
case SourceType::JButton:
src->d.jb = NUM2INT(rb_ary_entry(data, 1));
break;
case SourceType::CAxis:
case SourceType::JAxis:
src->d.ja.axis = NUM2INT(rb_ary_entry(data, 1));
src->d.ja.dir = static_cast<AxisDir>(NUM2INT(rb_ary_entry(data, 2)));
break;
case SourceType::JHat:
src->d.jh.hat = NUM2INT(rb_ary_entry(data, 1));
src->d.jh.pos = NUM2INT(rb_ary_entry(data, 2));
break;
default:
break;
}
return self;
}
void keybindingsBindingInit(){
VALUE klass = rb_define_class("KeyBind", rb_cObject);
rb_define_alloc_func(klass, sourceDesc_alloc);
rb_define_singleton_method(klass, "key", RUBY_METHOD_FUNC(rb_source_key), 1);
rb_define_singleton_method(klass, "caxis", RUBY_METHOD_FUNC(rb_source_caxis), 2);
rb_define_singleton_method(klass, "cbutton", RUBY_METHOD_FUNC(rb_source_cbutton), 1);
rb_define_singleton_method(klass, "jaxis", RUBY_METHOD_FUNC(rb_source_jaxis), 2);
rb_define_singleton_method(klass, "jhat", RUBY_METHOD_FUNC(rb_source_jhat), 2);
rb_define_singleton_method(klass, "jbutton", RUBY_METHOD_FUNC(rb_source_jbutton), 1);
rb_define_method(klass, "type", RUBY_METHOD_FUNC(rb_source_type), 0);
rb_define_method(klass, "scancode", RUBY_METHOD_FUNC(rb_source_scancode), 0);
rb_define_method(klass, "button", RUBY_METHOD_FUNC(rb_source_button), 0);
rb_define_method(klass, "axis", RUBY_METHOD_FUNC(rb_source_axis), 0);
rb_define_method(klass, "dir", RUBY_METHOD_FUNC(rb_source_dir), 0);
rb_define_method(klass, "hat", RUBY_METHOD_FUNC(rb_source_hat), 0);
rb_define_method(klass, "pos", RUBY_METHOD_FUNC(rb_source_pos), 0);
rb_define_method(klass, "marshal_dump", RUBY_METHOD_FUNC(rb_source_marshal_dump), 0);
rb_define_method(klass, "marshal_load", RUBY_METHOD_FUNC(rb_source_marshal_load), 1);
rb_const_set(klass, rb_intern("Negative"), INT2FIX(0));
rb_const_set(klass, rb_intern("Positive"), INT2FIX(1));
VALUE module = rb_define_module_under(klass, "Type");
rb_const_set(module, rb_intern("Invalid"), INT2FIX(SourceType::Invalid));
rb_const_set(module, rb_intern("Key"), INT2FIX(SourceType::Key));
rb_const_set(module, rb_intern("CButton"), INT2FIX(SourceType::CButton));
rb_const_set(module, rb_intern("CAxis"), INT2FIX(SourceType::CAxis));
rb_const_set(module, rb_intern("JButton"), INT2FIX(SourceType::JButton));
rb_const_set(module, rb_intern("JAxis"), INT2FIX(SourceType::JAxis));
rb_const_set(module, rb_intern("JHat"), INT2FIX(SourceType::JHat));
}

View file

@ -0,0 +1,8 @@
#pragma once
#include "keybindings.h"
#include <ruby.h>
extern void sourceDesc_free(void* ptr);
extern const rb_data_type_t sourceDesc_type;

View file

@ -81,7 +81,8 @@ set(scripts
i18n_Japanese.rb i18n_Japanese.rb
i18n_Language.rb i18n_Language.rb
Window_TPtL.rb Window_TPtL.rb
Settings.rb) Settings.rb
Input.rb)
find_program(RUBY_EXE ruby find_program(RUBY_EXE ruby
DOC "Location of the Ruby executable") DOC "Location of the Ruby executable")

View file

@ -3,41 +3,105 @@ module Settings
def reset! def reset!
@data = { @data = {
# Audio # Audio
:bgm_volume => 100, :bgm_volume => 100,
:sfx_volume => 100, :sfx_volume => 100,
# Video # Video
:fullscreen => false, :fullscreen => false,
:colorblind => false, :colorblind => false,
:frameskip => true, :frameskip => true,
:twm_shader => true, :twm_shader => true,
# UI # UI
:in_game_timer => false, :in_game_timer => false,
:language => 0, :language => 0,
:fasttravel_ui => 0, :fasttravel_ui => 0,
:debug_text_scene_title => true, :debug_text_scene_title => true,
# Gameplay # Gameplay
:movement => 0, :movement => 0,
:skip_text => false, :skip_text => false,
:en_purple_messagebox => true, :en_purple_messagebox => true,
:enforce_april_fools => false, :enforce_april_fools => false,
:true_memory_mode => false, :true_memory_mode => false,
:pre_solstice_update_content => false, :pre_solstice_update_content => false,
:dejavu_mode => false, :dejavu_mode => false,
:demo => false, :demo => false,
:oneshot_mode => false, :oneshot_mode => false,
# Advanced # Advanced
#controls #controls
:gamepad_led => true, :gamepad_led => true,
:gamepad_deadzone => 5,
:controls_walk_down => [
KeyBind.key(Input::key_from_name("Down")),
KeyBind.caxis(Input::c_axis_from_name("LeftY"), KeyBind::Positive),
KeyBind.cbutton(Input::c_button_from_name("DpDown"))
],
:controls_walk_left => [
KeyBind.key(Input::key_from_name("Left")),
KeyBind.caxis(Input::c_axis_from_name("LeftX"), KeyBind::Negative),
KeyBind.cbutton(Input::c_button_from_name("DpLeft"))
],
:controls_walk_right => [
KeyBind.key(Input::key_from_name("Right")),
KeyBind.caxis(Input::c_axis_from_name("LeftX"), KeyBind::Positive),
KeyBind.cbutton(Input::c_button_from_name("DpRight"))
],
:controls_walk_up => [
KeyBind.key(Input::key_from_name("Up")),
KeyBind.caxis(Input::c_axis_from_name("LeftY"), KeyBind::Negative),
KeyBind.cbutton(Input::c_button_from_name("DpUp"))
],
:controls_run => [
KeyBind.key(Input::key_from_name("Left Shift")),
KeyBind.caxis(Input::c_axis_from_name("righttrigger"), KeyBind::Positive),
KeyBind.cbutton(Input::c_button_from_name("x"))
],
# -----------------------------------------------------------------------------------------------------------
:controls_action => [
KeyBind.key(Input::key_from_name("Z")),
KeyBind.key(Input::key_from_name("Space")),
KeyBind.cbutton(Input::c_button_from_name("a")),
],
:controls_deactivate => [
KeyBind.key(Input::key_from_name("Left Shift")),
KeyBind.cbutton(Input::c_button_from_name("back")),
KeyBind.caxis(Input::c_axis_from_name("lefttrigger"), KeyBind::Positive),
],
:controls_cancel => [
KeyBind.key(Input::key_from_name("X")),
KeyBind.key(Input::key_from_name("Escape")),
KeyBind.cbutton(Input::c_button_from_name("b")),
],
:controls_menu => [
KeyBind.key(Input::key_from_name("A")),
KeyBind.key(Input::key_from_name("Return")),
KeyBind.cbutton(Input::c_button_from_name("start")),
],
:controls_items => [
KeyBind.key(Input::key_from_name("S")),
KeyBind.cbutton(Input::c_button_from_name("y")),
],
:controls_nav_left => [
KeyBind.key(Input::key_from_name("Q")),
KeyBind.cbutton(Input::c_button_from_name("leftshoulder")),
],
:controls_nav_right => [
KeyBind.key(Input::key_from_name("W")),
KeyBind.cbutton(Input::c_button_from_name("rightshoulder")),
],
# -----------------------------------------------------------------------------------------------------------
:controls_debug => [
KeyBind.key(Input::key_from_name("Left Ctrl")),
KeyBind.cbutton(Input::c_button_from_name("rightstick")),
],
# Debug # Debug
:debug => false, :debug => false,
:debug_character => false, :debug_character => false,
:debug_text => false, :debug_text => false,
} }
end end
end end
@ -48,14 +112,14 @@ class Window_Settings
DATA = { DATA = {
tr("Audio") => [ tr("Audio") => [
{ {
:type => :int, :type => :slider,
:name => tr('BGM Volume'), :name => tr('BGM Volume'),
:parameter => :bgm_volume, :parameter => :bgm_volume,
:min => 0, :min => 0,
:max => 100 :max => 100
}, },
{ {
:type => :int, :type => :slider,
:name => tr('SFX Volume'), :name => tr('SFX Volume'),
:parameter => :sfx_volume, :parameter => :sfx_volume,
:min => 0, :min => 0,
@ -109,12 +173,6 @@ class Window_Settings
}, },
], ],
tr("Gameplay") => [ tr("Gameplay") => [
{
:type => :enum,
:name => tr('Default movement'),
:parameter => :movement,
:values => [tr("Walk"), tr("Run")]
},
{ {
:type => :bool, :type => :bool,
:name => tr('Skip Text (R)'), :name => tr('Skip Text (R)'),
@ -167,13 +225,101 @@ class Window_Settings
:name => tr('Control LED lighting on gamepads'), :name => tr('Control LED lighting on gamepads'),
:parameter => :gamepad_led :parameter => :gamepad_led
}, },
#{
# :type => :slider,
# :name => tr("Gamepad deadzone"),
# :parameter => :gamepad_deadzone,
# :min => 0,
# :max => 10
#},
{ :type => :sep, :name => tr("Walk") },
{
:type => :key,
:name => tr("Walk Down"),
:parameter => :controls_walk_down,
:bind => Input::DOWN
},
{
:type => :key,
:name => tr("Walk Left"),
:parameter => :controls_walk_left,
:bind => Input::LEFT
},
{
:type => :key,
:name => tr("Walk Right"),
:parameter => :controls_walk_right,
:bind => Input::RIGHT
},
{
:type => :key,
:name => tr("Walk Up"),
:parameter => :controls_walk_up,
:bind => Input::UP
},
{
:type => :key,
:name => tr("Run"),
:parameter => :controls_run,
:bind => Input::RUN
},
{ :type => :sep, :name => tr("Actions") },
{
:type => :key,
:name => tr("Action"),
:parameter => :controls_action,
:bind => Input::ACTION
},
{
:type => :key,
:name => tr("Deactivate"),
:parameter => :controls_deactivate,
:bind => Input::DEACTIVATE
},
{
:type => :key,
:name => tr("Cancel"),
:parameter => :controls_cancel,
:bind => Input::CANCEL
},
{
:type => :key,
:name => tr("Menu"),
:parameter => :controls_menu,
:bind => Input::MENU
},
{
:type => :key,
:name => tr("Items"),
:parameter => :controls_items,
:bind => Input::ITEMS
},
{
:type => :key,
:name => tr("Nav Left"),
:parameter => :controls_nav_left,
:bind => Input::L
},
{
:type => :key,
:name => tr("Nav Right"),
:parameter => :controls_nav_right,
:bind => Input::R
},
{ :type => :sep, :name => tr("Other") },
{
:type => :key,
:name => tr("Debug"),
:parameter => :controls_debug,
:bind => Input::DEBUGACTION
},
], ],
tr("Advanced") => [ tr("Advanced") => [
{ {
:type => :bool, :type => :bool,
:name => tr('useless option:3'), :name => tr('useless option:3'),
:parameter => :erfsdgvfdgfgf :default => false
}, },
], ],
tr("Debug") => [ tr("Debug") => [
{ {

View file

@ -1,8 +1,12 @@
# Logic of settings UI
class Window_Settings class Window_Settings
SCREENS_PANELS_MARGIN = 32 SCREENS_PANELS_MARGIN = 32
PARAMETER_WIDTH = (Graphics.width - 640) / 2 + 512 PARAMETER_WIDTH = (Graphics.width - 640) / 2 + 512
PARAMETER_HEIGHT = 32 PARAMETER_HEIGHT = 32
PARAMETER_VALUE_WIDTH = 200 PARAMETER_VALUE_WIDTH = PARAMETER_WIDTH / 2
PARAMETER_KEY_WIDTH = PARAMETER_WIDTH / 5
PARAMETER_CHANGE_AUDIO = "Audio/SE/text_robot.wav"
class SettingsContent class SettingsContent
attr_reader :x attr_reader :x
@ -17,6 +21,8 @@ class Window_Settings
@index = 0 @index = 0
@opacity = 255 @opacity = 255
@offset = offset_y @offset = offset_y
@waiting_for_key = false
@wait_timer = 0
@visible_x = 0 @visible_x = 0
@visible_y = offset_y @visible_y = offset_y
@ -38,6 +44,22 @@ class Window_Settings
@screen_panel_selection_sprite.y = SCREENS_PANELS_MARGIN @screen_panel_selection_sprite.y = SCREENS_PANELS_MARGIN
@screen_panel_selection_sprite.x = Graphics.width / 2 @screen_panel_selection_sprite.x = Graphics.width / 2
@switch_panels_hint_left = Sprite.new(@viewport)
@switch_panels_hint_left.bitmap = Bitmap.new(PARAMETER_WIDTH / 2 - SCREENS_PANELS_MARGIN, @offset / 2)
@switch_panels_hint_left.bitmap.font.size = 20
@switch_panels_hint_left.x = @x + SCREENS_PANELS_MARGIN
@switch_panels_hint_left.zoom_x = @switch_panels_hint_left.zoom_y = 2
@switch_panels_hint_left.opacity = 127
@switch_panels_hint_right = Sprite.new(@viewport)
@switch_panels_hint_right.bitmap = Bitmap.new(PARAMETER_WIDTH / 2 - SCREENS_PANELS_MARGIN, @offset / 2)
@switch_panels_hint_right.bitmap.font.size = 20
@switch_panels_hint_right.x = @x + SCREENS_PANELS_MARGIN
@switch_panels_hint_right.zoom_x = @switch_panels_hint_right.zoom_y = 2
@switch_panels_hint_right.opacity = 127
redraw_panels_hints
@parameters = {} @parameters = {}
@screen_panels = [] @screen_panels = []
@next_screen_panel_offset = 0 @next_screen_panel_offset = 0
@ -126,6 +148,13 @@ class Window_Settings
@screen_panel_selection_sprite.zoom_x = @screen_panels[@screen].width * 0.3 + @screen_panel_selection_sprite.zoom_x * 0.7 @screen_panel_selection_sprite.zoom_x = @screen_panels[@screen].width * 0.3 + @screen_panel_selection_sprite.zoom_x * 0.7
@screen_panel_selection_sprite.x = (Graphics.width / 2 - @screen_panels[@screen].width * 0.5) * 0.3 + @screen_panel_selection_sprite.x * 0.7 @screen_panel_selection_sprite.x = (Graphics.width / 2 - @screen_panels[@screen].width * 0.5) * 0.3 + @screen_panel_selection_sprite.x * 0.7
@switch_panels_hint_left.x = @switch_panels_hint_left.x * 0.8 + (@x + SCREENS_PANELS_MARGIN) * 0.2
@switch_panels_hint_right.x = @switch_panels_hint_right.x * 0.8 + (@x + SCREENS_PANELS_MARGIN) * 0.2
@waiting_for_key2 = @waiting_for_key
@wait_timer = (@wait_timer + (@waiting_for_key ? 1 : -1)).clamp(0, 3)
end end
def redraw_all def redraw_all
@ -136,6 +165,11 @@ class Window_Settings
end end
end end
end end
def redraw_panels_hints
@switch_panels_hint_right.bitmap.draw_text(0, 0, @switch_panels_hint_right.bitmap.width, @switch_panels_hint_right.bitmap.height, "W→", 2)
@switch_panels_hint_left.bitmap.draw_text(0, 0, @switch_panels_hint_left.bitmap.width, @switch_panels_hint_left.bitmap.height, "←Q")
end
def update_pos() def update_pos()
center = Graphics.height / 2 - PARAMETER_HEIGHT * 0.5 center = Graphics.height / 2 - PARAMETER_HEIGHT * 0.5
@ -144,35 +178,55 @@ class Window_Settings
# Navigation # Navigation
def screen_left() def screen_left()
previous = @index
@parameters.values[@screen]&.[](@index)&.deselect
@screen = (@screen - 1) % @parameters.length @screen = (@screen - 1) % @parameters.length
@index = @index.clamp(0, @parameters.values[@screen].length - 1) @index = @index.clamp(0, @parameters.values[@screen].length - 1)
@switch_panels_hint_left.x -= SCREENS_PANELS_MARGIN
@parameters.values[@screen]&.[](@index)&.select(previous)
update_pos update_pos
end end
def screen_right() def screen_right()
previous = @index
@parameters.values[@screen]&.[](@index)&.deselect
@screen = (@screen + 1) % @parameters.length @screen = (@screen + 1) % @parameters.length
@index = @index.clamp(0, @parameters.values[@screen].length - 1) @index = @index.clamp(0, @parameters.values[@screen].length - 1)
@switch_panels_hint_right.x += SCREENS_PANELS_MARGIN
@parameters.values[@screen]&.[](@index)&.select(previous)
update_pos update_pos
end end
def parameter_up() def parameter_up()
previous = @index
@parameters.values[@screen]&.[](@index)&.deselect
offset = 1 offset = 1
if @parameters.values&.[](@screen)&.[](@index - 1)&.class&.const_get(:TYPE) == :sep if @parameters.values&.[](@screen)&.[](@index - 1)&.class&.const_get(:TYPE) == :sep
offset += 1 offset += 1
end end
@index = (@index - offset) % @parameters.values[@screen].length @index = (@index - offset) % @parameters.values[@screen].length
@parameters.values[@screen]&.[](@index)&.select(previous)
update_pos update_pos
end end
def parameter_down() def parameter_down()
previous = @index
@parameters.values[@screen]&.[](@index)&.deselect
offset = 1 offset = 1
if @parameters.values&.[](@screen)&.[](@index + 1)&.class&.const_get(:TYPE) == :sep if @parameters.values&.[](@screen)&.[](@index + 1)&.class&.const_get(:TYPE) == :sep
offset += 1 offset += 1
end end
@index = (@index + offset) % @parameters.values[@screen].length @index = (@index + offset) % @parameters.values[@screen].length
@parameters.values[@screen]&.[](@index)&.select(previous)
update_pos update_pos
end end
def parameter_select_offset(offset) def parameter_select_offset(offset)
previous = @index
@parameters.values[@screen]&.[](@index)&.deselect
@index = (@index + offset) % @parameters.values[@screen].length @index = (@index + offset) % @parameters.values[@screen].length
if @parameters.values&.[](@screen)&.[](@index)&.class&.const_get(:TYPE) == :sep
@index += offset <=> 0
end
@parameters.values[@screen]&.[](@index)&.select(previous)
update_pos update_pos
end end
@ -211,8 +265,16 @@ class Window_Settings
@opacity = value @opacity = value
@selection_sprite.opacity = value @selection_sprite.opacity = value
@screen_panel_selection_sprite.opacity = value @screen_panel_selection_sprite.opacity = value
@switch_panels_hint_right.opacity = @switch_panels_hint_left.opacity = (value * 127) / 255
redraw_all redraw_all
end end
def waiting_for_key=(value)
@waiting_for_key = value
end
def waiting_for_key
@wait_timer > 0
end
end end
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
@ -281,7 +343,7 @@ class Window_Settings
end end
def update() def update()
@sprite.x = @screen_id * Graphics.width - @settings_content.visible_x + @settings_content.x @sprite.x = @screen_id * Graphics.width - @settings_content.visible_x + @settings_content.x + 8
@sprite.y = @settings_content.visible_y + @position * PARAMETER_HEIGHT @sprite.y = @settings_content.visible_y + @position * PARAMETER_HEIGHT
@sprite.opacity = ((1.0 + ((@sprite.y - @settings_content.offset).to_f / 64.0).clamp(-1.0, 0.0)) * @opacity * (@settings_content.opacity.to_f / 255.0) * 255.0).to_i @sprite.opacity = ((1.0 + ((@sprite.y - @settings_content.offset).to_f / 64.0).clamp(-1.0, 0.0)) * @opacity * (@settings_content.opacity.to_f / 255.0) * 255.0).to_i
end end
@ -293,6 +355,8 @@ class Window_Settings
def value_left() end def value_left() end
def value_right() end def value_right() end
def action() end def action() end
def select(previous) end
def deselect() end
end end
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
@ -321,6 +385,13 @@ class Window_Settings
super(settings_content, screen_id, position, name, parameter, bool_value || false) super(settings_content, screen_id, position, name, parameter, bool_value || false)
end end
def value=(value)
if (value != @value)
Audio.se_play(PARAMETER_CHANGE_AUDIO, 70, value ? 125 : 75)
end
super(value)
end
def get_display_value def get_display_value
return @value ? tr("ON") : tr("OFF") return @value ? tr("ON") : tr("OFF")
end end
@ -339,6 +410,26 @@ class Window_Settings
end end
end end
# ----------------------------------------------------------------------------------------
class SwitchPatameter < BoolParameter
TYPE = :switch
def initialize(settings_content, screen_id, position, name, parameter, bool_value, switch, invert)
@switch = switch
@invert = invert
super(settings_content, screen_id, position, name, parameter, bool_value)
end
def update_parameter
super()
if @switch
$game_switches[@switch] = invert ? !@value : @value
end
end
end
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
class IntParameter < BaseParameter class IntParameter < BaseParameter
TYPE = :int TYPE = :int
@ -347,10 +438,17 @@ class Window_Settings
attr_reader :min_value attr_reader :min_value
def initialize(settings_content, screen_id, position, name, parameter, int_value, min_value, max_value) def initialize(settings_content, screen_id, position, name, parameter, int_value, min_value, max_value)
super(settings_content, screen_id, position, name, parameter, int_value)
@min_value = min_value @min_value = min_value
@max_value = max_value @max_value = max_value
super(settings_content, screen_id, position, name, parameter, int_value)
end
def value=(value)
if (value != @value)
Audio.se_play(PARAMETER_CHANGE_AUDIO, 70, ((value.to_f + @min_value.to_f) / (@max_value.to_f + @min_value.to_f) * 50.0).to_i + 75)
end
super(value)
end end
def value_left() def value_left()
@ -363,14 +461,86 @@ class Window_Settings
end end
end end
# ----------------------------------------------------------------------------------------
class SliderParameter < IntParameter
TYPE = :slider
def initialize(settings_content, screen_id, position, name, parameter, int_value, min_value, max_value)
super(settings_content, screen_id, position, name, parameter, int_value, min_value, max_value)
end
def get_display_value()
percent = (@value.to_f - @min_value.to_f) / @max_value.to_f
(percent * 100.0).to_i.to_s + "%"
end
def redraw()
@sprite.bitmap.clear
@sprite.bitmap.font.color = Color.new(255, 255, 255)
@sprite.bitmap.draw_text(0, 0, @sprite.bitmap.width - PARAMETER_VALUE_WIDTH, @sprite.bitmap.height, @name)
percent = (@value.to_f - @min_value.to_f) / @max_value.to_f
width = (PARAMETER_VALUE_WIDTH * percent).to_i
@sprite.bitmap.fill_rect(Rect.new(@sprite.bitmap.width - PARAMETER_VALUE_WIDTH, 4, PARAMETER_VALUE_WIDTH, @sprite.bitmap.height - 8), Color.new(255, 255, 255, 64))
#@sprite.bitmap.fill_rect(Rect.new(@sprite.bitmap.width - PARAMETER_VALUE_WIDTH + 1, 5, PARAMETER_VALUE_WIDTH - 2, @sprite.bitmap.height - 10), Color.new(255, 255, 255, 0))
@sprite.bitmap.fill_rect(Rect.new(@sprite.bitmap.width - PARAMETER_VALUE_WIDTH, 4, width, @sprite.bitmap.height - 8), Color.new(255, 255, 255, 255))
if percent >= 0.5
@sprite.bitmap.font.color = Color.new(0, 0, 0)
@sprite.bitmap.draw_text(@sprite.bitmap.width - PARAMETER_VALUE_WIDTH, 4, width, @sprite.bitmap.height - 8, get_display_value, 1)
else
@sprite.bitmap.font.color = Color.new(255, 255, 255)
@sprite.bitmap.draw_text(@sprite.bitmap.width - PARAMETER_VALUE_WIDTH + width, 4, PARAMETER_VALUE_WIDTH - width, @sprite.bitmap.height - 8, get_display_value, 1)
end
if (@settings_content.need_draw_line(@screen_id, @position))
@sprite.bitmap.fill_rect(Rect.new(0, PARAMETER_HEIGHT - 1, PARAMETER_WIDTH, 2), Color.new(255, 255, 255, 24))
end
end
end
# ----------------------------------------------------------------------------------------
class FloatParameter < BaseParameter
TYPE = :float
attr_reader :max_value
attr_reader :min_value
attr_reader :step
def initialize(settings_content, screen_id, position, name, parameter, float_value, step, min_value, max_value)
@step = step
@min_value = min_value
@max_value = max_value
super(settings_content, screen_id, position, name, parameter, float_value)
end
def value=(value)
if (value != @value)
Audio.se_play(PARAMETER_CHANGE_AUDIO, 70, ((value + @min_value) / (@max_value + @min_value) * 50.0).to_i + 75)
end
super(value)
end
def value_left()
self.value = (@value - step).clamp(@min_value, @max_value)
redraw
end
def value_right()
self.value = (@value + step).clamp(@min_value, @max_value)
redraw
end
end
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
class EnumParameter < IntParameter class EnumParameter < IntParameter
TYPE = :enum TYPE = :enum
def initialize(settings_content, screen_id, position, name, parameter, int_value, enum_texts) def initialize(settings_content, screen_id, position, name, parameter, int_value, enum_texts)
super(settings_content, screen_id, position, name, parameter, int_value, 0, enum_texts.length - 1)
@texts = enum_texts @texts = enum_texts
super(settings_content, screen_id, position, name, parameter, int_value, 0, enum_texts.length - 1)
end end
def get_display_value def get_display_value
@ -386,4 +556,159 @@ class Window_Settings
redraw redraw
end end
end end
#----------------------------------------------------------------------------------------
class KeyParameter < BaseParameter
TYPE = :key
attr_reader :selection
def initialize(settings_content, screen_id, position, name, parameter, key_binds, input_bind)
@selected = false
@selection = 0
@key_binds = parameter ? Settings[parameter] : key_binds
@bind = input_bind
@waiting_for_key = false
@accept_action = false
super(settings_content, screen_id, position, name, parameter, nil)
apply
end
def get_display_value(bind_id = 0)
key_bind = @key_binds[bind_id]
if key_bind == nil
return tr("None")
end
case key_bind.type
when KeyBind::Type::Invalid
return tr("Invalid")
when KeyBind::Type::Key
return tr(Input::key_name(key_bind.scancode))
when KeyBind::Type::CButton
return tr(Input::c_button_name(key_bind.button))
when KeyBind::Type::CAxis
axis_name = Input::c_axis_name(key_bind.axis)
dir_vert = axis_name.downcase.include?("y") ? true : false
dir_horiz = axis_name.downcase.include?("x") ? true : false
return tr(axis_name + (dir_horiz || dir_vert ? (" " + (dir_vert ? (key_bind.dir == 1 ? "Up" : "Down") : (key_bind.dir == 1 ? "Right" : "Left"))) : ""))
when KeyBind::Type::JButton
return tr("Joystick Button") + " " + key_bind.button.to_s
when KeyBind::Type::JAxis
return tr("Joystick Axis") + " " + key_bind.axis.to_s + " " + key_bind.dir == 1 ? "Positive" : "Negative"
when KeyBind::Type::JHat
return tr("Joystick Hat") + " " + key_bind.hat.to_s + " " + key_bind.pos == 1 ? "Positive" : "Negative"
end
end
def redraw()
@sprite.bitmap.clear
if @selected
@sprite.bitmap.fill_rect(Rect.new(@sprite.bitmap.width - PARAMETER_KEY_WIDTH * (4 - @selection), 0, PARAMETER_KEY_WIDTH, @sprite.bitmap.height), Color.new(255, 255, 255, 48))
@sprite.bitmap.draw_text(@sprite.bitmap.width - PARAMETER_KEY_WIDTH * (4 - @selection) + 10, 0, 10, @sprite.bitmap.height, "", 1)
@sprite.bitmap.draw_text(@sprite.bitmap.width - PARAMETER_KEY_WIDTH * (3 - @selection) - 20, 0, 10, @sprite.bitmap.height, "", 1)
end
@sprite.bitmap.draw_text(0, 0, @sprite.bitmap.width - PARAMETER_KEY_WIDTH * 4, @sprite.bitmap.height, @name)
for i in 0..3
if @waiting_for_key && i == selection
@sprite.bitmap.draw_text(@sprite.bitmap.width - PARAMETER_KEY_WIDTH * (4 - i), 0, PARAMETER_KEY_WIDTH, @sprite.bitmap.height, tr("Press a key"), 1)
else
@sprite.bitmap.draw_text(@sprite.bitmap.width - PARAMETER_KEY_WIDTH * (4 - i), 0, PARAMETER_KEY_WIDTH, @sprite.bitmap.height, get_display_value(i), 1)
end
@sprite.bitmap.fill_rect(Rect.new(@sprite.bitmap.width - PARAMETER_KEY_WIDTH * (4 - i) - 1, 1, 2, @sprite.bitmap.height - 2), Color.new(255, 255, 255, 32))
end
if (@settings_content.need_draw_line(@screen_id, @position))
@sprite.bitmap.fill_rect(Rect.new(0, PARAMETER_HEIGHT - 1, PARAMETER_WIDTH, 2), Color.new(255, 255, 255, 24))
end
end
def value_left()
if !@waiting_for_key
@selection = (@selection - 1) % 4
$game_system.se_play($data_system.cursor_se)
redraw
end
end
def value_right()
if !@waiting_for_key
@selection = (@selection + 1) % 4
$game_system.se_play($data_system.cursor_se)
redraw
end
end
def action()
@accept_action = false
@waiting_for_key = true
@settings_content.waiting_for_key = true
redraw
end
def apply()
if @bind
Input::set_binding(@key_binds, @bind)
end
end
def update()
super()
if @waiting_for_key && @settings_content.waiting_for_key
key = Input::pressed_key
c_button = Input::pressed_c_button
c_axis = Input::active_c_axis
if !Input.press?(Input::ACTION)
@accept_action = true
end
if key && (!Input.press?(Input::ACTION) || @accept_action)
if key != Input::key_from_name("Backspace")
Settings[@parameter][@selection] = KeyBind.key(key)
end
@waiting_for_key = @settings_content.waiting_for_key = false
apply
redraw
elsif c_button
Settings[@parameter][@selection] = KeyBind.cbutton(c_button)
@waiting_for_key = @settings_content.waiting_for_key = false
apply
redraw
elsif c_axis
Settings[@parameter][@selection] = KeyBind.caxis(c_axis, Input::c_axis_pressure(c_axis) > 0 ? KeyBind::Positive : KeyBind::Negative)
@waiting_for_key = @settings_content.waiting_for_key = false
apply
redraw
end
end
end
def select(previous)
prev = @settings_content.get_parameter_by_sceen_id(@settings_content.screen, previous)
if prev&.respond_to?(:selection)
@selection = prev.selection
end
@selected = true
redraw
end
def deselect
@selected = false
redraw
end
end
end end

11
scripts/Input.rb Normal file
View file

@ -0,0 +1,11 @@
# Modifications for input-binding.cpp
module Input
class << self
alias_method(:c_axis_pressure_int, :c_axis_pressure)
def c_axis_pressure(axis)
normalized = c_axis_pressure_int(axis).to_f / 32767.0
return normalized < Settings[:gamepad_deadzone] / 10.0 ? 0.0 : normalized
end
end
end

View file

@ -11,7 +11,7 @@ class Window_Settings
@viewport.z = 9998 @viewport.z = 9998
@bg = Sprite.new(@viewport) @bg = Sprite.new(@viewport)
@bg.bitmap = Bitmap.new(Graphics.width, Graphics.height) @bg.bitmap = Bitmap.new(Graphics.width, Graphics.height)
@bg.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(255, 255, 255, 128)) @bg.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(255, 255, 255, 196))
@bg.blend_type = 2 @bg.blend_type = 2
@title = Sprite.new(@viewport) @title = Sprite.new(@viewport)
@title.bitmap = Bitmap.new(320, TITLE_MARGIN) @title.bitmap = Bitmap.new(320, TITLE_MARGIN)
@ -37,15 +37,27 @@ class Window_Settings
when :bool when :bool
@content.add_parameter(screen_title, BoolParameter.new(@content, screen_index, parameter_index, @content.add_parameter(screen_title, BoolParameter.new(@content, screen_index, parameter_index,
parameter_info[:name], parameter_info[:parameter], parameter_info[:default])) parameter_info[:name], parameter_info[:parameter], parameter_info[:default]))
when :switch
@content.add_parameter(screen_title, BoolParameter.new(@content, screen_index, parameter_index,
parameter_info[:name], parameter_info[:parameter], parameter_info[:default], parameter_info[:switch], parameter_info[:invert]))
when :int when :int
@content.add_parameter(screen_title, IntParameter.new(@content, screen_index, parameter_index, @content.add_parameter(screen_title, IntParameter.new(@content, screen_index, parameter_index,
parameter_info[:name], parameter_info[:parameter], parameter_info[:default], parameter_info[:min], parameter_info[:max])) parameter_info[:name], parameter_info[:parameter], parameter_info[:default], parameter_info[:min], parameter_info[:max]))
when :slider
@content.add_parameter(screen_title, SliderParameter.new(@content, screen_index, parameter_index,
parameter_info[:name], parameter_info[:parameter], parameter_info[:default], parameter_info[:min], parameter_info[:max]))
when :float
@content.add_parameter(screen_title, FloatParameter.new(@content, screen_index, parameter_index,
parameter_info[:name], parameter_info[:parameter], parameter_info[:default], parameter_info[:step], parameter_info[:min], parameter_info[:max]))
when :enum when :enum
@content.add_parameter(screen_title, EnumParameter.new(@content, screen_index, parameter_index, @content.add_parameter(screen_title, EnumParameter.new(@content, screen_index, parameter_index,
parameter_info[:name], parameter_info[:parameter], 0, parameter_info[:values])) parameter_info[:name], parameter_info[:parameter], 0, parameter_info[:values]))
when :sep when :sep
@content.add_parameter(screen_title, Separator.new(@content, screen_index, parameter_index, @content.add_parameter(screen_title, Separator.new(@content, screen_index, parameter_index,
parameter_info[:name])) parameter_info[:name]))
when :key
@content.add_parameter(screen_title, KeyParameter.new(@content, screen_index, parameter_index,
parameter_info[:name], parameter_info[:parameter], parameter_info[:key_binds], parameter_info[:bind]))
end end
end end
end end
@ -109,11 +121,18 @@ class Window_Settings
end end
return if !self.visible return if !self.visible
return if @content.waiting_for_key
# navigation # navigation
if Input.wheel_y != 0 if Input.wheel_y != 0
@content.parameter_select_offset(-Input.wheel_y.round) if (Input::key_press?(Input::key_from_name("Left Shift")))
$game_system.se_play($data_system.cursor_se) for i in 0...Input.wheel_y.round.abs
Input.wheel_y.round > 0 ? @content.parameter_right : @content.parameter_left
end
else
@content.parameter_select_offset(-Input.wheel_y.round)
$game_system.se_play($data_system.cursor_se)
end
end end
if (Input.trigger?(Input::L)) if (Input.trigger?(Input::L))
@ -174,15 +193,6 @@ class Window_Settings
if (Input.trigger?(Input::ACTION)) if (Input.trigger?(Input::ACTION))
current_parameter&.action current_parameter&.action
end end
current_val = current_parameter&.value
if current_val != old_val
current_type = current_parameter&.class&.const_get(:TYPE)
if current_type == :int || current_type == :enum
Audio.se_play("Audio/SE/text_robot.wav", 70, ((current_val.to_f + current_parameter.min_value.to_f) / (current_parameter.max_value.to_f + current_parameter.min_value.to_f) * 50.0).to_i + 75)
elsif current_type == :bool
Audio.se_play("Audio/SE/text_robot.wav", 70, current_val ? 125 : 75)
end
end
# menu closing # menu closing
if Input.trigger?(Input::CANCEL) if Input.trigger?(Input::CANCEL)

View file

@ -28,6 +28,7 @@ Game_FastTravel
# yes. # yes.
Settings Settings
Input
Sprite_Character Sprite_Character
Sprite_Picture Sprite_Picture

View file

@ -29,7 +29,6 @@
#include <SDL3/SDL_scancode.h> #include <SDL3/SDL_scancode.h>
#include <SDL3/SDL_mouse.h> #include <SDL3/SDL_mouse.h>
#include <vector>
#include <SDL3/SDL_stdinc.h> #include <SDL3/SDL_stdinc.h>
#include <assert.h> #include <assert.h>
@ -384,6 +383,148 @@ struct InputPrivate {
bindings.push_back(&bind[i]); bindings.push_back(&bind[i]);
} }
void setBindingDescs(const std::vector<SourceDesc> &descs, const Input::ButtonCode &target){
// cleaning
kbBindings.erase(
std::remove_if(
kbBindings.begin(),
kbBindings.end(),
[target](const KbBinding& b)
{ return b.target == target; }
),
kbBindings.end()
);
gcABindings.erase(
std::remove_if(
gcABindings.begin(),
gcABindings.end(),
[target](const GcAxisBinding& b)
{ return b.target == target; }
),
gcABindings.end()
);
gcBBindings.erase(
std::remove_if(
gcBBindings.begin(),
gcBBindings.end(),
[target](const GcButtonBinding& b)
{ return b.target == target; }
),
gcBBindings.end()
);
jsABindings.erase(
std::remove_if(
jsABindings.begin(),
jsABindings.end(),
[target](const JsAxisBinding& b)
{ return b.target == target; }
),
jsABindings.end()
);
jsHBindings.erase(
std::remove_if(
jsHBindings.begin(),
jsHBindings.end(),
[target](const JsHatBinding& b)
{ return b.target == target; }
),
jsHBindings.end()
);
jsBBindings.erase(
std::remove_if(
jsBBindings.begin(),
jsBBindings.end(),
[target](const JsButtonBinding& b)
{ return b.target == target; }
),
jsBBindings.end()
);
for (size_t i = 0; i < descs.size(); ++i){
const SourceDesc &src = descs[i];
if (target == Input::None)
continue;
switch (src.type){
case Invalid :
break;
case Key :
{
KbBinding bind;
bind.source = src.d.scan;
bind.target = target;
kbBindings.push_back(bind);
break;
}
case CAxis :
{
GcAxisBinding bind;
bind.source = src.d.ja.axis;
bind.dir = src.d.ja.dir;
bind.target = target;
gcABindings.push_back(bind);
break;
}
case CButton :
{
GcButtonBinding bind;
bind.source = src.d.jb;
bind.target = target;
gcBBindings.push_back(bind);
break;
}
case JAxis :
{
JsAxisBinding bind;
bind.source = src.d.ja.axis;
bind.dir = src.d.ja.dir;
bind.target = target;
jsABindings.push_back(bind);
break;
}
case JHat :
{
JsHatBinding bind;
bind.source = src.d.jh.hat;
bind.pos = src.d.jh.pos;
bind.target = target;
jsHBindings.push_back(bind);
break;
}
case JButton :
{
JsButtonBinding bind;
bind.source = src.d.jb;
bind.target = target;
jsBBindings.push_back(bind);
break;
}
default :
assert(!"unreachable");
}
}
bindings.clear();
appendBindings(kbStatBindings);
appendBindings(msBindings);
appendBindings(kbBindings);
appendBindings(gcABindings);
appendBindings(gcBBindings);
appendBindings(jsABindings);
appendBindings(jsHBindings);
appendBindings(jsBBindings);
}
void applyBindingDesc(const BDescVec &d){ void applyBindingDesc(const BDescVec &d){
kbBindings.clear(); kbBindings.clear();
gcABindings.clear(); gcABindings.clear();
@ -692,6 +833,10 @@ int Input::mouseY(){
return (EventThread::mouseState.y - rtData.screenOffset.y) * rtData.sizeResoRatio.y; return (EventThread::mouseState.y - rtData.screenOffset.y) * rtData.sizeResoRatio.y;
} }
void Input::setBinding(std::vector<SourceDesc> descs, Input::ButtonCode target){
p->setBindingDescs(descs, target);
}
// wheel support :3 // wheel support :3
float Input::wheelX() { return p->mouseWheelState.wheelX; } float Input::wheelX() { return p->mouseWheelState.wheelX; }
float Input::wheelY() { return p->mouseWheelState.wheelY; } float Input::wheelY() { return p->mouseWheelState.wheelY; }

View file

@ -19,11 +19,14 @@
** along with mkxp. If not, see <http://www.gnu.org/licenses/>. ** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <vector>
#ifndef INPUT_H #ifndef INPUT_H
#define INPUT_H #define INPUT_H
struct InputPrivate; struct InputPrivate;
struct RGSSThreadData; struct RGSSThreadData;
struct SourceDesc;
class Input{ class Input{
public: public:
@ -62,6 +65,8 @@ public:
int mouseX(); int mouseX();
int mouseY(); int mouseY();
void setBinding(std::vector<SourceDesc> descs, Input::ButtonCode target);
// more non-standard extensions // more non-standard extensions
float wheelX(); float wheelX();
float wheelY(); float wheelY();

View file

@ -100,16 +100,16 @@ static const KbBindingData defaultKbBindings[] ={
static elementsN(defaultKbBindings); static elementsN(defaultKbBindings);
static const GcBindingData defaultGcBindings[] ={ static const GcBindingData defaultGcBindings[] ={
{ SDL_GAMEPAD_BUTTON_DPAD_LEFT, Input::Left }, { SDL_GAMEPAD_BUTTON_DPAD_LEFT, Input::Left },
{ SDL_GAMEPAD_BUTTON_DPAD_RIGHT, Input::Right }, { SDL_GAMEPAD_BUTTON_DPAD_RIGHT, Input::Right },
{ SDL_GAMEPAD_BUTTON_DPAD_UP, Input::Up }, { SDL_GAMEPAD_BUTTON_DPAD_UP, Input::Up },
{ SDL_GAMEPAD_BUTTON_DPAD_DOWN, Input::Down }, { SDL_GAMEPAD_BUTTON_DPAD_DOWN, Input::Down },
{ SDL_GAMEPAD_BUTTON_SOUTH, Input::Action }, { SDL_GAMEPAD_BUTTON_SOUTH, Input::Action },
{ SDL_GAMEPAD_BUTTON_EAST, Input::Cancel }, { SDL_GAMEPAD_BUTTON_EAST, Input::Cancel },
{ SDL_GAMEPAD_BUTTON_WEST, Input::Run }, { SDL_GAMEPAD_BUTTON_WEST, Input::Run },
{ SDL_GAMEPAD_BUTTON_NORTH, Input::Items }, { SDL_GAMEPAD_BUTTON_NORTH, Input::Items },
{ SDL_GAMEPAD_BUTTON_START, Input::Menu }, { SDL_GAMEPAD_BUTTON_START, Input::Menu },
{ SDL_GAMEPAD_BUTTON_BACK, Input::Deactivate }, { SDL_GAMEPAD_BUTTON_BACK, Input::Deactivate },
{ SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, Input::L }, { SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, Input::L },
{ SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, Input::R }, { SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, Input::R },
}; };