diff options
647 files changed, 10459 insertions, 5732 deletions
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index 15bd4bc69b..44d0cb041f 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -51,6 +51,14 @@ jobs: build-mono: false artifact: true + - name: Minimal Template (target=release, tools=no, everything disabled) + cache-name: linux-template-minimal + target: release + tools: false + tests: false + sconsflags: modules_enabled_by_default=no disable_3d=yes disable_advanced_gui=yes deprecated=no minizip=no + artifact: true + steps: - uses: actions/checkout@v2 diff --git a/core/core_bind.cpp b/core/core_bind.cpp index b1858c6b32..d42d39a159 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -502,15 +502,15 @@ String OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const { return ::OS::get_singleton()->get_system_dir(::OS::SystemDir(p_dir), p_shared_storage); } -String OS::get_keycode_string(uint32_t p_code) const { +String OS::get_keycode_string(Key p_code) const { return ::keycode_get_string(p_code); } -bool OS::is_keycode_unicode(uint32_t p_unicode) const { - return ::keycode_has_unicode(p_unicode); +bool OS::is_keycode_unicode(char32_t p_unicode) const { + return ::keycode_has_unicode((Key)p_unicode); } -int OS::find_keycode_from_string(const String &p_code) const { +Key OS::find_keycode_from_string(const String &p_code) const { return find_keycode(p_code); } diff --git a/core/core_bind.h b/core/core_bind.h index 72865f583c..641e3a33ae 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -195,9 +195,9 @@ public: String get_unique_id() const; - String get_keycode_string(uint32_t p_code) const; - bool is_keycode_unicode(uint32_t p_unicode) const; - int find_keycode_from_string(const String &p_code) const; + String get_keycode_string(Key p_code) const; + bool is_keycode_unicode(char32_t p_unicode) const; + Key find_keycode_from_string(const String &p_code) const; void set_use_file_access_save_and_swap(bool p_enable); diff --git a/core/core_constants.cpp b/core/core_constants.cpp index c04d6ea56e..dd1754f010 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -71,6 +71,16 @@ static Vector<_CoreConstant> _global_constants; #define BIND_CORE_ENUM_CONSTANT(m_constant) \ _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant)); +// This just binds enum classes as if they were regular enum constants. +#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \ + _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int)m_enum::m_member)); + +#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \ + _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_name), #m_name, (int)m_enum::m_member)); + +#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \ + _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member), #m_prefix "_" #m_member, (int)m_enum::m_member, true)); + #define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \ _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), m_custom_name, m_constant)); @@ -91,6 +101,16 @@ static Vector<_CoreConstant> _global_constants; #define BIND_CORE_ENUM_CONSTANT(m_constant) \ _global_constants.push_back(_CoreConstant(#m_constant, m_constant)); +// This just binds enum classes as if they were regular enum constants. +#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \ + _global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int)m_enum::m_member)); + +#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \ + _global_constants.push_back(_CoreConstant(#m_name, (int)m_enum::m_member)); + +#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \ + _global_constants.push_back(_CoreConstant(#m_prefix "_" #m_member, (int)m_enum::m_member)); + #define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \ _global_constants.push_back(_CoreConstant(m_custom_name, m_constant)); @@ -144,326 +164,317 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_CENTER); BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_BOTTOM); - // huge list of keys - BIND_CORE_CONSTANT(SPKEY); - - BIND_CORE_ENUM_CONSTANT(KEY_ESCAPE); - BIND_CORE_ENUM_CONSTANT(KEY_TAB); - BIND_CORE_ENUM_CONSTANT(KEY_BACKTAB); - BIND_CORE_ENUM_CONSTANT(KEY_BACKSPACE); - BIND_CORE_ENUM_CONSTANT(KEY_ENTER); - BIND_CORE_ENUM_CONSTANT(KEY_KP_ENTER); - BIND_CORE_ENUM_CONSTANT(KEY_INSERT); - BIND_CORE_ENUM_CONSTANT(KEY_DELETE); - BIND_CORE_ENUM_CONSTANT(KEY_PAUSE); - BIND_CORE_ENUM_CONSTANT(KEY_PRINT); - BIND_CORE_ENUM_CONSTANT(KEY_SYSREQ); - BIND_CORE_ENUM_CONSTANT(KEY_CLEAR); - BIND_CORE_ENUM_CONSTANT(KEY_HOME); - BIND_CORE_ENUM_CONSTANT(KEY_END); - BIND_CORE_ENUM_CONSTANT(KEY_LEFT); - BIND_CORE_ENUM_CONSTANT(KEY_UP); - BIND_CORE_ENUM_CONSTANT(KEY_RIGHT); - BIND_CORE_ENUM_CONSTANT(KEY_DOWN); - BIND_CORE_ENUM_CONSTANT(KEY_PAGEUP); - BIND_CORE_ENUM_CONSTANT(KEY_PAGEDOWN); - BIND_CORE_ENUM_CONSTANT(KEY_SHIFT); - BIND_CORE_ENUM_CONSTANT(KEY_CTRL); - BIND_CORE_ENUM_CONSTANT(KEY_META); - BIND_CORE_ENUM_CONSTANT(KEY_ALT); - BIND_CORE_ENUM_CONSTANT(KEY_CAPSLOCK); - BIND_CORE_ENUM_CONSTANT(KEY_NUMLOCK); - BIND_CORE_ENUM_CONSTANT(KEY_SCROLLLOCK); - BIND_CORE_ENUM_CONSTANT(KEY_F1); - BIND_CORE_ENUM_CONSTANT(KEY_F2); - BIND_CORE_ENUM_CONSTANT(KEY_F3); - BIND_CORE_ENUM_CONSTANT(KEY_F4); - BIND_CORE_ENUM_CONSTANT(KEY_F5); - BIND_CORE_ENUM_CONSTANT(KEY_F6); - BIND_CORE_ENUM_CONSTANT(KEY_F7); - BIND_CORE_ENUM_CONSTANT(KEY_F8); - BIND_CORE_ENUM_CONSTANT(KEY_F9); - BIND_CORE_ENUM_CONSTANT(KEY_F10); - BIND_CORE_ENUM_CONSTANT(KEY_F11); - BIND_CORE_ENUM_CONSTANT(KEY_F12); - BIND_CORE_ENUM_CONSTANT(KEY_F13); - BIND_CORE_ENUM_CONSTANT(KEY_F14); - BIND_CORE_ENUM_CONSTANT(KEY_F15); - BIND_CORE_ENUM_CONSTANT(KEY_F16); - BIND_CORE_ENUM_CONSTANT(KEY_KP_MULTIPLY); - BIND_CORE_ENUM_CONSTANT(KEY_KP_DIVIDE); - BIND_CORE_ENUM_CONSTANT(KEY_KP_SUBTRACT); - BIND_CORE_ENUM_CONSTANT(KEY_KP_PERIOD); - BIND_CORE_ENUM_CONSTANT(KEY_KP_ADD); - BIND_CORE_ENUM_CONSTANT(KEY_KP_0); - BIND_CORE_ENUM_CONSTANT(KEY_KP_1); - BIND_CORE_ENUM_CONSTANT(KEY_KP_2); - BIND_CORE_ENUM_CONSTANT(KEY_KP_3); - BIND_CORE_ENUM_CONSTANT(KEY_KP_4); - BIND_CORE_ENUM_CONSTANT(KEY_KP_5); - BIND_CORE_ENUM_CONSTANT(KEY_KP_6); - BIND_CORE_ENUM_CONSTANT(KEY_KP_7); - BIND_CORE_ENUM_CONSTANT(KEY_KP_8); - BIND_CORE_ENUM_CONSTANT(KEY_KP_9); - BIND_CORE_ENUM_CONSTANT(KEY_SUPER_L); - BIND_CORE_ENUM_CONSTANT(KEY_SUPER_R); - BIND_CORE_ENUM_CONSTANT(KEY_MENU); - BIND_CORE_ENUM_CONSTANT(KEY_HYPER_L); - BIND_CORE_ENUM_CONSTANT(KEY_HYPER_R); - BIND_CORE_ENUM_CONSTANT(KEY_HELP); - BIND_CORE_ENUM_CONSTANT(KEY_DIRECTION_L); - BIND_CORE_ENUM_CONSTANT(KEY_DIRECTION_R); - BIND_CORE_ENUM_CONSTANT(KEY_BACK); - BIND_CORE_ENUM_CONSTANT(KEY_FORWARD); - BIND_CORE_ENUM_CONSTANT(KEY_STOP); - BIND_CORE_ENUM_CONSTANT(KEY_REFRESH); - BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEDOWN); - BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEMUTE); - BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEUP); - BIND_CORE_ENUM_CONSTANT(KEY_BASSBOOST); - BIND_CORE_ENUM_CONSTANT(KEY_BASSUP); - BIND_CORE_ENUM_CONSTANT(KEY_BASSDOWN); - BIND_CORE_ENUM_CONSTANT(KEY_TREBLEUP); - BIND_CORE_ENUM_CONSTANT(KEY_TREBLEDOWN); - BIND_CORE_ENUM_CONSTANT(KEY_MEDIAPLAY); - BIND_CORE_ENUM_CONSTANT(KEY_MEDIASTOP); - BIND_CORE_ENUM_CONSTANT(KEY_MEDIAPREVIOUS); - BIND_CORE_ENUM_CONSTANT(KEY_MEDIANEXT); - BIND_CORE_ENUM_CONSTANT(KEY_MEDIARECORD); - BIND_CORE_ENUM_CONSTANT(KEY_HOMEPAGE); - BIND_CORE_ENUM_CONSTANT(KEY_FAVORITES); - BIND_CORE_ENUM_CONSTANT(KEY_SEARCH); - BIND_CORE_ENUM_CONSTANT(KEY_STANDBY); - BIND_CORE_ENUM_CONSTANT(KEY_OPENURL); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHMAIL); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHMEDIA); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH0); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH1); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH2); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH3); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH4); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH5); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH6); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH7); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH8); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH9); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHA); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHB); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHC); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHD); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHE); - BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHF); - - BIND_CORE_ENUM_CONSTANT(KEY_UNKNOWN); - BIND_CORE_ENUM_CONSTANT(KEY_SPACE); - BIND_CORE_ENUM_CONSTANT(KEY_EXCLAM); - BIND_CORE_ENUM_CONSTANT(KEY_QUOTEDBL); - BIND_CORE_ENUM_CONSTANT(KEY_NUMBERSIGN); - BIND_CORE_ENUM_CONSTANT(KEY_DOLLAR); - BIND_CORE_ENUM_CONSTANT(KEY_PERCENT); - BIND_CORE_ENUM_CONSTANT(KEY_AMPERSAND); - BIND_CORE_ENUM_CONSTANT(KEY_APOSTROPHE); - BIND_CORE_ENUM_CONSTANT(KEY_PARENLEFT); - BIND_CORE_ENUM_CONSTANT(KEY_PARENRIGHT); - BIND_CORE_ENUM_CONSTANT(KEY_ASTERISK); - BIND_CORE_ENUM_CONSTANT(KEY_PLUS); - BIND_CORE_ENUM_CONSTANT(KEY_COMMA); - BIND_CORE_ENUM_CONSTANT(KEY_MINUS); - BIND_CORE_ENUM_CONSTANT(KEY_PERIOD); - BIND_CORE_ENUM_CONSTANT(KEY_SLASH); - BIND_CORE_ENUM_CONSTANT(KEY_0); - BIND_CORE_ENUM_CONSTANT(KEY_1); - BIND_CORE_ENUM_CONSTANT(KEY_2); - BIND_CORE_ENUM_CONSTANT(KEY_3); - BIND_CORE_ENUM_CONSTANT(KEY_4); - BIND_CORE_ENUM_CONSTANT(KEY_5); - BIND_CORE_ENUM_CONSTANT(KEY_6); - BIND_CORE_ENUM_CONSTANT(KEY_7); - BIND_CORE_ENUM_CONSTANT(KEY_8); - BIND_CORE_ENUM_CONSTANT(KEY_9); - BIND_CORE_ENUM_CONSTANT(KEY_COLON); - BIND_CORE_ENUM_CONSTANT(KEY_SEMICOLON); - BIND_CORE_ENUM_CONSTANT(KEY_LESS); - BIND_CORE_ENUM_CONSTANT(KEY_EQUAL); - BIND_CORE_ENUM_CONSTANT(KEY_GREATER); - BIND_CORE_ENUM_CONSTANT(KEY_QUESTION); - BIND_CORE_ENUM_CONSTANT(KEY_AT); - BIND_CORE_ENUM_CONSTANT(KEY_A); - BIND_CORE_ENUM_CONSTANT(KEY_B); - BIND_CORE_ENUM_CONSTANT(KEY_C); - BIND_CORE_ENUM_CONSTANT(KEY_D); - BIND_CORE_ENUM_CONSTANT(KEY_E); - BIND_CORE_ENUM_CONSTANT(KEY_F); - BIND_CORE_ENUM_CONSTANT(KEY_G); - BIND_CORE_ENUM_CONSTANT(KEY_H); - BIND_CORE_ENUM_CONSTANT(KEY_I); - BIND_CORE_ENUM_CONSTANT(KEY_J); - BIND_CORE_ENUM_CONSTANT(KEY_K); - BIND_CORE_ENUM_CONSTANT(KEY_L); - BIND_CORE_ENUM_CONSTANT(KEY_M); - BIND_CORE_ENUM_CONSTANT(KEY_N); - BIND_CORE_ENUM_CONSTANT(KEY_O); - BIND_CORE_ENUM_CONSTANT(KEY_P); - BIND_CORE_ENUM_CONSTANT(KEY_Q); - BIND_CORE_ENUM_CONSTANT(KEY_R); - BIND_CORE_ENUM_CONSTANT(KEY_S); - BIND_CORE_ENUM_CONSTANT(KEY_T); - BIND_CORE_ENUM_CONSTANT(KEY_U); - BIND_CORE_ENUM_CONSTANT(KEY_V); - BIND_CORE_ENUM_CONSTANT(KEY_W); - BIND_CORE_ENUM_CONSTANT(KEY_X); - BIND_CORE_ENUM_CONSTANT(KEY_Y); - BIND_CORE_ENUM_CONSTANT(KEY_Z); - BIND_CORE_ENUM_CONSTANT(KEY_BRACKETLEFT); - BIND_CORE_ENUM_CONSTANT(KEY_BACKSLASH); - BIND_CORE_ENUM_CONSTANT(KEY_BRACKETRIGHT); - BIND_CORE_ENUM_CONSTANT(KEY_ASCIICIRCUM); - BIND_CORE_ENUM_CONSTANT(KEY_UNDERSCORE); - BIND_CORE_ENUM_CONSTANT(KEY_QUOTELEFT); - BIND_CORE_ENUM_CONSTANT(KEY_BRACELEFT); - BIND_CORE_ENUM_CONSTANT(KEY_BAR); - BIND_CORE_ENUM_CONSTANT(KEY_BRACERIGHT); - BIND_CORE_ENUM_CONSTANT(KEY_ASCIITILDE); - BIND_CORE_ENUM_CONSTANT(KEY_NOBREAKSPACE); - BIND_CORE_ENUM_CONSTANT(KEY_EXCLAMDOWN); - BIND_CORE_ENUM_CONSTANT(KEY_CENT); - BIND_CORE_ENUM_CONSTANT(KEY_STERLING); - BIND_CORE_ENUM_CONSTANT(KEY_CURRENCY); - BIND_CORE_ENUM_CONSTANT(KEY_YEN); - BIND_CORE_ENUM_CONSTANT(KEY_BROKENBAR); - BIND_CORE_ENUM_CONSTANT(KEY_SECTION); - BIND_CORE_ENUM_CONSTANT(KEY_DIAERESIS); - BIND_CORE_ENUM_CONSTANT(KEY_COPYRIGHT); - BIND_CORE_ENUM_CONSTANT(KEY_ORDFEMININE); - BIND_CORE_ENUM_CONSTANT(KEY_GUILLEMOTLEFT); - BIND_CORE_ENUM_CONSTANT(KEY_NOTSIGN); - BIND_CORE_ENUM_CONSTANT(KEY_HYPHEN); - BIND_CORE_ENUM_CONSTANT(KEY_REGISTERED); - BIND_CORE_ENUM_CONSTANT(KEY_MACRON); - BIND_CORE_ENUM_CONSTANT(KEY_DEGREE); - BIND_CORE_ENUM_CONSTANT(KEY_PLUSMINUS); - BIND_CORE_ENUM_CONSTANT(KEY_TWOSUPERIOR); - BIND_CORE_ENUM_CONSTANT(KEY_THREESUPERIOR); - BIND_CORE_ENUM_CONSTANT(KEY_ACUTE); - BIND_CORE_ENUM_CONSTANT(KEY_MU); - BIND_CORE_ENUM_CONSTANT(KEY_PARAGRAPH); - BIND_CORE_ENUM_CONSTANT(KEY_PERIODCENTERED); - BIND_CORE_ENUM_CONSTANT(KEY_CEDILLA); - BIND_CORE_ENUM_CONSTANT(KEY_ONESUPERIOR); - BIND_CORE_ENUM_CONSTANT(KEY_MASCULINE); - BIND_CORE_ENUM_CONSTANT(KEY_GUILLEMOTRIGHT); - BIND_CORE_ENUM_CONSTANT(KEY_ONEQUARTER); - BIND_CORE_ENUM_CONSTANT(KEY_ONEHALF); - BIND_CORE_ENUM_CONSTANT(KEY_THREEQUARTERS); - BIND_CORE_ENUM_CONSTANT(KEY_QUESTIONDOWN); - BIND_CORE_ENUM_CONSTANT(KEY_AGRAVE); - BIND_CORE_ENUM_CONSTANT(KEY_AACUTE); - BIND_CORE_ENUM_CONSTANT(KEY_ACIRCUMFLEX); - BIND_CORE_ENUM_CONSTANT(KEY_ATILDE); - BIND_CORE_ENUM_CONSTANT(KEY_ADIAERESIS); - BIND_CORE_ENUM_CONSTANT(KEY_ARING); - BIND_CORE_ENUM_CONSTANT(KEY_AE); - BIND_CORE_ENUM_CONSTANT(KEY_CCEDILLA); - BIND_CORE_ENUM_CONSTANT(KEY_EGRAVE); - BIND_CORE_ENUM_CONSTANT(KEY_EACUTE); - BIND_CORE_ENUM_CONSTANT(KEY_ECIRCUMFLEX); - BIND_CORE_ENUM_CONSTANT(KEY_EDIAERESIS); - BIND_CORE_ENUM_CONSTANT(KEY_IGRAVE); - BIND_CORE_ENUM_CONSTANT(KEY_IACUTE); - BIND_CORE_ENUM_CONSTANT(KEY_ICIRCUMFLEX); - BIND_CORE_ENUM_CONSTANT(KEY_IDIAERESIS); - BIND_CORE_ENUM_CONSTANT(KEY_ETH); - BIND_CORE_ENUM_CONSTANT(KEY_NTILDE); - BIND_CORE_ENUM_CONSTANT(KEY_OGRAVE); - BIND_CORE_ENUM_CONSTANT(KEY_OACUTE); - BIND_CORE_ENUM_CONSTANT(KEY_OCIRCUMFLEX); - BIND_CORE_ENUM_CONSTANT(KEY_OTILDE); - BIND_CORE_ENUM_CONSTANT(KEY_ODIAERESIS); - BIND_CORE_ENUM_CONSTANT(KEY_MULTIPLY); - BIND_CORE_ENUM_CONSTANT(KEY_OOBLIQUE); - BIND_CORE_ENUM_CONSTANT(KEY_UGRAVE); - BIND_CORE_ENUM_CONSTANT(KEY_UACUTE); - BIND_CORE_ENUM_CONSTANT(KEY_UCIRCUMFLEX); - BIND_CORE_ENUM_CONSTANT(KEY_UDIAERESIS); - BIND_CORE_ENUM_CONSTANT(KEY_YACUTE); - BIND_CORE_ENUM_CONSTANT(KEY_THORN); - BIND_CORE_ENUM_CONSTANT(KEY_SSHARP); - - BIND_CORE_ENUM_CONSTANT(KEY_DIVISION); - BIND_CORE_ENUM_CONSTANT(KEY_YDIAERESIS); - - BIND_CORE_ENUM_CONSTANT(KEY_CODE_MASK); - BIND_CORE_ENUM_CONSTANT(KEY_MODIFIER_MASK); - - BIND_CORE_ENUM_CONSTANT(KEY_MASK_SHIFT); - BIND_CORE_ENUM_CONSTANT(KEY_MASK_ALT); - BIND_CORE_ENUM_CONSTANT(KEY_MASK_META); - BIND_CORE_ENUM_CONSTANT(KEY_MASK_CTRL); - BIND_CORE_ENUM_CONSTANT_NO_VAL(KEY_MASK_CMD); - BIND_CORE_ENUM_CONSTANT(KEY_MASK_KPAD); - BIND_CORE_ENUM_CONSTANT(KEY_MASK_GROUP_SWITCH); - - // mouse - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_LEFT); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_RIGHT); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MIDDLE); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_XBUTTON1); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_XBUTTON2); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_UP); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_DOWN); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_LEFT); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_WHEEL_RIGHT); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_LEFT); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_RIGHT); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_MIDDLE); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_XBUTTON1); - BIND_CORE_ENUM_CONSTANT(MOUSE_BUTTON_MASK_XBUTTON2); - - // Joypad buttons - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_INVALID); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_A); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_B); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_X); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_Y); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_BACK); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_GUIDE); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_START); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_LEFT_STICK); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_RIGHT_STICK); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_LEFT_SHOULDER); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_RIGHT_SHOULDER); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_UP); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_DOWN); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_LEFT); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_RIGHT); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_MISC1); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE1); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE2); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE3); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_PADDLE4); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_TOUCHPAD); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_SDL_MAX); - BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_MAX); - - // Joypad axes - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_INVALID); - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_LEFT_X); - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_LEFT_Y); - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_RIGHT_X); - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_RIGHT_Y); - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_TRIGGER_LEFT); - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_TRIGGER_RIGHT); - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_SDL_MAX); - BIND_CORE_ENUM_CONSTANT(JOY_AXIS_MAX); - - // midi - BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF); - BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON); - BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_AFTERTOUCH); - BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_CONTROL_CHANGE); - BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_PROGRAM_CHANGE); - BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_CHANNEL_PRESSURE); - BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_PITCH_BEND); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SPECIAL); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ESCAPE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TAB); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKTAB); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKSPACE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ENTER); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_ENTER); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, INSERT); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_DELETE, KEY_DELETE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAUSE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PRINT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SYSREQ); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CLEAR); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HOME); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, END); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, RIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAGEUP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAGEDOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SHIFT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CTRL); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, META); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ALT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CAPSLOCK); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NUMLOCK); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SCROLLLOCK); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F1); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F2); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F3); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F4); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F5); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F6); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F7); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F8); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F9); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F10); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F11); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F12); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F13); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F14); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F15); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F16); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_MULTIPLY); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_DIVIDE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_SUBTRACT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_PERIOD); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_ADD); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_0); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_1); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_2); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_3); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_4); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_5); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_6); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_7); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_8); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_9); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SUPER_L); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SUPER_R); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MENU); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HYPER_L); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HYPER_R); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HELP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIRECTION_L); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIRECTION_R); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACK); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, FORWARD); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, STOP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, REFRESH); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEDOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEMUTE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEUP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BASSBOOST); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BASSUP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BASSDOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TREBLEUP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TREBLEDOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIAPLAY); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIASTOP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIAPREVIOUS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIANEXT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIARECORD); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HOMEPAGE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, FAVORITES); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SEARCH); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, STANDBY); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OPENURL); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHMAIL); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHMEDIA); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH0); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH1); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH2); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH3); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH4); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH5); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH6); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH7); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH8); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH9); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHA); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHB); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHC); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHD); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHF); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UNKNOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SPACE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EXCLAM); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUOTEDBL); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NUMBERSIGN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DOLLAR); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PERCENT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AMPERSAND); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, APOSTROPHE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PARENLEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PARENRIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASTERISK); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PLUS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, COMMA); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MINUS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PERIOD); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SLASH); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_0, KEY_0); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_1, KEY_1); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_2, KEY_2); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_3, KEY_3); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_4, KEY_4); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_5, KEY_5); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_6, KEY_6); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_7, KEY_7); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_8, KEY_8); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_9, KEY_9); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, COLON); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SEMICOLON); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LESS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EQUAL); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, GREATER); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUESTION); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, A); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, B); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, C); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, D); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, E); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, G); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, H); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, I); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, J); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, K); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, L); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, M); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, N); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, O); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, P); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Q); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, R); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, S); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, T); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, U); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, V); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, W); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, X); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Y); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Z); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACKETLEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKSLASH); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACKETRIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASCIICIRCUM); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UNDERSCORE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUOTELEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACELEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BAR); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACERIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASCIITILDE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NOBREAKSPACE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EXCLAMDOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CENT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, STERLING); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CURRENCY); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YEN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BROKENBAR); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SECTION); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIAERESIS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, COPYRIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ORDFEMININE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, GUILLEMOTLEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NOTSIGN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HYPHEN); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_REGISTERED, KEY_REGISTERED); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MACRON); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DEGREE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PLUSMINUS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TWOSUPERIOR); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, THREESUPERIOR); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ACUTE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MU); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PARAGRAPH); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PERIODCENTERED); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CEDILLA); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ONESUPERIOR); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MASCULINE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, GUILLEMOTRIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ONEQUARTER); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ONEHALF); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, THREEQUARTERS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUESTIONDOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AGRAVE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AACUTE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ACIRCUMFLEX); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ATILDE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ADIAERESIS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ARING); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CCEDILLA); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EGRAVE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EACUTE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ECIRCUMFLEX); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EDIAERESIS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, IGRAVE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, IACUTE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ICIRCUMFLEX); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, IDIAERESIS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ETH); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NTILDE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OGRAVE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OACUTE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OCIRCUMFLEX); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OTILDE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ODIAERESIS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MULTIPLY); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OOBLIQUE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UGRAVE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UACUTE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UCIRCUMFLEX); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UDIAERESIS); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YACUTE); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, THORN); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SSHARP); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DIVISION); + BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YDIAERESIS); + + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(KeyModifierMask, KEY_CODE_MASK, CODE_MASK); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(KeyModifierMask, KEY_MODIFIER_MASK, MODIFIER_MASK); + BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, SHIFT); + BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, ALT); + BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, META); + BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, CTRL); + BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(KeyModifierMask, KEY_MASK, CMD); + BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, KPAD); + BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, GROUP_SWITCH); + + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, LEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, RIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MIDDLE); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_UP); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_DOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_LEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_RIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON1, MB_XBUTTON1); + BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON2, MB_XBUTTON2); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_LEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_RIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_MIDDLE); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_XBUTTON1); + BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MASK_XBUTTON2); + + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, INVALID); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, A); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, B); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, X); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, Y); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, BACK); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, GUIDE); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, START); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, LEFT_STICK); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, RIGHT_STICK); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, LEFT_SHOULDER); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, RIGHT_SHOULDER); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_UP); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_DOWN); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_LEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_RIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC1); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE1); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE2); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE3); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE4); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, TOUCHPAD); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, SDL_MAX); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MAX); + + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, INVALID); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, LEFT_X); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, LEFT_Y); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, RIGHT_X); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, RIGHT_Y); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, TRIGGER_LEFT); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, TRIGGER_RIGHT); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, SDL_MAX); + BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, MAX); + + BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_OFF); + BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_ON); + BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, AFTERTOUCH); + BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CONTROL_CHANGE); + BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PROGRAM_CHANGE); + BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CHANNEL_PRESSURE); + BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PITCH_BEND); // error list diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index 4770c9c65f..a65408fdda 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -774,13 +774,13 @@ static GDNativeTypePtr gdnative_packed_vector3_array_operator_index_const(const static GDNativeVariantPtr gdnative_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { Array *self = (Array *)p_self; ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self[p_index]; + return (GDNativeVariantPtr)&self->operator[](p_index); } static GDNativeVariantPtr gdnative_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { const Array *self = (const Array *)p_self; ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self[p_index]; + return (GDNativeVariantPtr)&self->operator[](p_index); } /* OBJECT API */ diff --git a/core/input/input.cpp b/core/input/input.cpp index 35ca8aefe6..6fd8aca01b 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -35,7 +35,7 @@ #include "core/input/input_map.h" #include "core/os/os.h" -static const char *_joy_buttons[JOY_BUTTON_SDL_MAX] = { +static const char *_joy_buttons[(size_t)JoyButton::SDL_MAX] = { "a", "b", "x", @@ -59,7 +59,7 @@ static const char *_joy_buttons[JOY_BUTTON_SDL_MAX] = { "touchpad", }; -static const char *_joy_axes[JOY_AXIS_SDL_MAX] = { +static const char *_joy_axes[(size_t)JoyAxis::SDL_MAX] = { "leftx", "lefty", "rightx", @@ -225,11 +225,15 @@ bool Input::is_key_pressed(Key p_keycode) const { bool Input::is_mouse_button_pressed(MouseButton p_button) const { _THREAD_SAFE_METHOD_ - return (mouse_button_mask & (1 << (p_button - 1))) != 0; + return (mouse_button_mask & mouse_button_to_mask(p_button)) != MouseButton::NONE; } -static int _combine_device(int p_value, int p_device) { - return p_value | (p_device << 20); +static JoyAxis _combine_device(JoyAxis p_value, int p_device) { + return JoyAxis((int)p_value | (p_device << 20)); +} + +static JoyButton _combine_device(JoyButton p_value, int p_device) { + return JoyButton((int)p_value | (p_device << 20)); } bool Input::is_joy_button_pressed(int p_device, JoyButton p_button) const { @@ -338,7 +342,7 @@ Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_po float Input::get_joy_axis(int p_device, JoyAxis p_axis) const { _THREAD_SAFE_METHOD_ - int c = _combine_device(p_axis, p_device); + JoyAxis c = _combine_device(p_axis, p_device); if (_joy_axis.has(c)) { return _joy_axis[c]; } else { @@ -412,11 +416,11 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S js.mapping = mapping; } else { js.connected = false; - for (int i = 0; i < JOY_BUTTON_MAX; i++) { - int c = _combine_device(i, p_idx); + for (int i = 0; i < (int)JoyButton::MAX; i++) { + JoyButton c = _combine_device((JoyButton)i, p_idx); joy_buttons_pressed.erase(c); } - for (int i = 0; i < JOY_AXIS_MAX; i++) { + for (int i = 0; i < (int)JoyAxis::MAX; i++) { set_joy_axis(p_idx, (JoyAxis)i, 0.0f); } } @@ -454,7 +458,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em // require additional handling by this class. Ref<InputEventKey> k = p_event; - if (k.is_valid() && !k->is_echo() && k->get_keycode() != 0) { + if (k.is_valid() && !k->is_echo() && k->get_keycode() != Key::NONE) { if (k->is_pressed()) { keys_pressed.insert(k->get_keycode()); } else { @@ -466,9 +470,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em if (mb.is_valid()) { if (mb->is_pressed()) { - mouse_button_mask |= (MouseButton)(1 << (mb->get_button_index() - 1)); + mouse_button_mask |= mouse_button_to_mask(mb->get_button_index()); } else { - mouse_button_mask &= (MouseButton) ~(1 << (mb->get_button_index() - 1)); + mouse_button_mask &= ~mouse_button_to_mask(mb->get_button_index()); } Point2 pos = mb->get_global_position(); @@ -476,7 +480,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em set_mouse_position(pos); } - if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mb->get_button_index() == 1) { + if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mb->get_button_index() == MouseButton::LEFT) { Ref<InputEventScreenTouch> touch_event; touch_event.instantiate(); touch_event->set_pressed(mb->is_pressed()); @@ -493,7 +497,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em set_mouse_position(pos); } - if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mm->get_button_mask() & 1) { + if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && (mm->get_button_mask() & MouseButton::LEFT) != MouseButton::NONE) { Ref<InputEventScreenDrag> drag_event; drag_event.instantiate(); @@ -539,11 +543,11 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em button_event->set_position(st->get_position()); button_event->set_global_position(st->get_position()); button_event->set_pressed(st->is_pressed()); - button_event->set_button_index(MOUSE_BUTTON_LEFT); + button_event->set_button_index(MouseButton::LEFT); if (st->is_pressed()) { - button_event->set_button_mask(MouseButton(mouse_button_mask | MOUSE_BUTTON_MASK_LEFT)); + button_event->set_button_mask(MouseButton(mouse_button_mask | MouseButton::MASK_LEFT)); } else { - button_event->set_button_mask(MouseButton(mouse_button_mask & ~MOUSE_BUTTON_MASK_LEFT)); + button_event->set_button_mask(MouseButton(mouse_button_mask & ~MouseButton::MASK_LEFT)); } _parse_input_event_impl(button_event, true); @@ -576,7 +580,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em Ref<InputEventJoypadButton> jb = p_event; if (jb.is_valid()) { - int c = _combine_device(jb->get_button_index(), jb->get_device()); + JoyButton c = _combine_device(jb->get_button_index(), jb->get_device()); if (jb->is_pressed()) { joy_buttons_pressed.insert(c); @@ -624,7 +628,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em void Input::set_joy_axis(int p_device, JoyAxis p_axis, float p_value) { _THREAD_SAFE_METHOD_ - int c = _combine_device(p_axis, p_device); + JoyAxis c = _combine_device(p_axis, p_device); _joy_axis[c] = p_value; } @@ -692,7 +696,7 @@ Point2 Input::get_last_mouse_speed() const { return mouse_speed_track.speed; } -int Input::get_mouse_button_mask() const { +MouseButton Input::get_mouse_button_mask() const { return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state(); } @@ -710,11 +714,11 @@ Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, con // detect the warp: if the relative distance is greater than the half of the size of the relevant rect // (checked per each axis), it will be considered as the consequence of a former pointer warp. - const Point2i rel_sgn(p_motion->get_relative().x >= 0.0f ? 1 : -1, p_motion->get_relative().y >= 0.0 ? 1 : -1); + const Point2i rel_sign(p_motion->get_relative().x >= 0.0f ? 1 : -1, p_motion->get_relative().y >= 0.0 ? 1 : -1); const Size2i warp_margin = p_rect.size * 0.5f; const Point2i rel_warped( - Math::fmod(p_motion->get_relative().x + rel_sgn.x * warp_margin.x, p_rect.size.x) - rel_sgn.x * warp_margin.x, - Math::fmod(p_motion->get_relative().y + rel_sgn.y * warp_margin.y, p_rect.size.y) - rel_sgn.y * warp_margin.y); + Math::fmod(p_motion->get_relative().x + rel_sign.x * warp_margin.x, p_rect.size.x) - rel_sign.x * warp_margin.x, + Math::fmod(p_motion->get_relative().y + rel_sign.y * warp_margin.y, p_rect.size.y) - rel_sign.y * warp_margin.y); const Point2i pos_local = p_motion->get_global_position() - p_rect.position; const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y)); @@ -771,8 +775,8 @@ void Input::ensure_touch_mouse_raised() { button_event->set_position(mouse_pos); button_event->set_global_position(mouse_pos); button_event->set_pressed(false); - button_event->set_button_index(MOUSE_BUTTON_LEFT); - button_event->set_button_mask(MouseButton(mouse_button_mask & ~MOUSE_BUTTON_MASK_LEFT)); + button_event->set_button_index(MouseButton::LEFT); + button_event->set_button_mask(MouseButton(mouse_button_mask & ~MouseButton::MASK_LEFT)); _parse_input_event_impl(button_event, true); } @@ -876,10 +880,10 @@ void Input::joy_button(int p_device, JoyButton p_button, bool p_pressed) { _THREAD_SAFE_METHOD_; Joypad &joy = joy_names[p_device]; //printf("got button %i, mapping is %i\n", p_button, joy.mapping); - if (joy.last_buttons[p_button] == p_pressed) { + if (joy.last_buttons[(size_t)p_button] == p_pressed) { return; } - joy.last_buttons[p_button] = p_pressed; + joy.last_buttons[(size_t)p_button] = p_pressed; if (joy.mapping == -1) { _button_event(p_device, p_button, p_pressed); return; @@ -901,16 +905,16 @@ void Input::joy_button(int p_device, JoyButton p_button, bool p_pressed) { void Input::joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value) { _THREAD_SAFE_METHOD_; - ERR_FAIL_INDEX(p_axis, JOY_AXIS_MAX); + ERR_FAIL_INDEX((int)p_axis, (int)JoyAxis::MAX); Joypad &joy = joy_names[p_device]; - if (joy.last_axis[p_axis] == p_value.value) { + if (joy.last_axis[(size_t)p_axis] == p_value.value) { return; } //when changing direction quickly, insert fake event to release pending inputmap actions - float last = joy.last_axis[p_axis]; + float last = joy.last_axis[(size_t)p_axis]; if (p_value.min == 0 && (last < 0.25 || last > 0.75) && (last - 0.5) * (p_value.value - 0.5) < 0) { JoyAxisValue jx; jx.min = p_value.min; @@ -923,7 +927,7 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value) joy_axis(p_device, p_axis, jx); } - joy.last_axis[p_axis] = p_value.value; + joy.last_axis[(size_t)p_axis] = p_value.value; float val = p_value.min == 0 ? -1.0f + 2.0f * p_value.value : p_value.value; if (joy.mapping == -1) { @@ -935,32 +939,32 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value) if (map.type == TYPE_BUTTON) { bool pressed = map.value > 0.5; - if (pressed == joy_buttons_pressed.has(_combine_device(map.index, p_device))) { + if (pressed == joy_buttons_pressed.has(_combine_device((JoyButton)map.index, p_device))) { // Button already pressed or released; so ignore. return; } _button_event(p_device, (JoyButton)map.index, pressed); // Ensure opposite D-Pad button is also released. - switch (map.index) { - case JOY_BUTTON_DPAD_UP: - if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_DOWN, p_device))) { - _button_event(p_device, JOY_BUTTON_DPAD_DOWN, false); + switch ((JoyButton)map.index) { + case JoyButton::DPAD_UP: + if (joy_buttons_pressed.has(_combine_device(JoyButton::DPAD_DOWN, p_device))) { + _button_event(p_device, JoyButton::DPAD_DOWN, false); } break; - case JOY_BUTTON_DPAD_DOWN: - if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_UP, p_device))) { - _button_event(p_device, JOY_BUTTON_DPAD_UP, false); + case JoyButton::DPAD_DOWN: + if (joy_buttons_pressed.has(_combine_device(JoyButton::DPAD_UP, p_device))) { + _button_event(p_device, JoyButton::DPAD_UP, false); } break; - case JOY_BUTTON_DPAD_LEFT: - if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_RIGHT, p_device))) { - _button_event(p_device, JOY_BUTTON_DPAD_RIGHT, false); + case JoyButton::DPAD_LEFT: + if (joy_buttons_pressed.has(_combine_device(JoyButton::DPAD_RIGHT, p_device))) { + _button_event(p_device, JoyButton::DPAD_RIGHT, false); } break; - case JOY_BUTTON_DPAD_RIGHT: - if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_LEFT, p_device))) { - _button_event(p_device, JOY_BUTTON_DPAD_LEFT, false); + case JoyButton::DPAD_RIGHT: + if (joy_buttons_pressed.has(_combine_device(JoyButton::DPAD_LEFT, p_device))) { + _button_event(p_device, JoyButton::DPAD_LEFT, false); } break; default: @@ -977,27 +981,27 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value) //printf("invalid mapping\n"); } -void Input::joy_hat(int p_device, int p_val) { +void Input::joy_hat(int p_device, HatMask p_val) { _THREAD_SAFE_METHOD_; const Joypad &joy = joy_names[p_device]; - JoyEvent map[HAT_MAX]; + JoyEvent map[(size_t)HatDir::MAX]; - map[HatDir::HAT_UP].type = TYPE_BUTTON; - map[HatDir::HAT_UP].index = JOY_BUTTON_DPAD_UP; - map[HatDir::HAT_UP].value = 0; + map[(size_t)HatDir::UP].type = TYPE_BUTTON; + map[(size_t)HatDir::UP].index = (int)JoyButton::DPAD_UP; + map[(size_t)HatDir::UP].value = 0; - map[HatDir::HAT_RIGHT].type = TYPE_BUTTON; - map[HatDir::HAT_RIGHT].index = JOY_BUTTON_DPAD_RIGHT; - map[HatDir::HAT_RIGHT].value = 0; + map[(size_t)HatDir::RIGHT].type = TYPE_BUTTON; + map[(size_t)HatDir::RIGHT].index = (int)JoyButton::DPAD_RIGHT; + map[(size_t)HatDir::RIGHT].value = 0; - map[HatDir::HAT_DOWN].type = TYPE_BUTTON; - map[HatDir::HAT_DOWN].index = JOY_BUTTON_DPAD_DOWN; - map[HatDir::HAT_DOWN].value = 0; + map[(size_t)HatDir::DOWN].type = TYPE_BUTTON; + map[(size_t)HatDir::DOWN].index = (int)JoyButton::DPAD_DOWN; + map[(size_t)HatDir::DOWN].value = 0; - map[HatDir::HAT_LEFT].type = TYPE_BUTTON; - map[HatDir::HAT_LEFT].index = JOY_BUTTON_DPAD_LEFT; - map[HatDir::HAT_LEFT].value = 0; + map[(size_t)HatDir::LEFT].type = TYPE_BUTTON; + map[(size_t)HatDir::LEFT].index = (int)JoyButton::DPAD_LEFT; + map[(size_t)HatDir::LEFT].value = 0; if (joy.mapping != -1) { _get_mapped_hat_events(map_db[joy.mapping], (HatDir)0, map); @@ -1005,18 +1009,18 @@ void Input::joy_hat(int p_device, int p_val) { int cur_val = joy_names[p_device].hat_current; - for (int hat_direction = 0, hat_mask = 1; hat_direction < HAT_MAX; hat_direction++, hat_mask <<= 1) { - if ((p_val & hat_mask) != (cur_val & hat_mask)) { + for (int hat_direction = 0, hat_mask = 1; hat_direction < (int)HatDir::MAX; hat_direction++, hat_mask <<= 1) { + if (((int)p_val & hat_mask) != (cur_val & hat_mask)) { if (map[hat_direction].type == TYPE_BUTTON) { - _button_event(p_device, (JoyButton)map[hat_direction].index, p_val & hat_mask); + _button_event(p_device, (JoyButton)map[hat_direction].index, (int)p_val & hat_mask); } if (map[hat_direction].type == TYPE_AXIS) { - _axis_event(p_device, (JoyAxis)map[hat_direction].index, (p_val & hat_mask) ? map[hat_direction].value : 0.0); + _axis_event(p_device, (JoyAxis)map[hat_direction].index, ((int)p_val & hat_mask) ? map[hat_direction].value : 0.0); } } } - joy_names[p_device].hat_current = p_val; + joy_names[p_device].hat_current = (int)p_val; } void Input::_button_event(int p_device, JoyButton p_index, bool p_pressed) { @@ -1049,10 +1053,10 @@ Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, event.type = binding.outputType; switch (binding.outputType) { case TYPE_BUTTON: - event.index = binding.output.button; + event.index = (int)binding.output.button; return event; case TYPE_AXIS: - event.index = binding.output.axis.axis; + event.index = (int)binding.output.axis.axis; switch (binding.output.axis.range) { case POSITIVE_HALF_AXIS: event.value = 1; @@ -1104,7 +1108,7 @@ Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, J } switch (binding.outputType) { case TYPE_BUTTON: - event.index = binding.output.button; + event.index = (int)binding.output.button; switch (binding.input.axis.range) { case POSITIVE_HALF_AXIS: event.value = shifted_positive_value; @@ -1121,7 +1125,7 @@ Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, J } return event; case TYPE_AXIS: - event.index = binding.output.axis.axis; + event.index = (int)binding.output.axis.axis; event.value = value; if (binding.output.axis.range != binding.input.axis.range) { switch (binding.output.axis.range) { @@ -1150,43 +1154,43 @@ void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat for (int i = 0; i < mapping.bindings.size(); i++) { const JoyBinding binding = mapping.bindings[i]; if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) { - int hat_direction; + HatDir hat_direction; switch (binding.input.hat.hat_mask) { - case HatMask::HAT_MASK_UP: - hat_direction = HatDir::HAT_UP; + case HatMask::UP: + hat_direction = HatDir::UP; break; - case HatMask::HAT_MASK_RIGHT: - hat_direction = HatDir::HAT_RIGHT; + case HatMask::RIGHT: + hat_direction = HatDir::RIGHT; break; - case HatMask::HAT_MASK_DOWN: - hat_direction = HatDir::HAT_DOWN; + case HatMask::DOWN: + hat_direction = HatDir::DOWN; break; - case HatMask::HAT_MASK_LEFT: - hat_direction = HatDir::HAT_LEFT; + case HatMask::LEFT: + hat_direction = HatDir::LEFT; break; default: ERR_PRINT_ONCE("Joypad button mapping error."); continue; } - r_events[hat_direction].type = binding.outputType; + r_events[(size_t)hat_direction].type = binding.outputType; switch (binding.outputType) { case TYPE_BUTTON: - r_events[hat_direction].index = binding.output.button; + r_events[(size_t)hat_direction].index = (int)binding.output.button; break; case TYPE_AXIS: - r_events[hat_direction].index = binding.output.axis.axis; + r_events[(size_t)hat_direction].index = (int)binding.output.axis.axis; switch (binding.output.axis.range) { case POSITIVE_HALF_AXIS: - r_events[hat_direction].value = 1; + r_events[(size_t)hat_direction].value = 1; break; case NEGATIVE_HALF_AXIS: - r_events[hat_direction].value = -1; + r_events[(size_t)hat_direction].value = -1; break; case FULL_AXIS: // It doesn't make sense for a hat direction to map to a full axis, // but keeping as a default for a trigger with a positive half-axis. - r_events[hat_direction].value = 1; + r_events[(size_t)hat_direction].value = 1; break; } break; @@ -1198,21 +1202,21 @@ void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat } JoyButton Input::_get_output_button(String output) { - for (int i = 0; i < JOY_BUTTON_SDL_MAX; i++) { + for (int i = 0; i < (int)JoyButton::SDL_MAX; i++) { if (output == _joy_buttons[i]) { return JoyButton(i); } } - return JoyButton::JOY_BUTTON_INVALID; + return JoyButton::INVALID; } JoyAxis Input::_get_output_axis(String output) { - for (int i = 0; i < JOY_AXIS_SDL_MAX; i++) { + for (int i = 0; i < (int)JoyAxis::SDL_MAX; i++) { if (output == _joy_axes[i]) { return JoyAxis(i); } } - return JoyAxis::JOY_AXIS_INVALID; + return JoyAxis::INVALID; } void Input::parse_mapping(String p_mapping) { @@ -1273,16 +1277,16 @@ void Input::parse_mapping(String p_mapping) { JoyButton output_button = _get_output_button(output); JoyAxis output_axis = _get_output_axis(output); - ERR_CONTINUE_MSG(output_button == JOY_BUTTON_INVALID && output_axis == JOY_AXIS_INVALID, + ERR_CONTINUE_MSG(output_button == JoyButton::INVALID && output_axis == JoyAxis::INVALID, vformat("Unrecognised output string \"%s\" in mapping:\n%s", output, p_mapping)); - ERR_CONTINUE_MSG(output_button != JOY_BUTTON_INVALID && output_axis != JOY_AXIS_INVALID, + ERR_CONTINUE_MSG(output_button != JoyButton::INVALID && output_axis != JoyAxis::INVALID, vformat("Output string \"%s\" matched both button and axis in mapping:\n%s", output, p_mapping)); JoyBinding binding; - if (output_button != JOY_BUTTON_INVALID) { + if (output_button != JoyButton::INVALID) { binding.outputType = TYPE_BUTTON; binding.output.button = output_button; - } else if (output_axis != JOY_AXIS_INVALID) { + } else if (output_axis != JoyAxis::INVALID) { binding.outputType = TYPE_AXIS; binding.output.axis.axis = output_axis; binding.output.axis.range = output_range; diff --git a/core/input/input.h b/core/input/input.h index f63138a875..dd57ebb563 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -85,11 +85,11 @@ public: typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event); private: - int mouse_button_mask = 0; + MouseButton mouse_button_mask = MouseButton::NONE; - Set<int> keys_pressed; - Set<int> joy_buttons_pressed; - Map<int, float> _joy_axis; + Set<Key> keys_pressed; + Set<JoyButton> joy_buttons_pressed; + Map<JoyAxis, float> _joy_axis; //Map<StringName,int> custom_action_press; Vector3 gravity; Vector3 accelerometer; @@ -133,9 +133,9 @@ private: StringName name; StringName uid; bool connected = false; - bool last_buttons[JOY_BUTTON_MAX] = { false }; - float last_axis[JOY_AXIS_MAX] = { 0.0f }; - int last_hat = HatMask::HAT_MASK_CENTER; + bool last_buttons[(size_t)JoyButton::MAX] = { false }; + float last_axis[(size_t)JoyAxis::MAX] = { 0.0f }; + HatMask last_hat = HatMask::CENTER; int mapping = -1; int hat_current = 0; }; @@ -162,7 +162,7 @@ private: struct JoyEvent { int type; - int index; + int index; // Can be either JoyAxis or JoyButton. float value; }; @@ -206,7 +206,7 @@ private: JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button); JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, JoyAxis p_axis, float p_value); - void _get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat, JoyEvent r_events[HAT_MAX]); + void _get_mapped_hat_events(const JoyDeviceMapping &mapping, HatDir p_hat, JoyEvent r_events[(size_t)HatDir::MAX]); JoyButton _get_output_button(String output); JoyAxis _get_output_axis(String output); void _button_event(int p_device, JoyButton p_index, bool p_pressed); @@ -273,7 +273,7 @@ public: Point2 get_mouse_position() const; Point2 get_last_mouse_speed() const; - int get_mouse_button_mask() const; + MouseButton get_mouse_button_mask() const; void warp_mouse_position(const Vector2 &p_to); Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect); @@ -312,7 +312,7 @@ public: void parse_mapping(String p_mapping); void joy_button(int p_device, JoyButton p_button, bool p_pressed); void joy_axis(int p_device, JoyAxis p_axis, const JoyAxisValue &p_value); - void joy_hat(int p_device, int p_val); + void joy_hat(int p_device, HatMask p_val); void add_joy_mapping(String p_mapping, bool p_update_existing = false); void remove_joy_mapping(String p_guid); diff --git a/core/input/input_enums.h b/core/input/input_enums.h index 4479a85bfe..8601007ac9 100644 --- a/core/input/input_enums.h +++ b/core/input/input_enums.h @@ -31,90 +31,106 @@ #ifndef INPUT_ENUMS_H #define INPUT_ENUMS_H -enum HatDir { - HAT_UP = 0, - HAT_RIGHT = 1, - HAT_DOWN = 2, - HAT_LEFT = 3, - HAT_MAX = 4, +enum class HatDir { + UP = 0, + RIGHT = 1, + DOWN = 2, + LEFT = 3, + MAX = 4, }; -enum HatMask { - HAT_MASK_CENTER = 0, - HAT_MASK_UP = 1, - HAT_MASK_RIGHT = 2, - HAT_MASK_DOWN = 4, - HAT_MASK_LEFT = 8, +enum class HatMask { + CENTER = 0, + UP = 1, + RIGHT = 2, + DOWN = 4, + LEFT = 8, }; -enum JoyAxis { - JOY_AXIS_INVALID = -1, - JOY_AXIS_LEFT_X = 0, - JOY_AXIS_LEFT_Y = 1, - JOY_AXIS_RIGHT_X = 2, - JOY_AXIS_RIGHT_Y = 3, - JOY_AXIS_TRIGGER_LEFT = 4, - JOY_AXIS_TRIGGER_RIGHT = 5, - JOY_AXIS_SDL_MAX = 6, - JOY_AXIS_MAX = 10, // OpenVR supports up to 5 Joysticks making a total of 10 axes. +enum class JoyAxis { + INVALID = -1, + LEFT_X = 0, + LEFT_Y = 1, + RIGHT_X = 2, + RIGHT_Y = 3, + TRIGGER_LEFT = 4, + TRIGGER_RIGHT = 5, + SDL_MAX = 6, + MAX = 10, // OpenVR supports up to 5 Joysticks making a total of 10 axes. }; -enum JoyButton { - JOY_BUTTON_INVALID = -1, - JOY_BUTTON_A = 0, - JOY_BUTTON_B = 1, - JOY_BUTTON_X = 2, - JOY_BUTTON_Y = 3, - JOY_BUTTON_BACK = 4, - JOY_BUTTON_GUIDE = 5, - JOY_BUTTON_START = 6, - JOY_BUTTON_LEFT_STICK = 7, - JOY_BUTTON_RIGHT_STICK = 8, - JOY_BUTTON_LEFT_SHOULDER = 9, - JOY_BUTTON_RIGHT_SHOULDER = 10, - JOY_BUTTON_DPAD_UP = 11, - JOY_BUTTON_DPAD_DOWN = 12, - JOY_BUTTON_DPAD_LEFT = 13, - JOY_BUTTON_DPAD_RIGHT = 14, - JOY_BUTTON_MISC1 = 15, - JOY_BUTTON_PADDLE1 = 16, - JOY_BUTTON_PADDLE2 = 17, - JOY_BUTTON_PADDLE3 = 18, - JOY_BUTTON_PADDLE4 = 19, - JOY_BUTTON_TOUCHPAD = 20, - JOY_BUTTON_SDL_MAX = 21, - JOY_BUTTON_MAX = 36, // Android supports up to 36 buttons. +enum class JoyButton { + INVALID = -1, + A = 0, + B = 1, + X = 2, + Y = 3, + BACK = 4, + GUIDE = 5, + START = 6, + LEFT_STICK = 7, + RIGHT_STICK = 8, + LEFT_SHOULDER = 9, + RIGHT_SHOULDER = 10, + DPAD_UP = 11, + DPAD_DOWN = 12, + DPAD_LEFT = 13, + DPAD_RIGHT = 14, + MISC1 = 15, + PADDLE1 = 16, + PADDLE2 = 17, + PADDLE3 = 18, + PADDLE4 = 19, + TOUCHPAD = 20, + SDL_MAX = 21, + MAX = 36, // Android supports up to 36 buttons. }; -enum MIDIMessage { - MIDI_MESSAGE_NONE = 0, - MIDI_MESSAGE_NOTE_OFF = 0x8, - MIDI_MESSAGE_NOTE_ON = 0x9, - MIDI_MESSAGE_AFTERTOUCH = 0xA, - MIDI_MESSAGE_CONTROL_CHANGE = 0xB, - MIDI_MESSAGE_PROGRAM_CHANGE = 0xC, - MIDI_MESSAGE_CHANNEL_PRESSURE = 0xD, - MIDI_MESSAGE_PITCH_BEND = 0xE, +enum class MIDIMessage { + NONE = 0, + NOTE_OFF = 0x8, + NOTE_ON = 0x9, + AFTERTOUCH = 0xA, + CONTROL_CHANGE = 0xB, + PROGRAM_CHANGE = 0xC, + CHANNEL_PRESSURE = 0xD, + PITCH_BEND = 0xE, }; -enum MouseButton { - MOUSE_BUTTON_NONE = 0, - MOUSE_BUTTON_LEFT = 1, - MOUSE_BUTTON_RIGHT = 2, - MOUSE_BUTTON_MIDDLE = 3, - MOUSE_BUTTON_WHEEL_UP = 4, - MOUSE_BUTTON_WHEEL_DOWN = 5, - MOUSE_BUTTON_WHEEL_LEFT = 6, - MOUSE_BUTTON_WHEEL_RIGHT = 7, - MOUSE_BUTTON_XBUTTON1 = 8, - MOUSE_BUTTON_XBUTTON2 = 9, - MOUSE_BUTTON_MASK_LEFT = (1 << (MOUSE_BUTTON_LEFT - 1)), - MOUSE_BUTTON_MASK_RIGHT = (1 << (MOUSE_BUTTON_RIGHT - 1)), - MOUSE_BUTTON_MASK_MIDDLE = (1 << (MOUSE_BUTTON_MIDDLE - 1)), - MOUSE_BUTTON_MASK_XBUTTON1 = (1 << (MOUSE_BUTTON_XBUTTON1 - 1)), - MOUSE_BUTTON_MASK_XBUTTON2 = (1 << (MOUSE_BUTTON_XBUTTON2 - 1)), +enum class MouseButton { + NONE = 0, + LEFT = 1, + RIGHT = 2, + MIDDLE = 3, + WHEEL_UP = 4, + WHEEL_DOWN = 5, + WHEEL_LEFT = 6, + WHEEL_RIGHT = 7, + MB_XBUTTON1 = 8, // "XBUTTON1" is a reserved word on Windows. + MB_XBUTTON2 = 9, // "XBUTTON2" is a reserved word on Windows. + MASK_LEFT = (1 << (LEFT - 1)), + MASK_RIGHT = (1 << (RIGHT - 1)), + MASK_MIDDLE = (1 << (MIDDLE - 1)), + MASK_XBUTTON1 = (1 << (MB_XBUTTON1 - 1)), + MASK_XBUTTON2 = (1 << (MB_XBUTTON2 - 1)), }; +inline MouseButton mouse_button_to_mask(MouseButton button) { + return MouseButton(1 << ((int)button - 1)); +} + +inline MouseButton operator&(MouseButton a, MouseButton b) { + return (MouseButton)((int)a & (int)b); +} + +inline MouseButton operator|(MouseButton a, MouseButton b) { + return (MouseButton)((int)a | (int)b); +} + +inline MouseButton operator^(MouseButton a, MouseButton b) { + return (MouseButton)((int)a ^ (int)b); +} + inline MouseButton &operator|=(MouseButton &a, MouseButton b) { return (MouseButton &)((int &)a |= (int)b); } @@ -123,4 +139,28 @@ inline MouseButton &operator&=(MouseButton &a, MouseButton b) { return (MouseButton &)((int &)a &= (int)b); } +inline MouseButton operator~(MouseButton a) { + return (MouseButton)(~(int)a); +} + +inline HatMask operator|(HatMask a, HatMask b) { + return (HatMask)((int)a | (int)b); +} + +inline HatMask operator&(HatMask a, HatMask b) { + return (HatMask)((int)a & (int)b); +} + +inline HatMask &operator&=(HatMask &a, HatMask b) { + return (HatMask &)((int &)a &= (int)b); +} + +inline HatMask &operator|=(HatMask &a, HatMask b) { + return (HatMask &)((int &)a |= (int)b); +} + +inline HatMask operator~(HatMask a) { + return (HatMask)(~(int)a); +} + #endif // INPUT_ENUMS_H diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index af3190bb17..ccde8838e1 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -203,19 +203,19 @@ void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModif set_meta_pressed(event->is_meta_pressed()); } -uint32_t InputEventWithModifiers::get_modifiers_mask() const { - uint32_t mask = 0; +Key InputEventWithModifiers::get_modifiers_mask() const { + Key mask = Key::NONE; if (is_ctrl_pressed()) { - mask |= KEY_MASK_CTRL; + mask |= KeyModifierMask::CTRL; } if (is_shift_pressed()) { - mask |= KEY_MASK_SHIFT; + mask |= KeyModifierMask::SHIFT; } if (is_alt_pressed()) { - mask |= KEY_MASK_ALT; + mask |= KeyModifierMask::ALT; } if (is_meta_pressed()) { - mask |= KEY_MASK_META; + mask |= KeyModifierMask::META; } return mask; } @@ -224,16 +224,16 @@ String InputEventWithModifiers::as_text() const { Vector<String> mod_names; if (is_ctrl_pressed()) { - mod_names.push_back(find_keycode_name(KEY_CTRL)); + mod_names.push_back(find_keycode_name(Key::CTRL)); } if (is_shift_pressed()) { - mod_names.push_back(find_keycode_name(KEY_SHIFT)); + mod_names.push_back(find_keycode_name(Key::SHIFT)); } if (is_alt_pressed()) { - mod_names.push_back(find_keycode_name(KEY_ALT)); + mod_names.push_back(find_keycode_name(Key::ALT)); } if (is_meta_pressed()) { - mod_names.push_back(find_keycode_name(KEY_META)); + mod_names.push_back(find_keycode_name(Key::META)); } if (!mod_names.is_empty()) { @@ -325,12 +325,12 @@ Key InputEventKey::get_physical_keycode() const { return physical_keycode; } -void InputEventKey::set_unicode(uint32_t p_unicode) { +void InputEventKey::set_unicode(char32_t p_unicode) { unicode = p_unicode; emit_changed(); } -uint32_t InputEventKey::get_unicode() const { +char32_t InputEventKey::get_unicode() const { return unicode; } @@ -343,18 +343,18 @@ bool InputEventKey::is_echo() const { return echo; } -uint32_t InputEventKey::get_keycode_with_modifiers() const { +Key InputEventKey::get_keycode_with_modifiers() const { return keycode | get_modifiers_mask(); } -uint32_t InputEventKey::get_physical_keycode_with_modifiers() const { +Key InputEventKey::get_physical_keycode_with_modifiers() const { return physical_keycode | get_modifiers_mask(); } String InputEventKey::as_text() const { String kc; - if (keycode == 0) { + if (keycode == Key::NONE) { kc = keycode_get_string(physical_keycode) + " (" + RTR("Physical") + ")"; } else { kc = keycode_get_string(keycode); @@ -374,11 +374,11 @@ String InputEventKey::to_string() { String kc = ""; String physical = "false"; - if (keycode == 0) { - kc = itos(physical_keycode) + " (" + keycode_get_string(physical_keycode) + ")"; + if (keycode == Key::NONE) { + kc = itos((int64_t)physical_keycode) + " (" + keycode_get_string(physical_keycode) + ")"; physical = "true"; } else { - kc = itos(keycode) + " (" + keycode_get_string(keycode) + ")"; + kc = itos((int64_t)keycode) + " (" + keycode_get_string(keycode) + ")"; } String mods = InputEventWithModifiers::as_text(); @@ -390,22 +390,22 @@ String InputEventKey::to_string() { Ref<InputEventKey> InputEventKey::create_reference(Key p_keycode) { Ref<InputEventKey> ie; ie.instantiate(); - ie->set_keycode(p_keycode & KEY_CODE_MASK); - ie->set_unicode(p_keycode & KEY_CODE_MASK); + ie->set_keycode(p_keycode & KeyModifierMask::CODE_MASK); + ie->set_unicode(char32_t(p_keycode & KeyModifierMask::CODE_MASK)); - if (p_keycode & KEY_MASK_SHIFT) { + if ((p_keycode & KeyModifierMask::SHIFT) != Key::NONE) { ie->set_shift_pressed(true); } - if (p_keycode & KEY_MASK_ALT) { + if ((p_keycode & KeyModifierMask::ALT) != Key::NONE) { ie->set_alt_pressed(true); } - if (p_keycode & KEY_MASK_CTRL) { + if ((p_keycode & KeyModifierMask::CTRL) != Key::NONE) { ie->set_ctrl_pressed(true); } - if (p_keycode & KEY_MASK_CMD) { + if ((p_keycode & KeyModifierMask::CMD) != Key::NONE) { ie->set_command_pressed(true); } - if (p_keycode & KEY_MASK_META) { + if ((p_keycode & KeyModifierMask::META) != Key::NONE) { ie->set_meta_pressed(true); } @@ -419,14 +419,14 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed } bool match = false; - if (get_keycode() == 0) { - uint32_t code = get_physical_keycode_with_modifiers(); - uint32_t event_code = key->get_physical_keycode_with_modifiers(); + if (get_keycode() == Key::NONE) { + Key code = get_physical_keycode_with_modifiers(); + Key event_code = key->get_physical_keycode_with_modifiers(); match = get_physical_keycode() == key->get_physical_keycode() && (!key->is_pressed() || (code & event_code) == code); } else { - uint32_t code = get_keycode_with_modifiers(); - uint32_t event_code = key->get_keycode_with_modifiers(); + Key code = get_keycode_with_modifiers(); + Key event_code = key->get_keycode_with_modifiers(); match = get_keycode() == key->get_keycode() && (!key->is_pressed() || (code & event_code) == code); } @@ -452,7 +452,7 @@ bool InputEventKey::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) return false; } - if (keycode == 0) { + if (keycode == Key::NONE) { return physical_keycode == key->physical_keycode && (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask()); } else { @@ -487,12 +487,12 @@ void InputEventKey::_bind_methods() { /////////////////////////////////// -void InputEventMouse::set_button_mask(int p_mask) { +void InputEventMouse::set_button_mask(MouseButton p_mask) { button_mask = p_mask; emit_changed(); } -int InputEventMouse::get_button_mask() const { +MouseButton InputEventMouse::get_button_mask() const { return button_mask; } @@ -637,21 +637,21 @@ String InputEventMouseButton::as_text() const { String full_string = mods_text == "" ? "" : mods_text + "+"; // Button - int idx = get_button_index(); + MouseButton idx = get_button_index(); switch (idx) { - case MOUSE_BUTTON_LEFT: - case MOUSE_BUTTON_RIGHT: - case MOUSE_BUTTON_MIDDLE: - case MOUSE_BUTTON_WHEEL_UP: - case MOUSE_BUTTON_WHEEL_DOWN: - case MOUSE_BUTTON_WHEEL_LEFT: - case MOUSE_BUTTON_WHEEL_RIGHT: - case MOUSE_BUTTON_XBUTTON1: - case MOUSE_BUTTON_XBUTTON2: - full_string += RTR(_mouse_button_descriptions[idx - 1]); // button index starts from 1, array index starts from 0, so subtract 1 + case MouseButton::LEFT: + case MouseButton::RIGHT: + case MouseButton::MIDDLE: + case MouseButton::WHEEL_UP: + case MouseButton::WHEEL_DOWN: + case MouseButton::WHEEL_LEFT: + case MouseButton::WHEEL_RIGHT: + case MouseButton::MB_XBUTTON1: + case MouseButton::MB_XBUTTON2: + full_string += RTR(_mouse_button_descriptions[(size_t)idx - 1]); // button index starts from 1, array index starts from 0, so subtract 1 break; default: - full_string += RTR("Button") + " #" + itos(idx); + full_string += RTR("Button") + " #" + itos((int64_t)idx); break; } @@ -667,20 +667,20 @@ String InputEventMouseButton::to_string() { String p = is_pressed() ? "true" : "false"; String d = double_click ? "true" : "false"; - int idx = get_button_index(); - String button_string = itos(idx); + MouseButton idx = get_button_index(); + String button_string = itos((int64_t)idx); switch (idx) { - case MOUSE_BUTTON_LEFT: - case MOUSE_BUTTON_RIGHT: - case MOUSE_BUTTON_MIDDLE: - case MOUSE_BUTTON_WHEEL_UP: - case MOUSE_BUTTON_WHEEL_DOWN: - case MOUSE_BUTTON_WHEEL_LEFT: - case MOUSE_BUTTON_WHEEL_RIGHT: - case MOUSE_BUTTON_XBUTTON1: - case MOUSE_BUTTON_XBUTTON2: - button_string += " (" + RTR(_mouse_button_descriptions[idx - 1]) + ")"; // button index starts from 1, array index starts from 0, so subtract 1 + case MouseButton::LEFT: + case MouseButton::RIGHT: + case MouseButton::MIDDLE: + case MouseButton::WHEEL_UP: + case MouseButton::WHEEL_DOWN: + case MouseButton::WHEEL_LEFT: + case MouseButton::WHEEL_RIGHT: + case MouseButton::MB_XBUTTON1: + case MouseButton::MB_XBUTTON2: + button_string += " (" + RTR(_mouse_button_descriptions[(size_t)idx - 1]) + ")"; // button index starts from 1, array index starts from 0, so subtract 1 break; default: break; @@ -778,23 +778,23 @@ String InputEventMouseMotion::as_text() const { } String InputEventMouseMotion::to_string() { - int button_mask = get_button_mask(); - String button_mask_string = itos(button_mask); - switch (get_button_mask()) { - case MOUSE_BUTTON_MASK_LEFT: - button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_LEFT - 1]) + ")"; + MouseButton button_mask = get_button_mask(); + String button_mask_string = itos((int64_t)button_mask); + switch (button_mask) { + case MouseButton::MASK_LEFT: + button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::LEFT - 1]) + ")"; break; - case MOUSE_BUTTON_MASK_MIDDLE: - button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_MIDDLE - 1]) + ")"; + case MouseButton::MASK_MIDDLE: + button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MIDDLE - 1]) + ")"; break; - case MOUSE_BUTTON_MASK_RIGHT: - button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_RIGHT - 1]) + ")"; + case MouseButton::MASK_RIGHT: + button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::RIGHT - 1]) + ")"; break; - case MOUSE_BUTTON_MASK_XBUTTON1: - button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_XBUTTON1 - 1]) + ")"; + case MouseButton::MASK_XBUTTON1: + button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON1 - 1]) + ")"; break; - case MOUSE_BUTTON_MASK_XBUTTON2: - button_mask_string += " (" + RTR(_mouse_button_descriptions[MOUSE_BUTTON_XBUTTON2 - 1]) + ")"; + case MouseButton::MASK_XBUTTON2: + button_mask_string += " (" + RTR(_mouse_button_descriptions[(size_t)MouseButton::MB_XBUTTON2 - 1]) + ")"; break; default: break; @@ -869,7 +869,7 @@ void InputEventMouseMotion::_bind_methods() { /////////////////////////////////// void InputEventJoypadMotion::set_axis(JoyAxis p_axis) { - ERR_FAIL_INDEX(p_axis, JOY_AXIS_MAX); + ERR_FAIL_COND(p_axis < JoyAxis::LEFT_X || p_axis > JoyAxis::MAX); axis = p_axis; emit_changed(); @@ -938,7 +938,7 @@ bool InputEventJoypadMotion::is_match(const Ref<InputEvent> &p_event, bool p_exa (!p_exact_match || ((axis_value < 0) == (jm->axis_value < 0))); } -static const char *_joy_axis_descriptions[JOY_AXIS_MAX] = { +static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX] = { TTRC("Left Stick X-Axis, Joystick 0 X-Axis"), TTRC("Left Stick Y-Axis, Joystick 0 Y-Axis"), TTRC("Right Stick X-Axis, Joystick 1 X-Axis"), @@ -952,7 +952,7 @@ static const char *_joy_axis_descriptions[JOY_AXIS_MAX] = { }; String InputEventJoypadMotion::as_text() const { - String desc = axis < JOY_AXIS_MAX ? RTR(_joy_axis_descriptions[axis]) : TTR("Unknown Joypad Axis"); + String desc = axis < JoyAxis::MAX ? RTR(_joy_axis_descriptions[(size_t)axis]) : TTR("Unknown Joypad Axis"); return vformat(TTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value); } @@ -1032,7 +1032,7 @@ bool InputEventJoypadButton::is_match(const Ref<InputEvent> &p_event, bool p_exa return button_index == button->button_index; } -static const char *_joy_button_descriptions[JOY_BUTTON_SDL_MAX] = { +static const char *_joy_button_descriptions[(size_t)JoyButton::SDL_MAX] = { TTRC("Bottom Action, Sony Cross, Xbox A, Nintendo B"), TTRC("Right Action, Sony Circle, Xbox B, Nintendo A"), TTRC("Left Action, Sony Square, Xbox X, Nintendo Y"), @@ -1057,10 +1057,10 @@ static const char *_joy_button_descriptions[JOY_BUTTON_SDL_MAX] = { }; String InputEventJoypadButton::as_text() const { - String text = "Joypad Button " + itos(button_index); + String text = "Joypad Button " + itos((int64_t)button_index); - if (button_index >= 0 && button_index < JOY_BUTTON_SDL_MAX) { - text += vformat(" (%s)", _joy_button_descriptions[button_index]); + if (button_index > JoyButton::INVALID && button_index < JoyButton::SDL_MAX) { + text += vformat(" (%s)", _joy_button_descriptions[(size_t)button_index]); } if (pressure != 0) { @@ -1506,7 +1506,7 @@ int InputEventMIDI::get_controller_value() const { } String InputEventMIDI::as_text() const { - return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos(message)); + return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos((int64_t)message)); } String InputEventMIDI::to_string() { diff --git a/core/input/input_event.h b/core/input/input_event.h index 3fc8078a09..70046e4491 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -151,7 +151,7 @@ public: void set_modifiers_from_event(const InputEventWithModifiers *event); - uint32_t get_modifiers_mask() const; + Key get_modifiers_mask() const; virtual String as_text() const override; virtual String to_string() override; @@ -164,8 +164,8 @@ class InputEventKey : public InputEventWithModifiers { bool pressed = false; /// otherwise release - Key keycode = KEY_NONE; // Key enum, without modifier masks. - Key physical_keycode = KEY_NONE; + Key keycode = Key::NONE; // Key enum, without modifier masks. + Key physical_keycode = Key::NONE; uint32_t unicode = 0; ///unicode bool echo = false; /// true if this is an echo key @@ -183,14 +183,14 @@ public: void set_physical_keycode(Key p_keycode); Key get_physical_keycode() const; - void set_unicode(uint32_t p_unicode); - uint32_t get_unicode() const; + void set_unicode(char32_t p_unicode); + char32_t get_unicode() const; void set_echo(bool p_enable); virtual bool is_echo() const override; - uint32_t get_keycode_with_modifiers() const; - uint32_t get_physical_keycode_with_modifiers() const; + Key get_keycode_with_modifiers() const; + Key get_physical_keycode_with_modifiers() const; virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override; virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override; @@ -208,7 +208,7 @@ public: class InputEventMouse : public InputEventWithModifiers { GDCLASS(InputEventMouse, InputEventWithModifiers); - int button_mask = 0; + MouseButton button_mask = MouseButton::NONE; Vector2 pos; Vector2 global_pos; @@ -217,8 +217,8 @@ protected: static void _bind_methods(); public: - void set_button_mask(int p_mask); - int get_button_mask() const; + void set_button_mask(MouseButton p_mask); + MouseButton get_button_mask() const; void set_position(const Vector2 &p_pos); Vector2 get_position() const; @@ -233,7 +233,7 @@ class InputEventMouseButton : public InputEventMouse { GDCLASS(InputEventMouseButton, InputEventMouse); float factor = 1; - MouseButton button_index = MOUSE_BUTTON_NONE; + MouseButton button_index = MouseButton::NONE; bool pressed = false; //otherwise released bool double_click = false; //last even less than double click time @@ -501,7 +501,7 @@ class InputEventMIDI : public InputEvent { GDCLASS(InputEventMIDI, InputEvent); int channel = 0; - MIDIMessage message = MIDI_MESSAGE_NONE; + MIDIMessage message = MIDIMessage::NONE; int pitch = 0; int velocity = 0; int instrument = 0; diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 1ec4299093..84e1313756 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -381,320 +381,320 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() { } List<Ref<InputEvent>> inputs; - inputs.push_back(InputEventKey::create_reference(KEY_ENTER)); - inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER)); - inputs.push_back(InputEventKey::create_reference(KEY_SPACE)); + inputs.push_back(InputEventKey::create_reference(Key::ENTER)); + inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER)); + inputs.push_back(InputEventKey::create_reference(Key::SPACE)); default_builtin_cache.insert("ui_accept", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_Y)); - inputs.push_back(InputEventKey::create_reference(KEY_SPACE)); + inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::Y)); + inputs.push_back(InputEventKey::create_reference(Key::SPACE)); default_builtin_cache.insert("ui_select", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_ESCAPE)); + inputs.push_back(InputEventKey::create_reference(Key::ESCAPE)); default_builtin_cache.insert("ui_cancel", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_TAB)); + inputs.push_back(InputEventKey::create_reference(Key::TAB)); default_builtin_cache.insert("ui_focus_next", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_TAB | KEY_MASK_SHIFT)); + inputs.push_back(InputEventKey::create_reference(Key::TAB | KeyModifierMask::SHIFT)); default_builtin_cache.insert("ui_focus_prev", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_LEFT)); - inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_LEFT)); + inputs.push_back(InputEventKey::create_reference(Key::LEFT)); + inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::DPAD_LEFT)); default_builtin_cache.insert("ui_left", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_RIGHT)); - inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_RIGHT)); + inputs.push_back(InputEventKey::create_reference(Key::RIGHT)); + inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::DPAD_RIGHT)); default_builtin_cache.insert("ui_right", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_UP)); - inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_UP)); + inputs.push_back(InputEventKey::create_reference(Key::UP)); + inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::DPAD_UP)); default_builtin_cache.insert("ui_up", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DOWN)); - inputs.push_back(InputEventJoypadButton::create_reference(JOY_BUTTON_DPAD_DOWN)); + inputs.push_back(InputEventKey::create_reference(Key::DOWN)); + inputs.push_back(InputEventJoypadButton::create_reference(JoyButton::DPAD_DOWN)); default_builtin_cache.insert("ui_down", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_PAGEUP)); + inputs.push_back(InputEventKey::create_reference(Key::PAGEUP)); default_builtin_cache.insert("ui_page_up", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_PAGEDOWN)); + inputs.push_back(InputEventKey::create_reference(Key::PAGEDOWN)); default_builtin_cache.insert("ui_page_down", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_HOME)); + inputs.push_back(InputEventKey::create_reference(Key::HOME)); default_builtin_cache.insert("ui_home", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_END)); + inputs.push_back(InputEventKey::create_reference(Key::END)); default_builtin_cache.insert("ui_end", inputs); // ///// UI basic Shortcuts ///// inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_X | KEY_MASK_CMD)); - inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_SHIFT)); + inputs.push_back(InputEventKey::create_reference(Key::X | KeyModifierMask::CMD)); + inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE | KeyModifierMask::SHIFT)); default_builtin_cache.insert("ui_cut", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_C | KEY_MASK_CMD)); - inputs.push_back(InputEventKey::create_reference(KEY_INSERT | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::C | KeyModifierMask::CMD)); + inputs.push_back(InputEventKey::create_reference(Key::INSERT | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_copy", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_V | KEY_MASK_CMD)); - inputs.push_back(InputEventKey::create_reference(KEY_INSERT | KEY_MASK_SHIFT)); + inputs.push_back(InputEventKey::create_reference(Key::V | KeyModifierMask::CMD)); + inputs.push_back(InputEventKey::create_reference(Key::INSERT | KeyModifierMask::SHIFT)); default_builtin_cache.insert("ui_paste", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_Z | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::Z | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_undo", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_Z | KEY_MASK_CMD | KEY_MASK_SHIFT)); - inputs.push_back(InputEventKey::create_reference(KEY_Y | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::Z | KeyModifierMask::CMD | KeyModifierMask::SHIFT)); + inputs.push_back(InputEventKey::create_reference(Key::Y | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_redo", inputs); // ///// UI Text Input Shortcuts ///// inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_SPACE | KEY_MASK_CTRL)); + inputs.push_back(InputEventKey::create_reference(Key::SPACE | KeyModifierMask::CTRL)); default_builtin_cache.insert("ui_text_completion_query", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_ENTER)); - inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER)); + inputs.push_back(InputEventKey::create_reference(Key::ENTER)); + inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER)); default_builtin_cache.insert("ui_text_completion_accept", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_TAB)); + inputs.push_back(InputEventKey::create_reference(Key::TAB)); default_builtin_cache.insert("ui_text_completion_replace", inputs); // Newlines inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_ENTER)); - inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER)); + inputs.push_back(InputEventKey::create_reference(Key::ENTER)); + inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER)); default_builtin_cache.insert("ui_text_newline", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_ENTER | KEY_MASK_CMD)); - inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::ENTER | KeyModifierMask::CMD)); + inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_newline_blank", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_ENTER | KEY_MASK_SHIFT | KEY_MASK_CMD)); - inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER | KEY_MASK_SHIFT | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::ENTER | KeyModifierMask::SHIFT | KeyModifierMask::CMD)); + inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER | KeyModifierMask::SHIFT | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_newline_above", inputs); // Indentation inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_TAB)); + inputs.push_back(InputEventKey::create_reference(Key::TAB)); default_builtin_cache.insert("ui_text_indent", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_TAB | KEY_MASK_SHIFT)); + inputs.push_back(InputEventKey::create_reference(Key::TAB | KeyModifierMask::SHIFT)); default_builtin_cache.insert("ui_text_dedent", inputs); // Text Backspace and Delete inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE)); - inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_SHIFT)); + inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE)); + inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::SHIFT)); default_builtin_cache.insert("ui_text_backspace", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_backspace_word", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_ALT)); + inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::ALT)); default_builtin_cache.insert("ui_text_backspace_word.macos", inputs); inputs = List<Ref<InputEvent>>(); default_builtin_cache.insert("ui_text_backspace_all_to_left", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_backspace_all_to_left.macos", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DELETE)); + inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE)); default_builtin_cache.insert("ui_text_delete", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_delete_word", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_ALT)); + inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE | KeyModifierMask::ALT)); default_builtin_cache.insert("ui_text_delete_word.macos", inputs); inputs = List<Ref<InputEvent>>(); default_builtin_cache.insert("ui_text_delete_all_to_right", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DELETE | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_delete_all_to_right.macos", inputs); // Text Caret Movement Left/Right inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_LEFT)); + inputs.push_back(InputEventKey::create_reference(Key::LEFT)); default_builtin_cache.insert("ui_text_caret_left", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::LEFT | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_caret_word_left", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_ALT)); + inputs.push_back(InputEventKey::create_reference(Key::LEFT | KeyModifierMask::ALT)); default_builtin_cache.insert("ui_text_caret_word_left.macos", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_RIGHT)); + inputs.push_back(InputEventKey::create_reference(Key::RIGHT)); default_builtin_cache.insert("ui_text_caret_right", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::RIGHT | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_caret_word_right", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_ALT)); + inputs.push_back(InputEventKey::create_reference(Key::RIGHT | KeyModifierMask::ALT)); default_builtin_cache.insert("ui_text_caret_word_right.macos", inputs); // Text Caret Movement Up/Down inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_UP)); + inputs.push_back(InputEventKey::create_reference(Key::UP)); default_builtin_cache.insert("ui_text_caret_up", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DOWN)); + inputs.push_back(InputEventKey::create_reference(Key::DOWN)); default_builtin_cache.insert("ui_text_caret_down", inputs); // Text Caret Movement Line Start/End inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_HOME)); + inputs.push_back(InputEventKey::create_reference(Key::HOME)); default_builtin_cache.insert("ui_text_caret_line_start", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_A | KEY_MASK_CTRL)); - inputs.push_back(InputEventKey::create_reference(KEY_LEFT | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::A | KeyModifierMask::CTRL)); + inputs.push_back(InputEventKey::create_reference(Key::LEFT | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_caret_line_start.macos", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_END)); + inputs.push_back(InputEventKey::create_reference(Key::END)); default_builtin_cache.insert("ui_text_caret_line_end", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_E | KEY_MASK_CTRL)); - inputs.push_back(InputEventKey::create_reference(KEY_RIGHT | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::E | KeyModifierMask::CTRL)); + inputs.push_back(InputEventKey::create_reference(Key::RIGHT | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_caret_line_end.macos", inputs); // Text Caret Movement Page Up/Down inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_PAGEUP)); + inputs.push_back(InputEventKey::create_reference(Key::PAGEUP)); default_builtin_cache.insert("ui_text_caret_page_up", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_PAGEDOWN)); + inputs.push_back(InputEventKey::create_reference(Key::PAGEDOWN)); default_builtin_cache.insert("ui_text_caret_page_down", inputs); // Text Caret Movement Document Start/End inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_HOME | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::HOME | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_caret_document_start", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::UP | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_caret_document_start.macos", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_END | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::END | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_caret_document_end", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::DOWN | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_caret_document_end.macos", inputs); // Text Scrolling inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::UP | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_scroll_up", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_UP | KEY_MASK_CMD | KEY_MASK_ALT)); + inputs.push_back(InputEventKey::create_reference(Key::UP | KeyModifierMask::CMD | KeyModifierMask::ALT)); default_builtin_cache.insert("ui_text_scroll_up.macos", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::DOWN | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_scroll_down", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DOWN | KEY_MASK_CMD | KEY_MASK_ALT)); + inputs.push_back(InputEventKey::create_reference(Key::DOWN | KeyModifierMask::CMD | KeyModifierMask::ALT)); default_builtin_cache.insert("ui_text_scroll_down.macos", inputs); // Text Misc inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_A | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::A | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_select_all", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_D | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::D | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_text_select_word_under_caret", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_INSERT)); + inputs.push_back(InputEventKey::create_reference(Key::INSERT)); default_builtin_cache.insert("ui_text_toggle_insert_mode", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_MENU)); + inputs.push_back(InputEventKey::create_reference(Key::MENU)); default_builtin_cache.insert("ui_menu", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_ENTER)); - inputs.push_back(InputEventKey::create_reference(KEY_KP_ENTER)); + inputs.push_back(InputEventKey::create_reference(Key::ENTER)); + inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER)); default_builtin_cache.insert("ui_text_submit", inputs); // ///// UI Graph Shortcuts ///// inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_D | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::D | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_graph_duplicate", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_DELETE)); + inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE)); default_builtin_cache.insert("ui_graph_delete", inputs); // ///// UI File Dialog Shortcuts ///// inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_BACKSPACE)); + inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE)); default_builtin_cache.insert("ui_filedialog_up_one_level", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_F5)); + inputs.push_back(InputEventKey::create_reference(Key::F5)); default_builtin_cache.insert("ui_filedialog_refresh", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_H)); + inputs.push_back(InputEventKey::create_reference(Key::H)); default_builtin_cache.insert("ui_filedialog_show_hidden", inputs); inputs = List<Ref<InputEvent>>(); - inputs.push_back(InputEventKey::create_reference(KEY_QUOTELEFT | KEY_MASK_CMD)); + inputs.push_back(InputEventKey::create_reference(Key::QUOTELEFT | KeyModifierMask::CMD)); default_builtin_cache.insert("ui_swap_input_direction", inputs); return default_builtin_cache; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 5c1352c1b6..800ac779e5 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -85,8 +85,7 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) { } } } - query.erase(0, 1); - return query; + return query.substr(1); } Dictionary HTTPClient::_get_response_headers_as_dictionary() { diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index a1cacbd306..cd583e2533 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -134,8 +134,8 @@ public: virtual int get_preset_count() const { return 0; } virtual String get_preset_name(int p_idx) const { return String(); } - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const = 0; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const = 0; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const = 0; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const = 0; virtual String get_option_group_file() const { return String(); } virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) = 0; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 3d893afb4d..566300c716 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -261,7 +261,7 @@ Vector3 Basis::get_scale_abs() const { } Vector3 Basis::get_scale_local() const { - real_t det_sign = SGN(determinant()); + real_t det_sign = SIGN(determinant()); return det_sign * Vector3(elements[0].length(), elements[1].length(), elements[2].length()); } @@ -287,7 +287,7 @@ Vector3 Basis::get_scale() const { // matrix elements. // // The rotation part of this decomposition is returned by get_rotation* functions. - real_t det_sign = SGN(determinant()); + real_t det_sign = SIGN(determinant()); return det_sign * get_scale_abs(); } diff --git a/core/math/color.cpp b/core/math/color.cpp index dc86cacf8f..8310c342ed 100644 --- a/core/math/color.cpp +++ b/core/math/color.cpp @@ -107,6 +107,39 @@ uint64_t Color::to_rgba64() const { return c; } +String _to_hex(float p_val) { + int v = Math::round(p_val * 255); + v = CLAMP(v, 0, 255); + String ret; + + for (int i = 0; i < 2; i++) { + char32_t c[2] = { 0, 0 }; + int lv = v & 0xF; + if (lv < 10) { + c[0] = '0' + lv; + } else { + c[0] = 'a' + lv - 10; + } + + v >>= 4; + String cs = (const char32_t *)c; + ret = cs + ret; + } + + return ret; +} + +String Color::to_html(bool p_alpha) const { + String txt; + txt += _to_hex(r); + txt += _to_hex(g); + txt += _to_hex(b); + if (p_alpha) { + txt += _to_hex(a); + } + return txt; +} + float Color::get_h() const { float min = MIN(r, g); min = MIN(min, b); @@ -249,20 +282,6 @@ Color Color::hex64(uint64_t p_hex) { return Color(r, g, b, a); } -Color Color::from_rgbe9995(uint32_t p_rgbe) { - float r = p_rgbe & 0x1ff; - float g = (p_rgbe >> 9) & 0x1ff; - float b = (p_rgbe >> 18) & 0x1ff; - float e = (p_rgbe >> 27); - float m = Math::pow(2, e - 15.0 - 9.0); - - float rd = r * m; - float gd = g * m; - float bd = b * m; - - return Color(rd, gd, bd, 1.0f); -} - static int _parse_col4(const String &p_str, int p_ofs) { char character = p_str[p_ofs]; @@ -428,43 +447,24 @@ Color Color::from_string(const String &p_string, const Color &p_default) { } } -String _to_hex(float p_val) { - int v = Math::round(p_val * 255); - v = CLAMP(v, 0, 255); - String ret; - - for (int i = 0; i < 2; i++) { - char32_t c[2] = { 0, 0 }; - int lv = v & 0xF; - if (lv < 10) { - c[0] = '0' + lv; - } else { - c[0] = 'a' + lv - 10; - } - - v >>= 4; - String cs = (const char32_t *)c; - ret = cs + ret; - } - - return ret; +Color Color::from_hsv(float p_h, float p_s, float p_v, float p_alpha) { + Color c; + c.set_hsv(p_h, p_s, p_v, p_alpha); + return c; } -String Color::to_html(bool p_alpha) const { - String txt; - txt += _to_hex(r); - txt += _to_hex(g); - txt += _to_hex(b); - if (p_alpha) { - txt += _to_hex(a); - } - return txt; -} +Color Color::from_rgbe9995(uint32_t p_rgbe) { + float r = p_rgbe & 0x1ff; + float g = (p_rgbe >> 9) & 0x1ff; + float b = (p_rgbe >> 18) & 0x1ff; + float e = (p_rgbe >> 27); + float m = Math::pow(2, e - 15.0 - 9.0); -Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const { - Color c; - c.set_hsv(p_h, p_s, p_v, p_a); - return c; + float rd = r * m; + float gd = g * m; + float bd = b * m; + + return Color(rd, gd, bd, 1.0f); } Color::operator String() const { diff --git a/core/math/color.h b/core/math/color.h index a95dbf4f60..ffd0fd8f6e 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -51,6 +51,7 @@ struct Color { uint64_t to_rgba64() const; uint64_t to_argb64() const; uint64_t to_abgr64() const; + String to_html(bool p_alpha = true) const; float get_h() const; float get_s() const; float get_v() const; @@ -189,8 +190,7 @@ struct Color { static String get_named_color_name(int p_idx); static Color get_named_color(int p_idx); static Color from_string(const String &p_string, const Color &p_default); - String to_html(bool p_alpha = true) const; - Color from_hsv(float p_h, float p_s, float p_v, float p_a) const; + static Color from_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0); static Color from_rgbe9995(uint32_t p_rgbe); _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index bbed257f60..2b6d92fe0e 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -53,6 +53,10 @@ uint32_t Math::rand() { return default_rand.rand(); } +double Math::randfn(double mean, double deviation) { + return default_rand.randfn(mean, deviation); +} + int Math::step_decimals(double p_step) { static const int maxn = 10; static const double sd[maxn] = { diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index baff10af98..8df45255c9 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -266,8 +266,8 @@ public: float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f); return s * s * (3.0f - 2.0f * s); } - static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; } - static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SGN(p_to - p_from) * p_delta; } + static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; } + static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; } static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } @@ -291,6 +291,19 @@ public: return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); } + static _ALWAYS_INLINE_ float fract(float value) { + return value - floor(value); + } + static _ALWAYS_INLINE_ double fract(double value) { + return value - floor(value); + } + static _ALWAYS_INLINE_ float pingpong(float value, float length) { + return (length != 0.0f) ? abs(fract((value - length) / (length * 2.0f)) * length * 2.0f - length) : 0.0f; + } + static _ALWAYS_INLINE_ double pingpong(double value, double length) { + return (length != 0.0) ? abs(fract((value - length) / (length * 2.0)) * length * 2.0 - length) : 0.0; + } + // double only, as these functions are mainly used by the editor and not performance-critical, static double ease(double p_x, double p_c); static int step_decimals(double p_step); @@ -305,6 +318,7 @@ public: static uint32_t rand(); static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_32BIT_MAX; } static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_32BIT_MAX; } + static double randfn(double mean, double deviation); static double random(double from, double to); static float random(float from, float to); diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index df43c605f9..4bdeaa2a58 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -69,12 +69,12 @@ void Transform2D::rotate(const real_t p_phi) { real_t Transform2D::get_skew() const { real_t det = basis_determinant(); - return Math::acos(elements[0].normalized().dot(SGN(det) * elements[1].normalized())) - Math_PI * 0.5; + return Math::acos(elements[0].normalized().dot(SIGN(det) * elements[1].normalized())) - Math_PI * 0.5; } void Transform2D::set_skew(const real_t p_angle) { real_t det = basis_determinant(); - elements[1] = SGN(det) * elements[0].rotated((Math_PI * 0.5 + p_angle)).normalized() * elements[1].length(); + elements[1] = SIGN(det) * elements[0].rotated((Math_PI * 0.5 + p_angle)).normalized() * elements[1].length(); } real_t Transform2D::get_rotation() const { @@ -111,7 +111,7 @@ Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t } Size2 Transform2D::get_scale() const { - real_t det_sign = SGN(basis_determinant()); + real_t det_sign = SIGN(basis_determinant()); return Size2(elements[0].length(), det_sign * elements[1].length()); } diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 6259bdead0..718e94eee4 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -79,7 +79,7 @@ real_t Vector2::angle_to(const Vector2 &p_vector2) const { } real_t Vector2::angle_to_point(const Vector2 &p_vector2) const { - return (*this - p_vector2).angle(); + return (p_vector2 - *this).angle(); } real_t Vector2::dot(const Vector2 &p_other) const { @@ -91,7 +91,7 @@ real_t Vector2::cross(const Vector2 &p_other) const { } Vector2 Vector2::sign() const { - return Vector2(SGN(x), SGN(y)); + return Vector2(SIGN(x), SIGN(y)); } Vector2 Vector2::floor() const { diff --git a/core/math/vector2.h b/core/math/vector2.h index 332c0475fa..0a7b9d3faf 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -345,7 +345,7 @@ struct Vector2i { bool operator!=(const Vector2i &p_vec2) const; real_t aspect() const { return width / (real_t)height; } - Vector2i sign() const { return Vector2i(SGN(x), SGN(y)); } + Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } Vector2i abs() const { return Vector2i(ABS(x), ABS(y)); } Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const; diff --git a/core/math/vector3.h b/core/math/vector3.h index dc9aa60458..02a56f684e 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -217,7 +217,7 @@ Vector3 Vector3::abs() const { } Vector3 Vector3::sign() const { - return Vector3(SGN(x), SGN(y), SGN(z)); + return Vector3(SIGN(x), SIGN(y), SIGN(z)); } Vector3 Vector3::floor() const { diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 9308d09045..10c28a5bb9 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -115,7 +115,7 @@ Vector3i Vector3i::abs() const { } Vector3i Vector3i::sign() const { - return Vector3i(SGN(x), SGN(y), SGN(z)); + return Vector3i(SIGN(x), SIGN(y), SIGN(z)); } /* Operators */ diff --git a/core/object/object.cpp b/core/object/object.cpp index 498f116997..90bd697d37 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -628,7 +628,10 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons script_instance->get_property_list(p_list); } - _get_property_listv(p_list, p_reversed); + if (_extension) { + p_list->push_back(PropertyInfo(Variant::NIL, _extension->class_name, PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); + ClassDB::get_property_list(_extension->class_name, p_list, true, this); + } if (_extension && _extension->get_property_list) { uint32_t pcount; @@ -641,6 +644,8 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons } } + _get_property_listv(p_list, p_reversed); + if (!is_class("Script")) { // can still be set, but this is for user-friendliness p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT)); } @@ -1405,7 +1410,7 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable, ERR_FAIL_COND_MSG(!s->slot_map.has(*p_callable.get_base_comparator()), "Disconnecting nonexistent signal '" + p_signal + "', callable: " + p_callable + "."); - SignalData::Slot *slot = &s->slot_map[p_callable]; + SignalData::Slot *slot = &s->slot_map[*p_callable.get_base_comparator()]; if (!p_force) { slot->reference_count--; // by default is zero, if it was not referenced it will go below it diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index 4c5f0b5220..fdc43da7a5 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -33,400 +33,399 @@ #include "core/os/os.h" struct _KeyCodeText { - int code; + Key code; const char *text; }; static const _KeyCodeText _keycodes[] = { /* clang-format off */ - {KEY_ESCAPE ,"Escape"}, - {KEY_TAB ,"Tab"}, - {KEY_BACKTAB ,"BackTab"}, - {KEY_BACKSPACE ,"BackSpace"}, - {KEY_ENTER ,"Enter"}, - {KEY_KP_ENTER ,"Kp Enter"}, - {KEY_INSERT ,"Insert"}, - {KEY_DELETE ,"Delete"}, - {KEY_PAUSE ,"Pause"}, - {KEY_PRINT ,"Print"}, - {KEY_SYSREQ ,"SysReq"}, - {KEY_CLEAR ,"Clear"}, - {KEY_HOME ,"Home"}, - {KEY_END ,"End"}, - {KEY_LEFT ,"Left"}, - {KEY_UP ,"Up"}, - {KEY_RIGHT ,"Right"}, - {KEY_DOWN ,"Down"}, - {KEY_PAGEUP ,"PageUp"}, - {KEY_PAGEDOWN ,"PageDown"}, - {KEY_SHIFT ,"Shift"}, - {KEY_CTRL ,"Ctrl"}, + {Key::ESCAPE ,"Escape"}, + {Key::TAB ,"Tab"}, + {Key::BACKTAB ,"BackTab"}, + {Key::BACKSPACE ,"BackSpace"}, + {Key::ENTER ,"Enter"}, + {Key::KP_ENTER ,"Kp Enter"}, + {Key::INSERT ,"Insert"}, + {Key::KEY_DELETE ,"Delete"}, + {Key::PAUSE ,"Pause"}, + {Key::PRINT ,"Print"}, + {Key::SYSREQ ,"SysReq"}, + {Key::CLEAR ,"Clear"}, + {Key::HOME ,"Home"}, + {Key::END ,"End"}, + {Key::LEFT ,"Left"}, + {Key::UP ,"Up"}, + {Key::RIGHT ,"Right"}, + {Key::DOWN ,"Down"}, + {Key::PAGEUP ,"PageUp"}, + {Key::PAGEDOWN ,"PageDown"}, + {Key::SHIFT ,"Shift"}, + {Key::CTRL ,"Ctrl"}, #ifdef OSX_ENABLED - {KEY_META ,"Command"}, + {Key::META ,"Command"}, #else - {KEY_META ,"Meta"}, + {Key::META ,"Meta"}, #endif - {KEY_ALT ,"Alt"}, - {KEY_CAPSLOCK ,"CapsLock"}, - {KEY_NUMLOCK ,"NumLock"}, - {KEY_SCROLLLOCK ,"ScrollLock"}, - {KEY_F1 ,"F1"}, - {KEY_F2 ,"F2"}, - {KEY_F3 ,"F3"}, - {KEY_F4 ,"F4"}, - {KEY_F5 ,"F5"}, - {KEY_F6 ,"F6"}, - {KEY_F7 ,"F7"}, - {KEY_F8 ,"F8"}, - {KEY_F9 ,"F9"}, - {KEY_F10 ,"F10"}, - {KEY_F11 ,"F11"}, - {KEY_F12 ,"F12"}, - {KEY_F13 ,"F13"}, - {KEY_F14 ,"F14"}, - {KEY_F15 ,"F15"}, - {KEY_F16 ,"F16"}, - {KEY_KP_MULTIPLY ,"Kp Multiply"}, - {KEY_KP_DIVIDE ,"Kp Divide"}, - {KEY_KP_SUBTRACT ,"Kp Subtract"}, - {KEY_KP_PERIOD ,"Kp Period"}, - {KEY_KP_ADD ,"Kp Add"}, - {KEY_KP_0 ,"Kp 0"}, - {KEY_KP_1 ,"Kp 1"}, - {KEY_KP_2 ,"Kp 2"}, - {KEY_KP_3 ,"Kp 3"}, - {KEY_KP_4 ,"Kp 4"}, - {KEY_KP_5 ,"Kp 5"}, - {KEY_KP_6 ,"Kp 6"}, - {KEY_KP_7 ,"Kp 7"}, - {KEY_KP_8 ,"Kp 8"}, - {KEY_KP_9 ,"Kp 9"}, - {KEY_SUPER_L ,"Super L"}, - {KEY_SUPER_R ,"Super R"}, - {KEY_MENU ,"Menu"}, - {KEY_HYPER_L ,"Hyper L"}, - {KEY_HYPER_R ,"Hyper R"}, - {KEY_HELP ,"Help"}, - {KEY_DIRECTION_L ,"Direction L"}, - {KEY_DIRECTION_R ,"Direction R"}, - {KEY_BACK ,"Back"}, - {KEY_FORWARD ,"Forward"}, - {KEY_STOP ,"Stop"}, - {KEY_REFRESH ,"Refresh"}, - {KEY_VOLUMEDOWN ,"VolumeDown"}, - {KEY_VOLUMEMUTE ,"VolumeMute"}, - {KEY_VOLUMEUP ,"VolumeUp"}, - {KEY_BASSBOOST ,"BassBoost"}, - {KEY_BASSUP ,"BassUp"}, - {KEY_BASSDOWN ,"BassDown"}, - {KEY_TREBLEUP ,"TrebleUp"}, - {KEY_TREBLEDOWN ,"TrebleDown"}, - {KEY_MEDIAPLAY ,"MediaPlay"}, - {KEY_MEDIASTOP ,"MediaStop"}, - {KEY_MEDIAPREVIOUS ,"MediaPrevious"}, - {KEY_MEDIANEXT ,"MediaNext"}, - {KEY_MEDIARECORD ,"MediaRecord"}, - {KEY_HOMEPAGE ,"HomePage"}, - {KEY_FAVORITES ,"Favorites"}, - {KEY_SEARCH ,"Search"}, - {KEY_STANDBY ,"StandBy"}, - {KEY_LAUNCHMAIL ,"LaunchMail"}, - {KEY_LAUNCHMEDIA ,"LaunchMedia"}, - {KEY_LAUNCH0 ,"Launch0"}, - {KEY_LAUNCH1 ,"Launch1"}, - {KEY_LAUNCH2 ,"Launch2"}, - {KEY_LAUNCH3 ,"Launch3"}, - {KEY_LAUNCH4 ,"Launch4"}, - {KEY_LAUNCH5 ,"Launch5"}, - {KEY_LAUNCH6 ,"Launch6"}, - {KEY_LAUNCH7 ,"Launch7"}, - {KEY_LAUNCH8 ,"Launch8"}, - {KEY_LAUNCH9 ,"Launch9"}, - {KEY_LAUNCHA ,"LaunchA"}, - {KEY_LAUNCHB ,"LaunchB"}, - {KEY_LAUNCHC ,"LaunchC"}, - {KEY_LAUNCHD ,"LaunchD"}, - {KEY_LAUNCHE ,"LaunchE"}, - {KEY_LAUNCHF ,"LaunchF"}, - - {KEY_UNKNOWN ,"Unknown"}, - - {KEY_SPACE ,"Space"}, - {KEY_EXCLAM ,"Exclam"}, - {KEY_QUOTEDBL ,"QuoteDbl"}, - {KEY_NUMBERSIGN ,"NumberSign"}, - {KEY_DOLLAR ,"Dollar"}, - {KEY_PERCENT ,"Percent"}, - {KEY_AMPERSAND ,"Ampersand"}, - {KEY_APOSTROPHE ,"Apostrophe"}, - {KEY_PARENLEFT ,"ParenLeft"}, - {KEY_PARENRIGHT ,"ParenRight"}, - {KEY_ASTERISK ,"Asterisk"}, - {KEY_PLUS ,"Plus"}, - {KEY_COMMA ,"Comma"}, - {KEY_MINUS ,"Minus"}, - {KEY_PERIOD ,"Period"}, - {KEY_SLASH ,"Slash"}, - {KEY_0 ,"0"}, - {KEY_1 ,"1"}, - {KEY_2 ,"2"}, - {KEY_3 ,"3"}, - {KEY_4 ,"4"}, - {KEY_5 ,"5"}, - {KEY_6 ,"6"}, - {KEY_7 ,"7"}, - {KEY_8 ,"8"}, - {KEY_9 ,"9"}, - {KEY_COLON ,"Colon"}, - {KEY_SEMICOLON ,"Semicolon"}, - {KEY_LESS ,"Less"}, - {KEY_EQUAL ,"Equal"}, - {KEY_GREATER ,"Greater"}, - {KEY_QUESTION ,"Question"}, - {KEY_AT ,"At"}, - {KEY_A ,"A"}, - {KEY_B ,"B"}, - {KEY_C ,"C"}, - {KEY_D ,"D"}, - {KEY_E ,"E"}, - {KEY_F ,"F"}, - {KEY_G ,"G"}, - {KEY_H ,"H"}, - {KEY_I ,"I"}, - {KEY_J ,"J"}, - {KEY_K ,"K"}, - {KEY_L ,"L"}, - {KEY_M ,"M"}, - {KEY_N ,"N"}, - {KEY_O ,"O"}, - {KEY_P ,"P"}, - {KEY_Q ,"Q"}, - {KEY_R ,"R"}, - {KEY_S ,"S"}, - {KEY_T ,"T"}, - {KEY_U ,"U"}, - {KEY_V ,"V"}, - {KEY_W ,"W"}, - {KEY_X ,"X"}, - {KEY_Y ,"Y"}, - {KEY_Z ,"Z"}, - {KEY_BRACKETLEFT ,"BracketLeft"}, - {KEY_BACKSLASH ,"BackSlash"}, - {KEY_BRACKETRIGHT ,"BracketRight"}, - {KEY_ASCIICIRCUM ,"AsciiCircum"}, - {KEY_UNDERSCORE ,"UnderScore"}, - {KEY_QUOTELEFT ,"QuoteLeft"}, - {KEY_BRACELEFT ,"BraceLeft"}, - {KEY_BAR ,"Bar"}, - {KEY_BRACERIGHT ,"BraceRight"}, - {KEY_ASCIITILDE ,"AsciiTilde"}, - {KEY_NOBREAKSPACE ,"NoBreakSpace"}, - {KEY_EXCLAMDOWN ,"ExclamDown"}, - {KEY_CENT ,"Cent"}, - {KEY_STERLING ,"Sterling"}, - {KEY_CURRENCY ,"Currency"}, - {KEY_YEN ,"Yen"}, - {KEY_BROKENBAR ,"BrokenBar"}, - {KEY_SECTION ,"Section"}, - {KEY_DIAERESIS ,"Diaeresis"}, - {KEY_COPYRIGHT ,"Copyright"}, - {KEY_ORDFEMININE ,"Ordfeminine"}, - {KEY_GUILLEMOTLEFT ,"GuillemotLeft"}, - {KEY_NOTSIGN ,"NotSign"}, - {KEY_HYPHEN ,"Hyphen"}, - {KEY_REGISTERED ,"Registered"}, - {KEY_MACRON ,"Macron"}, - {KEY_DEGREE ,"Degree"}, - {KEY_PLUSMINUS ,"PlusMinus"}, - {KEY_TWOSUPERIOR ,"TwoSuperior"}, - {KEY_THREESUPERIOR ,"ThreeSuperior"}, - {KEY_ACUTE ,"Acute"}, - {KEY_MU ,"Mu"}, - {KEY_PARAGRAPH ,"Paragraph"}, - {KEY_PERIODCENTERED ,"PeriodCentered"}, - {KEY_CEDILLA ,"Cedilla"}, - {KEY_ONESUPERIOR ,"OneSuperior"}, - {KEY_MASCULINE ,"Masculine"}, - {KEY_GUILLEMOTRIGHT ,"GuillemotRight"}, - {KEY_ONEQUARTER ,"OneQuarter"}, - {KEY_ONEHALF ,"OneHalf"}, - {KEY_THREEQUARTERS ,"ThreeQuarters"}, - {KEY_QUESTIONDOWN ,"QuestionDown"}, - {KEY_AGRAVE ,"Agrave"}, - {KEY_AACUTE ,"Aacute"}, - {KEY_ACIRCUMFLEX ,"AcircumFlex"}, - {KEY_ATILDE ,"Atilde"}, - {KEY_ADIAERESIS ,"Adiaeresis"}, - {KEY_ARING ,"Aring"}, - {KEY_AE ,"Ae"}, - {KEY_CCEDILLA ,"Ccedilla"}, - {KEY_EGRAVE ,"Egrave"}, - {KEY_EACUTE ,"Eacute"}, - {KEY_ECIRCUMFLEX ,"Ecircumflex"}, - {KEY_EDIAERESIS ,"Ediaeresis"}, - {KEY_IGRAVE ,"Igrave"}, - {KEY_IACUTE ,"Iacute"}, - {KEY_ICIRCUMFLEX ,"Icircumflex"}, - {KEY_IDIAERESIS ,"Idiaeresis"}, - {KEY_ETH ,"Eth"}, - {KEY_NTILDE ,"Ntilde"}, - {KEY_OGRAVE ,"Ograve"}, - {KEY_OACUTE ,"Oacute"}, - {KEY_OCIRCUMFLEX ,"Ocircumflex"}, - {KEY_OTILDE ,"Otilde"}, - {KEY_ODIAERESIS ,"Odiaeresis"}, - {KEY_MULTIPLY ,"Multiply"}, - {KEY_OOBLIQUE ,"Ooblique"}, - {KEY_UGRAVE ,"Ugrave"}, - {KEY_UACUTE ,"Uacute"}, - {KEY_UCIRCUMFLEX ,"Ucircumflex"}, - {KEY_UDIAERESIS ,"Udiaeresis"}, - {KEY_YACUTE ,"Yacute"}, - {KEY_THORN ,"Thorn"}, - {KEY_SSHARP ,"Ssharp"}, - - {KEY_DIVISION ,"Division"}, - {KEY_YDIAERESIS ,"Ydiaeresis"}, - {0 ,nullptr} + {Key::ALT ,"Alt"}, + {Key::CAPSLOCK ,"CapsLock"}, + {Key::NUMLOCK ,"NumLock"}, + {Key::SCROLLLOCK ,"ScrollLock"}, + {Key::F1 ,"F1"}, + {Key::F2 ,"F2"}, + {Key::F3 ,"F3"}, + {Key::F4 ,"F4"}, + {Key::F5 ,"F5"}, + {Key::F6 ,"F6"}, + {Key::F7 ,"F7"}, + {Key::F8 ,"F8"}, + {Key::F9 ,"F9"}, + {Key::F10 ,"F10"}, + {Key::F11 ,"F11"}, + {Key::F12 ,"F12"}, + {Key::F13 ,"F13"}, + {Key::F14 ,"F14"}, + {Key::F15 ,"F15"}, + {Key::F16 ,"F16"}, + {Key::KP_MULTIPLY ,"Kp Multiply"}, + {Key::KP_DIVIDE ,"Kp Divide"}, + {Key::KP_SUBTRACT ,"Kp Subtract"}, + {Key::KP_PERIOD ,"Kp Period"}, + {Key::KP_ADD ,"Kp Add"}, + {Key::KP_0 ,"Kp 0"}, + {Key::KP_1 ,"Kp 1"}, + {Key::KP_2 ,"Kp 2"}, + {Key::KP_3 ,"Kp 3"}, + {Key::KP_4 ,"Kp 4"}, + {Key::KP_5 ,"Kp 5"}, + {Key::KP_6 ,"Kp 6"}, + {Key::KP_7 ,"Kp 7"}, + {Key::KP_8 ,"Kp 8"}, + {Key::KP_9 ,"Kp 9"}, + {Key::SUPER_L ,"Super L"}, + {Key::SUPER_R ,"Super R"}, + {Key::MENU ,"Menu"}, + {Key::HYPER_L ,"Hyper L"}, + {Key::HYPER_R ,"Hyper R"}, + {Key::HELP ,"Help"}, + {Key::DIRECTION_L ,"Direction L"}, + {Key::DIRECTION_R ,"Direction R"}, + {Key::BACK ,"Back"}, + {Key::FORWARD ,"Forward"}, + {Key::STOP ,"Stop"}, + {Key::REFRESH ,"Refresh"}, + {Key::VOLUMEDOWN ,"VolumeDown"}, + {Key::VOLUMEMUTE ,"VolumeMute"}, + {Key::VOLUMEUP ,"VolumeUp"}, + {Key::BASSBOOST ,"BassBoost"}, + {Key::BASSUP ,"BassUp"}, + {Key::BASSDOWN ,"BassDown"}, + {Key::TREBLEUP ,"TrebleUp"}, + {Key::TREBLEDOWN ,"TrebleDown"}, + {Key::MEDIAPLAY ,"MediaPlay"}, + {Key::MEDIASTOP ,"MediaStop"}, + {Key::MEDIAPREVIOUS ,"MediaPrevious"}, + {Key::MEDIANEXT ,"MediaNext"}, + {Key::MEDIARECORD ,"MediaRecord"}, + {Key::HOMEPAGE ,"HomePage"}, + {Key::FAVORITES ,"Favorites"}, + {Key::SEARCH ,"Search"}, + {Key::STANDBY ,"StandBy"}, + {Key::LAUNCHMAIL ,"LaunchMail"}, + {Key::LAUNCHMEDIA ,"LaunchMedia"}, + {Key::LAUNCH0 ,"Launch0"}, + {Key::LAUNCH1 ,"Launch1"}, + {Key::LAUNCH2 ,"Launch2"}, + {Key::LAUNCH3 ,"Launch3"}, + {Key::LAUNCH4 ,"Launch4"}, + {Key::LAUNCH5 ,"Launch5"}, + {Key::LAUNCH6 ,"Launch6"}, + {Key::LAUNCH7 ,"Launch7"}, + {Key::LAUNCH8 ,"Launch8"}, + {Key::LAUNCH9 ,"Launch9"}, + {Key::LAUNCHA ,"LaunchA"}, + {Key::LAUNCHB ,"LaunchB"}, + {Key::LAUNCHC ,"LaunchC"}, + {Key::LAUNCHD ,"LaunchD"}, + {Key::LAUNCHE ,"LaunchE"}, + {Key::LAUNCHF ,"LaunchF"}, + {Key::UNKNOWN ,"Unknown"}, + {Key::SPACE ,"Space"}, + {Key::EXCLAM ,"Exclam"}, + {Key::QUOTEDBL ,"QuoteDbl"}, + {Key::NUMBERSIGN ,"NumberSign"}, + {Key::DOLLAR ,"Dollar"}, + {Key::PERCENT ,"Percent"}, + {Key::AMPERSAND ,"Ampersand"}, + {Key::APOSTROPHE ,"Apostrophe"}, + {Key::PARENLEFT ,"ParenLeft"}, + {Key::PARENRIGHT ,"ParenRight"}, + {Key::ASTERISK ,"Asterisk"}, + {Key::PLUS ,"Plus"}, + {Key::COMMA ,"Comma"}, + {Key::MINUS ,"Minus"}, + {Key::PERIOD ,"Period"}, + {Key::SLASH ,"Slash"}, + {Key::KEY_0 ,"0"}, + {Key::KEY_1 ,"1"}, + {Key::KEY_2 ,"2"}, + {Key::KEY_3 ,"3"}, + {Key::KEY_4 ,"4"}, + {Key::KEY_5 ,"5"}, + {Key::KEY_6 ,"6"}, + {Key::KEY_7 ,"7"}, + {Key::KEY_8 ,"8"}, + {Key::KEY_9 ,"9"}, + {Key::COLON ,"Colon"}, + {Key::SEMICOLON ,"Semicolon"}, + {Key::LESS ,"Less"}, + {Key::EQUAL ,"Equal"}, + {Key::GREATER ,"Greater"}, + {Key::QUESTION ,"Question"}, + {Key::AT ,"At"}, + {Key::A ,"A"}, + {Key::B ,"B"}, + {Key::C ,"C"}, + {Key::D ,"D"}, + {Key::E ,"E"}, + {Key::F ,"F"}, + {Key::G ,"G"}, + {Key::H ,"H"}, + {Key::I ,"I"}, + {Key::J ,"J"}, + {Key::K ,"K"}, + {Key::L ,"L"}, + {Key::M ,"M"}, + {Key::N ,"N"}, + {Key::O ,"O"}, + {Key::P ,"P"}, + {Key::Q ,"Q"}, + {Key::R ,"R"}, + {Key::S ,"S"}, + {Key::T ,"T"}, + {Key::U ,"U"}, + {Key::V ,"V"}, + {Key::W ,"W"}, + {Key::X ,"X"}, + {Key::Y ,"Y"}, + {Key::Z ,"Z"}, + {Key::BRACKETLEFT ,"BracketLeft"}, + {Key::BACKSLASH ,"BackSlash"}, + {Key::BRACKETRIGHT ,"BracketRight"}, + {Key::ASCIICIRCUM ,"AsciiCircum"}, + {Key::UNDERSCORE ,"UnderScore"}, + {Key::QUOTELEFT ,"QuoteLeft"}, + {Key::BRACELEFT ,"BraceLeft"}, + {Key::BAR ,"Bar"}, + {Key::BRACERIGHT ,"BraceRight"}, + {Key::ASCIITILDE ,"AsciiTilde"}, + {Key::NOBREAKSPACE ,"NoBreakSpace"}, + {Key::EXCLAMDOWN ,"ExclamDown"}, + {Key::CENT ,"Cent"}, + {Key::STERLING ,"Sterling"}, + {Key::CURRENCY ,"Currency"}, + {Key::YEN ,"Yen"}, + {Key::BROKENBAR ,"BrokenBar"}, + {Key::SECTION ,"Section"}, + {Key::DIAERESIS ,"Diaeresis"}, + {Key::COPYRIGHT ,"Copyright"}, + {Key::ORDFEMININE ,"Ordfeminine"}, + {Key::GUILLEMOTLEFT ,"GuillemotLeft"}, + {Key::NOTSIGN ,"NotSign"}, + {Key::HYPHEN ,"Hyphen"}, + {Key::KEY_REGISTERED ,"Registered"}, + {Key::MACRON ,"Macron"}, + {Key::DEGREE ,"Degree"}, + {Key::PLUSMINUS ,"PlusMinus"}, + {Key::TWOSUPERIOR ,"TwoSuperior"}, + {Key::THREESUPERIOR ,"ThreeSuperior"}, + {Key::ACUTE ,"Acute"}, + {Key::MU ,"Mu"}, + {Key::PARAGRAPH ,"Paragraph"}, + {Key::PERIODCENTERED ,"PeriodCentered"}, + {Key::CEDILLA ,"Cedilla"}, + {Key::ONESUPERIOR ,"OneSuperior"}, + {Key::MASCULINE ,"Masculine"}, + {Key::GUILLEMOTRIGHT ,"GuillemotRight"}, + {Key::ONEQUARTER ,"OneQuarter"}, + {Key::ONEHALF ,"OneHalf"}, + {Key::THREEQUARTERS ,"ThreeQuarters"}, + {Key::QUESTIONDOWN ,"QuestionDown"}, + {Key::AGRAVE ,"Agrave"}, + {Key::AACUTE ,"Aacute"}, + {Key::ACIRCUMFLEX ,"AcircumFlex"}, + {Key::ATILDE ,"Atilde"}, + {Key::ADIAERESIS ,"Adiaeresis"}, + {Key::ARING ,"Aring"}, + {Key::AE ,"Ae"}, + {Key::CCEDILLA ,"Ccedilla"}, + {Key::EGRAVE ,"Egrave"}, + {Key::EACUTE ,"Eacute"}, + {Key::ECIRCUMFLEX ,"Ecircumflex"}, + {Key::EDIAERESIS ,"Ediaeresis"}, + {Key::IGRAVE ,"Igrave"}, + {Key::IACUTE ,"Iacute"}, + {Key::ICIRCUMFLEX ,"Icircumflex"}, + {Key::IDIAERESIS ,"Idiaeresis"}, + {Key::ETH ,"Eth"}, + {Key::NTILDE ,"Ntilde"}, + {Key::OGRAVE ,"Ograve"}, + {Key::OACUTE ,"Oacute"}, + {Key::OCIRCUMFLEX ,"Ocircumflex"}, + {Key::OTILDE ,"Otilde"}, + {Key::ODIAERESIS ,"Odiaeresis"}, + {Key::MULTIPLY ,"Multiply"}, + {Key::OOBLIQUE ,"Ooblique"}, + {Key::UGRAVE ,"Ugrave"}, + {Key::UACUTE ,"Uacute"}, + {Key::UCIRCUMFLEX ,"Ucircumflex"}, + {Key::UDIAERESIS ,"Udiaeresis"}, + {Key::YACUTE ,"Yacute"}, + {Key::THORN ,"Thorn"}, + {Key::SSHARP ,"Ssharp"}, + {Key::DIVISION ,"Division"}, + {Key::YDIAERESIS ,"Ydiaeresis"}, + {Key::NONE ,nullptr} /* clang-format on */ }; -bool keycode_has_unicode(uint32_t p_keycode) { +bool keycode_has_unicode(Key p_keycode) { switch (p_keycode) { - case KEY_ESCAPE: - case KEY_TAB: - case KEY_BACKTAB: - case KEY_BACKSPACE: - case KEY_ENTER: - case KEY_KP_ENTER: - case KEY_INSERT: - case KEY_DELETE: - case KEY_PAUSE: - case KEY_PRINT: - case KEY_SYSREQ: - case KEY_CLEAR: - case KEY_HOME: - case KEY_END: - case KEY_LEFT: - case KEY_UP: - case KEY_RIGHT: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: - case KEY_SHIFT: - case KEY_CTRL: - case KEY_META: - case KEY_ALT: - case KEY_CAPSLOCK: - case KEY_NUMLOCK: - case KEY_SCROLLLOCK: - case KEY_F1: - case KEY_F2: - case KEY_F3: - case KEY_F4: - case KEY_F5: - case KEY_F6: - case KEY_F7: - case KEY_F8: - case KEY_F9: - case KEY_F10: - case KEY_F11: - case KEY_F12: - case KEY_F13: - case KEY_F14: - case KEY_F15: - case KEY_F16: - case KEY_SUPER_L: - case KEY_SUPER_R: - case KEY_MENU: - case KEY_HYPER_L: - case KEY_HYPER_R: - case KEY_HELP: - case KEY_DIRECTION_L: - case KEY_DIRECTION_R: - case KEY_BACK: - case KEY_FORWARD: - case KEY_STOP: - case KEY_REFRESH: - case KEY_VOLUMEDOWN: - case KEY_VOLUMEMUTE: - case KEY_VOLUMEUP: - case KEY_BASSBOOST: - case KEY_BASSUP: - case KEY_BASSDOWN: - case KEY_TREBLEUP: - case KEY_TREBLEDOWN: - case KEY_MEDIAPLAY: - case KEY_MEDIASTOP: - case KEY_MEDIAPREVIOUS: - case KEY_MEDIANEXT: - case KEY_MEDIARECORD: - case KEY_HOMEPAGE: - case KEY_FAVORITES: - case KEY_SEARCH: - case KEY_STANDBY: - case KEY_OPENURL: - case KEY_LAUNCHMAIL: - case KEY_LAUNCHMEDIA: - case KEY_LAUNCH0: - case KEY_LAUNCH1: - case KEY_LAUNCH2: - case KEY_LAUNCH3: - case KEY_LAUNCH4: - case KEY_LAUNCH5: - case KEY_LAUNCH6: - case KEY_LAUNCH7: - case KEY_LAUNCH8: - case KEY_LAUNCH9: - case KEY_LAUNCHA: - case KEY_LAUNCHB: - case KEY_LAUNCHC: - case KEY_LAUNCHD: - case KEY_LAUNCHE: - case KEY_LAUNCHF: + case Key::ESCAPE: + case Key::TAB: + case Key::BACKTAB: + case Key::BACKSPACE: + case Key::ENTER: + case Key::KP_ENTER: + case Key::INSERT: + case Key::KEY_DELETE: + case Key::PAUSE: + case Key::PRINT: + case Key::SYSREQ: + case Key::CLEAR: + case Key::HOME: + case Key::END: + case Key::LEFT: + case Key::UP: + case Key::RIGHT: + case Key::DOWN: + case Key::PAGEUP: + case Key::PAGEDOWN: + case Key::SHIFT: + case Key::CTRL: + case Key::META: + case Key::ALT: + case Key::CAPSLOCK: + case Key::NUMLOCK: + case Key::SCROLLLOCK: + case Key::F1: + case Key::F2: + case Key::F3: + case Key::F4: + case Key::F5: + case Key::F6: + case Key::F7: + case Key::F8: + case Key::F9: + case Key::F10: + case Key::F11: + case Key::F12: + case Key::F13: + case Key::F14: + case Key::F15: + case Key::F16: + case Key::SUPER_L: + case Key::SUPER_R: + case Key::MENU: + case Key::HYPER_L: + case Key::HYPER_R: + case Key::HELP: + case Key::DIRECTION_L: + case Key::DIRECTION_R: + case Key::BACK: + case Key::FORWARD: + case Key::STOP: + case Key::REFRESH: + case Key::VOLUMEDOWN: + case Key::VOLUMEMUTE: + case Key::VOLUMEUP: + case Key::BASSBOOST: + case Key::BASSUP: + case Key::BASSDOWN: + case Key::TREBLEUP: + case Key::TREBLEDOWN: + case Key::MEDIAPLAY: + case Key::MEDIASTOP: + case Key::MEDIAPREVIOUS: + case Key::MEDIANEXT: + case Key::MEDIARECORD: + case Key::HOMEPAGE: + case Key::FAVORITES: + case Key::SEARCH: + case Key::STANDBY: + case Key::OPENURL: + case Key::LAUNCHMAIL: + case Key::LAUNCHMEDIA: + case Key::LAUNCH0: + case Key::LAUNCH1: + case Key::LAUNCH2: + case Key::LAUNCH3: + case Key::LAUNCH4: + case Key::LAUNCH5: + case Key::LAUNCH6: + case Key::LAUNCH7: + case Key::LAUNCH8: + case Key::LAUNCH9: + case Key::LAUNCHA: + case Key::LAUNCHB: + case Key::LAUNCHC: + case Key::LAUNCHD: + case Key::LAUNCHE: + case Key::LAUNCHF: return false; + default: { + } } return true; } -String keycode_get_string(uint32_t p_code) { +String keycode_get_string(Key p_code) { String codestr; - if (p_code & KEY_MASK_SHIFT) { - codestr += find_keycode_name(KEY_SHIFT); + if ((p_code & KeyModifierMask::SHIFT) != Key::NONE) { + codestr += find_keycode_name(Key::SHIFT); codestr += "+"; } - if (p_code & KEY_MASK_ALT) { - codestr += find_keycode_name(KEY_ALT); + if ((p_code & KeyModifierMask::ALT) != Key::NONE) { + codestr += find_keycode_name(Key::ALT); codestr += "+"; } - if (p_code & KEY_MASK_CTRL) { - codestr += find_keycode_name(KEY_CTRL); + if ((p_code & KeyModifierMask::CTRL) != Key::NONE) { + codestr += find_keycode_name(Key::CTRL); codestr += "+"; } - if (p_code & KEY_MASK_META) { - codestr += find_keycode_name(KEY_META); + if ((p_code & KeyModifierMask::META) != Key::NONE) { + codestr += find_keycode_name(Key::META); codestr += "+"; } - p_code &= KEY_CODE_MASK; + p_code &= KeyModifierMask::CODE_MASK; const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { - if (kct->code == (int)p_code) { + if (kct->code == p_code) { codestr += kct->text; return codestr; } kct++; } - codestr += String::chr(p_code); + codestr += String::chr((char32_t)p_code); return codestr; } -int find_keycode(const String &p_code) { +Key find_keycode(const String &p_code) { const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { @@ -436,10 +435,10 @@ int find_keycode(const String &p_code) { kct++; } - return 0; + return Key::NONE; } -const char *find_keycode_name(int p_keycode) { +const char *find_keycode_name(Key p_keycode) { const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { @@ -464,7 +463,7 @@ int keycode_get_count() { } int keycode_get_value_by_index(int p_index) { - return _keycodes[p_index].code; + return (int)_keycodes[p_index].code; } const char *keycode_get_name_by_index(int p_index) { diff --git a/core/os/keyboard.h b/core/os/keyboard.h index 52174432d9..c780099553 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -33,148 +33,142 @@ #include "core/string/ustring.h" -/* - Special Key: - - The strategy here is similar to the one used by toolkits, - which consists in leaving the 24 bits unicode range for printable - characters, and use the upper 8 bits for special keys and - modifiers. This way everything (char/keycode) can fit nicely in one 32 bits unsigned integer. -*/ -enum { - SPKEY = (1 << 24) -}; - -enum Key { - KEY_NONE = 0, +enum class Key { + NONE = 0, + // Special key: The strategy here is similar to the one used by toolkits, + // which consists in leaving the 24 bits unicode range for printable + // characters, and use the upper 8 bits for special keys and modifiers. + // This way everything (char/keycode) can fit nicely in one 32-bit + // integer (the enum's underlying type is `int` by default). + SPECIAL = (1 << 24), /* CURSOR/FUNCTION/BROWSER/MULTIMEDIA/MISC KEYS */ - KEY_ESCAPE = SPKEY | 0x01, - KEY_TAB = SPKEY | 0x02, - KEY_BACKTAB = SPKEY | 0x03, - KEY_BACKSPACE = SPKEY | 0x04, - KEY_ENTER = SPKEY | 0x05, - KEY_KP_ENTER = SPKEY | 0x06, - KEY_INSERT = SPKEY | 0x07, - KEY_DELETE = SPKEY | 0x08, - KEY_PAUSE = SPKEY | 0x09, - KEY_PRINT = SPKEY | 0x0A, - KEY_SYSREQ = SPKEY | 0x0B, - KEY_CLEAR = SPKEY | 0x0C, - KEY_HOME = SPKEY | 0x0D, - KEY_END = SPKEY | 0x0E, - KEY_LEFT = SPKEY | 0x0F, - KEY_UP = SPKEY | 0x10, - KEY_RIGHT = SPKEY | 0x11, - KEY_DOWN = SPKEY | 0x12, - KEY_PAGEUP = SPKEY | 0x13, - KEY_PAGEDOWN = SPKEY | 0x14, - KEY_SHIFT = SPKEY | 0x15, - KEY_CTRL = SPKEY | 0x16, - KEY_META = SPKEY | 0x17, - KEY_ALT = SPKEY | 0x18, - KEY_CAPSLOCK = SPKEY | 0x19, - KEY_NUMLOCK = SPKEY | 0x1A, - KEY_SCROLLLOCK = SPKEY | 0x1B, - KEY_F1 = SPKEY | 0x1C, - KEY_F2 = SPKEY | 0x1D, - KEY_F3 = SPKEY | 0x1E, - KEY_F4 = SPKEY | 0x1F, - KEY_F5 = SPKEY | 0x20, - KEY_F6 = SPKEY | 0x21, - KEY_F7 = SPKEY | 0x22, - KEY_F8 = SPKEY | 0x23, - KEY_F9 = SPKEY | 0x24, - KEY_F10 = SPKEY | 0x25, - KEY_F11 = SPKEY | 0x26, - KEY_F12 = SPKEY | 0x27, - KEY_F13 = SPKEY | 0x28, - KEY_F14 = SPKEY | 0x29, - KEY_F15 = SPKEY | 0x2A, - KEY_F16 = SPKEY | 0x2B, - KEY_KP_MULTIPLY = SPKEY | 0x81, - KEY_KP_DIVIDE = SPKEY | 0x82, - KEY_KP_SUBTRACT = SPKEY | 0x83, - KEY_KP_PERIOD = SPKEY | 0x84, - KEY_KP_ADD = SPKEY | 0x85, - KEY_KP_0 = SPKEY | 0x86, - KEY_KP_1 = SPKEY | 0x87, - KEY_KP_2 = SPKEY | 0x88, - KEY_KP_3 = SPKEY | 0x89, - KEY_KP_4 = SPKEY | 0x8A, - KEY_KP_5 = SPKEY | 0x8B, - KEY_KP_6 = SPKEY | 0x8C, - KEY_KP_7 = SPKEY | 0x8D, - KEY_KP_8 = SPKEY | 0x8E, - KEY_KP_9 = SPKEY | 0x8F, - KEY_SUPER_L = SPKEY | 0x2C, - KEY_SUPER_R = SPKEY | 0x2D, - KEY_MENU = SPKEY | 0x2E, - KEY_HYPER_L = SPKEY | 0x2F, - KEY_HYPER_R = SPKEY | 0x30, - KEY_HELP = SPKEY | 0x31, - KEY_DIRECTION_L = SPKEY | 0x32, - KEY_DIRECTION_R = SPKEY | 0x33, - KEY_BACK = SPKEY | 0x40, - KEY_FORWARD = SPKEY | 0x41, - KEY_STOP = SPKEY | 0x42, - KEY_REFRESH = SPKEY | 0x43, - KEY_VOLUMEDOWN = SPKEY | 0x44, - KEY_VOLUMEMUTE = SPKEY | 0x45, - KEY_VOLUMEUP = SPKEY | 0x46, - KEY_BASSBOOST = SPKEY | 0x47, - KEY_BASSUP = SPKEY | 0x48, - KEY_BASSDOWN = SPKEY | 0x49, - KEY_TREBLEUP = SPKEY | 0x4A, - KEY_TREBLEDOWN = SPKEY | 0x4B, - KEY_MEDIAPLAY = SPKEY | 0x4C, - KEY_MEDIASTOP = SPKEY | 0x4D, - KEY_MEDIAPREVIOUS = SPKEY | 0x4E, - KEY_MEDIANEXT = SPKEY | 0x4F, - KEY_MEDIARECORD = SPKEY | 0x50, - KEY_HOMEPAGE = SPKEY | 0x51, - KEY_FAVORITES = SPKEY | 0x52, - KEY_SEARCH = SPKEY | 0x53, - KEY_STANDBY = SPKEY | 0x54, - KEY_OPENURL = SPKEY | 0x55, - KEY_LAUNCHMAIL = SPKEY | 0x56, - KEY_LAUNCHMEDIA = SPKEY | 0x57, - KEY_LAUNCH0 = SPKEY | 0x58, - KEY_LAUNCH1 = SPKEY | 0x59, - KEY_LAUNCH2 = SPKEY | 0x5A, - KEY_LAUNCH3 = SPKEY | 0x5B, - KEY_LAUNCH4 = SPKEY | 0x5C, - KEY_LAUNCH5 = SPKEY | 0x5D, - KEY_LAUNCH6 = SPKEY | 0x5E, - KEY_LAUNCH7 = SPKEY | 0x5F, - KEY_LAUNCH8 = SPKEY | 0x60, - KEY_LAUNCH9 = SPKEY | 0x61, - KEY_LAUNCHA = SPKEY | 0x62, - KEY_LAUNCHB = SPKEY | 0x63, - KEY_LAUNCHC = SPKEY | 0x64, - KEY_LAUNCHD = SPKEY | 0x65, - KEY_LAUNCHE = SPKEY | 0x66, - KEY_LAUNCHF = SPKEY | 0x67, + ESCAPE = SPECIAL | 0x01, + TAB = SPECIAL | 0x02, + BACKTAB = SPECIAL | 0x03, + BACKSPACE = SPECIAL | 0x04, + ENTER = SPECIAL | 0x05, + KP_ENTER = SPECIAL | 0x06, + INSERT = SPECIAL | 0x07, + KEY_DELETE = SPECIAL | 0x08, // "DELETE" is a reserved word on Windows. + PAUSE = SPECIAL | 0x09, + PRINT = SPECIAL | 0x0A, + SYSREQ = SPECIAL | 0x0B, + CLEAR = SPECIAL | 0x0C, + HOME = SPECIAL | 0x0D, + END = SPECIAL | 0x0E, + LEFT = SPECIAL | 0x0F, + UP = SPECIAL | 0x10, + RIGHT = SPECIAL | 0x11, + DOWN = SPECIAL | 0x12, + PAGEUP = SPECIAL | 0x13, + PAGEDOWN = SPECIAL | 0x14, + SHIFT = SPECIAL | 0x15, + CTRL = SPECIAL | 0x16, + META = SPECIAL | 0x17, + ALT = SPECIAL | 0x18, + CAPSLOCK = SPECIAL | 0x19, + NUMLOCK = SPECIAL | 0x1A, + SCROLLLOCK = SPECIAL | 0x1B, + F1 = SPECIAL | 0x1C, + F2 = SPECIAL | 0x1D, + F3 = SPECIAL | 0x1E, + F4 = SPECIAL | 0x1F, + F5 = SPECIAL | 0x20, + F6 = SPECIAL | 0x21, + F7 = SPECIAL | 0x22, + F8 = SPECIAL | 0x23, + F9 = SPECIAL | 0x24, + F10 = SPECIAL | 0x25, + F11 = SPECIAL | 0x26, + F12 = SPECIAL | 0x27, + F13 = SPECIAL | 0x28, + F14 = SPECIAL | 0x29, + F15 = SPECIAL | 0x2A, + F16 = SPECIAL | 0x2B, + KP_MULTIPLY = SPECIAL | 0x81, + KP_DIVIDE = SPECIAL | 0x82, + KP_SUBTRACT = SPECIAL | 0x83, + KP_PERIOD = SPECIAL | 0x84, + KP_ADD = SPECIAL | 0x85, + KP_0 = SPECIAL | 0x86, + KP_1 = SPECIAL | 0x87, + KP_2 = SPECIAL | 0x88, + KP_3 = SPECIAL | 0x89, + KP_4 = SPECIAL | 0x8A, + KP_5 = SPECIAL | 0x8B, + KP_6 = SPECIAL | 0x8C, + KP_7 = SPECIAL | 0x8D, + KP_8 = SPECIAL | 0x8E, + KP_9 = SPECIAL | 0x8F, + SUPER_L = SPECIAL | 0x2C, + SUPER_R = SPECIAL | 0x2D, + MENU = SPECIAL | 0x2E, + HYPER_L = SPECIAL | 0x2F, + HYPER_R = SPECIAL | 0x30, + HELP = SPECIAL | 0x31, + DIRECTION_L = SPECIAL | 0x32, + DIRECTION_R = SPECIAL | 0x33, + BACK = SPECIAL | 0x40, + FORWARD = SPECIAL | 0x41, + STOP = SPECIAL | 0x42, + REFRESH = SPECIAL | 0x43, + VOLUMEDOWN = SPECIAL | 0x44, + VOLUMEMUTE = SPECIAL | 0x45, + VOLUMEUP = SPECIAL | 0x46, + BASSBOOST = SPECIAL | 0x47, + BASSUP = SPECIAL | 0x48, + BASSDOWN = SPECIAL | 0x49, + TREBLEUP = SPECIAL | 0x4A, + TREBLEDOWN = SPECIAL | 0x4B, + MEDIAPLAY = SPECIAL | 0x4C, + MEDIASTOP = SPECIAL | 0x4D, + MEDIAPREVIOUS = SPECIAL | 0x4E, + MEDIANEXT = SPECIAL | 0x4F, + MEDIARECORD = SPECIAL | 0x50, + HOMEPAGE = SPECIAL | 0x51, + FAVORITES = SPECIAL | 0x52, + SEARCH = SPECIAL | 0x53, + STANDBY = SPECIAL | 0x54, + OPENURL = SPECIAL | 0x55, + LAUNCHMAIL = SPECIAL | 0x56, + LAUNCHMEDIA = SPECIAL | 0x57, + LAUNCH0 = SPECIAL | 0x58, + LAUNCH1 = SPECIAL | 0x59, + LAUNCH2 = SPECIAL | 0x5A, + LAUNCH3 = SPECIAL | 0x5B, + LAUNCH4 = SPECIAL | 0x5C, + LAUNCH5 = SPECIAL | 0x5D, + LAUNCH6 = SPECIAL | 0x5E, + LAUNCH7 = SPECIAL | 0x5F, + LAUNCH8 = SPECIAL | 0x60, + LAUNCH9 = SPECIAL | 0x61, + LAUNCHA = SPECIAL | 0x62, + LAUNCHB = SPECIAL | 0x63, + LAUNCHC = SPECIAL | 0x64, + LAUNCHD = SPECIAL | 0x65, + LAUNCHE = SPECIAL | 0x66, + LAUNCHF = SPECIAL | 0x67, - KEY_UNKNOWN = SPKEY | 0xFFFFFF, + UNKNOWN = SPECIAL | 0xFFFFFF, /* PRINTABLE LATIN 1 CODES */ - KEY_SPACE = 0x0020, - KEY_EXCLAM = 0x0021, - KEY_QUOTEDBL = 0x0022, - KEY_NUMBERSIGN = 0x0023, - KEY_DOLLAR = 0x0024, - KEY_PERCENT = 0x0025, - KEY_AMPERSAND = 0x0026, - KEY_APOSTROPHE = 0x0027, - KEY_PARENLEFT = 0x0028, - KEY_PARENRIGHT = 0x0029, - KEY_ASTERISK = 0x002A, - KEY_PLUS = 0x002B, - KEY_COMMA = 0x002C, - KEY_MINUS = 0x002D, - KEY_PERIOD = 0x002E, - KEY_SLASH = 0x002F, + SPACE = 0x0020, + EXCLAM = 0x0021, + QUOTEDBL = 0x0022, + NUMBERSIGN = 0x0023, + DOLLAR = 0x0024, + PERCENT = 0x0025, + AMPERSAND = 0x0026, + APOSTROPHE = 0x0027, + PARENLEFT = 0x0028, + PARENRIGHT = 0x0029, + ASTERISK = 0x002A, + PLUS = 0x002B, + COMMA = 0x002C, + MINUS = 0x002D, + PERIOD = 0x002E, + SLASH = 0x002F, KEY_0 = 0x0030, KEY_1 = 0x0031, KEY_2 = 0x0032, @@ -185,134 +179,133 @@ enum Key { KEY_7 = 0x0037, KEY_8 = 0x0038, KEY_9 = 0x0039, - KEY_COLON = 0x003A, - KEY_SEMICOLON = 0x003B, - KEY_LESS = 0x003C, - KEY_EQUAL = 0x003D, - KEY_GREATER = 0x003E, - KEY_QUESTION = 0x003F, - KEY_AT = 0x0040, - KEY_A = 0x0041, - KEY_B = 0x0042, - KEY_C = 0x0043, - KEY_D = 0x0044, - KEY_E = 0x0045, - KEY_F = 0x0046, - KEY_G = 0x0047, - KEY_H = 0x0048, - KEY_I = 0x0049, - KEY_J = 0x004A, - KEY_K = 0x004B, - KEY_L = 0x004C, - KEY_M = 0x004D, - KEY_N = 0x004E, - KEY_O = 0x004F, - KEY_P = 0x0050, - KEY_Q = 0x0051, - KEY_R = 0x0052, - KEY_S = 0x0053, - KEY_T = 0x0054, - KEY_U = 0x0055, - KEY_V = 0x0056, - KEY_W = 0x0057, - KEY_X = 0x0058, - KEY_Y = 0x0059, - KEY_Z = 0x005A, - KEY_BRACKETLEFT = 0x005B, - KEY_BACKSLASH = 0x005C, - KEY_BRACKETRIGHT = 0x005D, - KEY_ASCIICIRCUM = 0x005E, - KEY_UNDERSCORE = 0x005F, - KEY_QUOTELEFT = 0x0060, - KEY_BRACELEFT = 0x007B, - KEY_BAR = 0x007C, - KEY_BRACERIGHT = 0x007D, - KEY_ASCIITILDE = 0x007E, - KEY_NOBREAKSPACE = 0x00A0, - KEY_EXCLAMDOWN = 0x00A1, - KEY_CENT = 0x00A2, - KEY_STERLING = 0x00A3, - KEY_CURRENCY = 0x00A4, - KEY_YEN = 0x00A5, - KEY_BROKENBAR = 0x00A6, - KEY_SECTION = 0x00A7, - KEY_DIAERESIS = 0x00A8, - KEY_COPYRIGHT = 0x00A9, - KEY_ORDFEMININE = 0x00AA, - KEY_GUILLEMOTLEFT = 0x00AB, - KEY_NOTSIGN = 0x00AC, - KEY_HYPHEN = 0x00AD, - KEY_REGISTERED = 0x00AE, - KEY_MACRON = 0x00AF, - KEY_DEGREE = 0x00B0, - KEY_PLUSMINUS = 0x00B1, - KEY_TWOSUPERIOR = 0x00B2, - KEY_THREESUPERIOR = 0x00B3, - KEY_ACUTE = 0x00B4, - KEY_MU = 0x00B5, - KEY_PARAGRAPH = 0x00B6, - KEY_PERIODCENTERED = 0x00B7, - KEY_CEDILLA = 0x00B8, - KEY_ONESUPERIOR = 0x00B9, - KEY_MASCULINE = 0x00BA, - KEY_GUILLEMOTRIGHT = 0x00BB, - KEY_ONEQUARTER = 0x00BC, - KEY_ONEHALF = 0x00BD, - KEY_THREEQUARTERS = 0x00BE, - KEY_QUESTIONDOWN = 0x00BF, - KEY_AGRAVE = 0x00C0, - KEY_AACUTE = 0x00C1, - KEY_ACIRCUMFLEX = 0x00C2, - KEY_ATILDE = 0x00C3, - KEY_ADIAERESIS = 0x00C4, - KEY_ARING = 0x00C5, - KEY_AE = 0x00C6, - KEY_CCEDILLA = 0x00C7, - KEY_EGRAVE = 0x00C8, - KEY_EACUTE = 0x00C9, - KEY_ECIRCUMFLEX = 0x00CA, - KEY_EDIAERESIS = 0x00CB, - KEY_IGRAVE = 0x00CC, - KEY_IACUTE = 0x00CD, - KEY_ICIRCUMFLEX = 0x00CE, - KEY_IDIAERESIS = 0x00CF, - KEY_ETH = 0x00D0, - KEY_NTILDE = 0x00D1, - KEY_OGRAVE = 0x00D2, - KEY_OACUTE = 0x00D3, - KEY_OCIRCUMFLEX = 0x00D4, - KEY_OTILDE = 0x00D5, - KEY_ODIAERESIS = 0x00D6, - KEY_MULTIPLY = 0x00D7, - KEY_OOBLIQUE = 0x00D8, - KEY_UGRAVE = 0x00D9, - KEY_UACUTE = 0x00DA, - KEY_UCIRCUMFLEX = 0x00DB, - KEY_UDIAERESIS = 0x00DC, - KEY_YACUTE = 0x00DD, - KEY_THORN = 0x00DE, - KEY_SSHARP = 0x00DF, + COLON = 0x003A, + SEMICOLON = 0x003B, + LESS = 0x003C, + EQUAL = 0x003D, + GREATER = 0x003E, + QUESTION = 0x003F, + AT = 0x0040, + A = 0x0041, + B = 0x0042, + C = 0x0043, + D = 0x0044, + E = 0x0045, + F = 0x0046, + G = 0x0047, + H = 0x0048, + I = 0x0049, + J = 0x004A, + K = 0x004B, + L = 0x004C, + M = 0x004D, + N = 0x004E, + O = 0x004F, + P = 0x0050, + Q = 0x0051, + R = 0x0052, + S = 0x0053, + T = 0x0054, + U = 0x0055, + V = 0x0056, + W = 0x0057, + X = 0x0058, + Y = 0x0059, + Z = 0x005A, + BRACKETLEFT = 0x005B, + BACKSLASH = 0x005C, + BRACKETRIGHT = 0x005D, + ASCIICIRCUM = 0x005E, + UNDERSCORE = 0x005F, + QUOTELEFT = 0x0060, + BRACELEFT = 0x007B, + BAR = 0x007C, + BRACERIGHT = 0x007D, + ASCIITILDE = 0x007E, + NOBREAKSPACE = 0x00A0, + EXCLAMDOWN = 0x00A1, + CENT = 0x00A2, + STERLING = 0x00A3, + CURRENCY = 0x00A4, + YEN = 0x00A5, + BROKENBAR = 0x00A6, + SECTION = 0x00A7, + DIAERESIS = 0x00A8, + COPYRIGHT = 0x00A9, + ORDFEMININE = 0x00AA, + GUILLEMOTLEFT = 0x00AB, + NOTSIGN = 0x00AC, + HYPHEN = 0x00AD, + KEY_REGISTERED = 0x00AE, // "REGISTERED" is a reserved word on Windows. + MACRON = 0x00AF, + DEGREE = 0x00B0, + PLUSMINUS = 0x00B1, + TWOSUPERIOR = 0x00B2, + THREESUPERIOR = 0x00B3, + ACUTE = 0x00B4, + MU = 0x00B5, + PARAGRAPH = 0x00B6, + PERIODCENTERED = 0x00B7, + CEDILLA = 0x00B8, + ONESUPERIOR = 0x00B9, + MASCULINE = 0x00BA, + GUILLEMOTRIGHT = 0x00BB, + ONEQUARTER = 0x00BC, + ONEHALF = 0x00BD, + THREEQUARTERS = 0x00BE, + QUESTIONDOWN = 0x00BF, + AGRAVE = 0x00C0, + AACUTE = 0x00C1, + ACIRCUMFLEX = 0x00C2, + ATILDE = 0x00C3, + ADIAERESIS = 0x00C4, + ARING = 0x00C5, + AE = 0x00C6, + CCEDILLA = 0x00C7, + EGRAVE = 0x00C8, + EACUTE = 0x00C9, + ECIRCUMFLEX = 0x00CA, + EDIAERESIS = 0x00CB, + IGRAVE = 0x00CC, + IACUTE = 0x00CD, + ICIRCUMFLEX = 0x00CE, + IDIAERESIS = 0x00CF, + ETH = 0x00D0, + NTILDE = 0x00D1, + OGRAVE = 0x00D2, + OACUTE = 0x00D3, + OCIRCUMFLEX = 0x00D4, + OTILDE = 0x00D5, + ODIAERESIS = 0x00D6, + MULTIPLY = 0x00D7, + OOBLIQUE = 0x00D8, + UGRAVE = 0x00D9, + UACUTE = 0x00DA, + UCIRCUMFLEX = 0x00DB, + UDIAERESIS = 0x00DC, + YACUTE = 0x00DD, + THORN = 0x00DE, + SSHARP = 0x00DF, - KEY_DIVISION = 0x00F7, - KEY_YDIAERESIS = 0x00FF, + DIVISION = 0x00F7, + YDIAERESIS = 0x00FF, + END_LATIN1 = 0x0100, }; -enum KeyModifierMask { - KEY_CODE_MASK = ((1 << 25) - 1), ///< Apply this mask to any keycode to remove modifiers. - KEY_MODIFIER_MASK = (0xFF << 24), ///< Apply this mask to isolate modifiers. - KEY_MASK_SHIFT = (1 << 25), - KEY_MASK_ALT = (1 << 26), - KEY_MASK_META = (1 << 27), - KEY_MASK_CTRL = (1 << 28), +enum class KeyModifierMask { + CODE_MASK = ((1 << 25) - 1), ///< Apply this mask to any keycode to remove modifiers. + MODIFIER_MASK = (0xFF << 24), ///< Apply this mask to isolate modifiers. + SHIFT = (1 << 25), + ALT = (1 << 26), + META = (1 << 27), + CTRL = (1 << 28), #ifdef APPLE_STYLE_KEYS - KEY_MASK_CMD = KEY_MASK_META, + CMD = META, #else - KEY_MASK_CMD = KEY_MASK_CTRL, + CMD = CTRL, #endif - - KEY_MASK_KPAD = (1 << 29), - KEY_MASK_GROUP_SWITCH = (1 << 30) - // bit 31 can't be used because variant uses regular 32 bits int as datatype + KPAD = (1 << 29), + GROUP_SWITCH = (1 << 30) }; // To avoid having unnecessary operators, only define the ones that are needed. @@ -325,10 +318,26 @@ inline Key &operator-=(Key &a, int b) { return (Key &)((int &)a -= b); } +inline Key operator+(Key a, int b) { + return (Key)((int)a + (int)b); +} + inline Key operator+(Key a, Key b) { + return (Key)((int)a + (int)b); +} + +inline Key operator-(Key a, Key b) { return (Key)((int)a - (int)b); } +inline Key operator&(Key a, Key b) { + return (Key)((int)a & (int)b); +} + +inline Key operator|(Key a, Key b) { + return (Key)((int)a | (int)b); +} + inline Key &operator|=(Key &a, Key b) { return (Key &)((int &)a |= (int)b); } @@ -337,6 +346,10 @@ inline Key &operator|=(Key &a, KeyModifierMask b) { return (Key &)((int &)a |= (int)b); } +inline Key &operator&=(Key &a, KeyModifierMask b) { + return (Key &)((int &)a &= (int)b); +} + inline Key operator|(Key a, KeyModifierMask b) { return (Key)((int)a | (int)b); } @@ -361,10 +374,10 @@ inline KeyModifierMask operator|(KeyModifierMask a, KeyModifierMask b) { return (KeyModifierMask)((int)a | (int)b); } -String keycode_get_string(uint32_t p_code); -bool keycode_has_unicode(uint32_t p_keycode); -int find_keycode(const String &p_code); -const char *find_keycode_name(int p_keycode); +String keycode_get_string(Key p_code); +bool keycode_has_unicode(Key p_keycode); +Key find_keycode(const String &p_code); +const char *find_keycode_name(Key p_keycode); int keycode_get_count(); int keycode_get_value_by_index(int p_index); const char *keycode_get_name_by_index(int p_index); diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp index ee87346dfc..ee33eef83f 100644 --- a/core/os/midi_driver.cpp +++ b/core/os/midi_driver.cpp @@ -68,46 +68,46 @@ void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_ } switch (event->get_message()) { - case MIDI_MESSAGE_AFTERTOUCH: + case MIDIMessage::AFTERTOUCH: if (length >= 2 + param_position) { event->set_pitch(data[param_position]); event->set_pressure(data[param_position + 1]); } break; - case MIDI_MESSAGE_CONTROL_CHANGE: + case MIDIMessage::CONTROL_CHANGE: if (length >= 2 + param_position) { event->set_controller_number(data[param_position]); event->set_controller_value(data[param_position + 1]); } break; - case MIDI_MESSAGE_NOTE_ON: - case MIDI_MESSAGE_NOTE_OFF: + case MIDIMessage::NOTE_ON: + case MIDIMessage::NOTE_OFF: if (length >= 2 + param_position) { event->set_pitch(data[param_position]); event->set_velocity(data[param_position + 1]); - if (event->get_message() == MIDI_MESSAGE_NOTE_ON && event->get_velocity() == 0) { + if (event->get_message() == MIDIMessage::NOTE_ON && event->get_velocity() == 0) { // https://www.midi.org/forum/228-writing-midi-software-send-note-off,-or-zero-velocity-note-on - event->set_message(MIDI_MESSAGE_NOTE_OFF); + event->set_message(MIDIMessage::NOTE_OFF); } } break; - case MIDI_MESSAGE_PITCH_BEND: + case MIDIMessage::PITCH_BEND: if (length >= 2 + param_position) { event->set_pitch((data[param_position + 1] << 7) | data[param_position]); } break; - case MIDI_MESSAGE_PROGRAM_CHANGE: + case MIDIMessage::PROGRAM_CHANGE: if (length >= 1 + param_position) { event->set_instrument(data[param_position]); } break; - case MIDI_MESSAGE_CHANNEL_PRESSURE: + case MIDIMessage::CHANNEL_PRESSURE: if (length >= 1 + param_position) { event->set_pressure(data[param_position]); } diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 8d6da31cf3..70236231a2 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -38,6 +38,7 @@ #include "core/string/translation.h" #include "core/string/ucaps.h" #include "core/variant/variant.h" +#include "core/version_generated.gen.h" #include <stdio.h> #include <stdlib.h> @@ -952,10 +953,6 @@ const char32_t *String::get_data() const { return size() ? &operator[](0) : &zero; } -void String::erase(int p_pos, int p_chars) { - *this = left(MAX(p_pos, 0)) + substr(p_pos + p_chars, length() - ((p_pos + p_chars))); -} - String String::capitalize() const { String aux = this->camelcase_to_underscore(true).replace("_", " ").strip_edges(); String cap; @@ -4420,7 +4417,7 @@ String String::property_name_encode() const { // as well as '"', '=' or ' ' (32) const char32_t *cstr = get_data(); for (int i = 0; cstr[i]; i++) { - if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] < 33 || cstr[i] > 126) { + if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] == ';' || cstr[i] == '[' || cstr[i] == ']' || cstr[i] < 33 || cstr[i] > 126) { return "\"" + c_escape_multiline() + "\""; } } @@ -4872,15 +4869,20 @@ String TTRN(const String &p_text, const String &p_text_plural, int p_n, const St return p_text_plural; } +/* DTR and DTRN are used for the documentation, handling descriptions extracted + * from the XML. + * They also replace `$DOCS_URL` with the actual URL to the documentation's branch, + * to allow dehardcoding it in the XML and doing proper substitutions everywhere. + */ String DTR(const String &p_text, const String &p_context) { // Comes straight from the XML, so remove indentation and any trailing whitespace. const String text = p_text.dedent().strip_edges(); if (TranslationServer::get_singleton()) { - return TranslationServer::get_singleton()->doc_translate(text, p_context); + return String(TranslationServer::get_singleton()->doc_translate(text, p_context)).replace("$DOCS_URL", VERSION_DOCS_URL); } - return text; + return text.replace("$DOCS_URL", VERSION_DOCS_URL); } String DTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) { @@ -4888,14 +4890,14 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St const String text_plural = p_text_plural.dedent().strip_edges(); if (TranslationServer::get_singleton()) { - return TranslationServer::get_singleton()->doc_translate_plural(text, text_plural, p_n, p_context); + return String(TranslationServer::get_singleton()->doc_translate_plural(text, text_plural, p_n, p_context)).replace("$DOCS_URL", VERSION_DOCS_URL); } // Return message based on English plural rule if translation is not possible. if (p_n == 1) { - return text; + return text.replace("$DOCS_URL", VERSION_DOCS_URL); } - return text_plural; + return text_plural.replace("$DOCS_URL", VERSION_DOCS_URL); } #endif diff --git a/core/typedefs.h b/core/typedefs.h index 9ab874b2f0..95bd423817 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -91,8 +91,8 @@ #define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v)) #endif -#ifndef SGN -#define SGN(m_v) (((m_v) == 0) ? (0.0) : (((m_v) < 0) ? (-1.0) : (+1.0))) +#ifndef SIGN +#define SIGN(m_v) (((m_v) == 0) ? (0.0) : (((m_v) < 0) ? (-1.0) : (+1.0))) #endif #ifndef MIN diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index f06d767cf5..98be62391f 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -80,7 +80,7 @@ struct VariantCaster<const T &> { } \ typedef int64_t EncodeT; \ _FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \ - *(int64_t *)p_ptr = p_val; \ + *(int64_t *)p_ptr = (int64_t)p_val; \ } \ }; diff --git a/core/variant/variant.h b/core/variant/variant.h index 8ce5e7dcd2..230ed33c0c 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -31,6 +31,7 @@ #ifndef VARIANT_H #define VARIANT_H +#include "core/input/input_enums.h" #include "core/io/ip_address.h" #include "core/math/aabb.h" #include "core/math/basis.h" @@ -43,6 +44,7 @@ #include "core/math/vector3.h" #include "core/math/vector3i.h" #include "core/object/object_id.h" +#include "core/os/keyboard.h" #include "core/string/node_path.h" #include "core/string/ustring.h" #include "core/templates/rid.h" @@ -430,6 +432,21 @@ public: Variant(const IPAddress &p_address); +#define VARIANT_ENUM_CLASS_CONSTRUCTOR(m_enum) \ + Variant(const m_enum &p_value) { \ + type = INT; \ + _data._int = (int64_t)p_value; \ + } + + // Only enum classes that need to be bound need this to be defined. + VARIANT_ENUM_CLASS_CONSTRUCTOR(JoyAxis) + VARIANT_ENUM_CLASS_CONSTRUCTOR(JoyButton) + VARIANT_ENUM_CLASS_CONSTRUCTOR(Key) + VARIANT_ENUM_CLASS_CONSTRUCTOR(MIDIMessage) + VARIANT_ENUM_CLASS_CONSTRUCTOR(MouseButton) + +#undef VARIANT_ENUM_CLASS_CONSTRUCTOR + // If this changes the table in variant_op must be updated enum Operator { //comparison diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index c3fe443456..65ea969146 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1412,8 +1412,6 @@ static void _register_variant_builtin_methods() { bind_method(String, plus_file, sarray("file"), varray()); bind_method(String, unicode_at, sarray("at"), varray()); bind_method(String, dedent, sarray(), varray()); - // FIXME: String needs to be immutable when binding - //bind_method(String, erase, sarray("position", "chars"), varray()); bind_method(String, hash, sarray(), varray()); bind_method(String, md5_text, sarray(), varray()); bind_method(String, sha1_text, sarray(), varray()); @@ -1422,8 +1420,6 @@ static void _register_variant_builtin_methods() { bind_method(String, sha1_buffer, sarray(), varray()); bind_method(String, sha256_buffer, sarray(), varray()); bind_method(String, is_empty, sarray(), varray()); - // FIXME: Static function, not sure how to bind - //bind_method(String, humanize_size, sarray("size"), varray()); bind_method(String, is_absolute_path, sarray(), varray()); bind_method(String, is_relative_path, sarray(), varray()); @@ -1635,17 +1631,15 @@ static void _register_variant_builtin_methods() { bind_method(Color, to_argb64, sarray(), varray()); bind_method(Color, to_abgr64, sarray(), varray()); bind_method(Color, to_rgba64, sarray(), varray()); + bind_method(Color, to_html, sarray("with_alpha"), varray(true)); bind_method(Color, clamp, sarray("min", "max"), varray(Color(0, 0, 0, 0), Color(1, 1, 1, 1))); bind_method(Color, inverted, sarray(), varray()); bind_method(Color, lerp, sarray("to", "weight"), varray()); bind_method(Color, lightened, sarray("amount"), varray()); bind_method(Color, darkened, sarray("amount"), varray()); - bind_method(Color, to_html, sarray("with_alpha"), varray(true)); bind_method(Color, blend, sarray("over"), varray()); - // FIXME: Color is immutable, need to probably find a way to do this via constructor - //ADDFUNC4R(COLOR, COLOR, Color, from_hsv, FLOAT, "h", FLOAT, "s", FLOAT, "v", FLOAT, "a", varray(1.0)); bind_method(Color, is_equal_approx, sarray("to"), varray()); bind_static_method(Color, hex, sarray("hex"), varray()); @@ -1657,6 +1651,7 @@ static void _register_variant_builtin_methods() { bind_static_method(Color, get_named_color_name, sarray("idx"), varray()); bind_static_method(Color, get_named_color, sarray("idx"), varray()); bind_static_method(Color, from_string, sarray("str", "default"), varray()); + bind_static_method(Color, from_hsv, sarray("h", "s", "v", "alpha"), varray(1.0)); bind_static_method(Color, from_rgbe9995, sarray("rgbe"), varray()); /* RID */ diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 666b582e39..554b2f1c25 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -151,10 +151,10 @@ struct VariantUtilityFunctions { r_error.error = Callable::CallError::CALL_OK; switch (x.get_type()) { case Variant::INT: { - return SGN(VariantInternalAccessor<int64_t>::get(&x)); + return SIGN(VariantInternalAccessor<int64_t>::get(&x)); } break; case Variant::FLOAT: { - return SGN(VariantInternalAccessor<double>::get(&x)); + return SIGN(VariantInternalAccessor<double>::get(&x)); } break; case Variant::VECTOR2: { return VariantInternalAccessor<Vector2>::get(&x).sign(); @@ -176,11 +176,11 @@ struct VariantUtilityFunctions { } static inline double signf(double x) { - return SGN(x); + return SIGN(x); } static inline int64_t signi(int64_t x) { - return SGN(x); + return SIGN(x); } static inline double pow(double x, double y) { @@ -275,6 +275,10 @@ struct VariantUtilityFunctions { return Math::wrapf(value, min, max); } + static inline double pingpong(double value, double length) { + return Math::pingpong(value, length); + } + static inline Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; @@ -399,6 +403,10 @@ struct VariantUtilityFunctions { return Math::randf(); } + static inline double randfn(double mean, double deviation) { + return Math::randfn(mean, deviation); + } + static inline int64_t randi_range(int64_t from, int64_t to) { return Math::random((int32_t)from, (int32_t)to); } @@ -1226,6 +1234,7 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(clampf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(nearest_po2, sarray("value"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(pingpong, sarray("value", "length"), Variant::UTILITY_FUNC_TYPE_MATH); // Random @@ -1234,6 +1243,7 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(randf, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM); FUNCBINDR(randi_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM); FUNCBINDR(randf_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM); + FUNCBINDR(randfn, sarray("mean", "deviation"), Variant::UTILITY_FUNC_TYPE_RANDOM); FUNCBIND(seed, sarray("base"), Variant::UTILITY_FUNC_TYPE_RANDOM); FUNCBINDR(rand_from_seed, sarray("seed"), Variant::UTILITY_FUNC_TYPE_RANDOM); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index ea49b6b634..9cfe494b7f 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -566,6 +566,26 @@ [b]Warning:[/b] Due to the way it is implemented, this function returns [code]0[/code] rather than [code]1[/code] for non-positive values of [code]value[/code] (in reality, 1 is the smallest integer power of 2). </description> </method> + <method name="pingpong"> + <return type="float" /> + <argument index="0" name="value" type="float" /> + <argument index="1" name="length" type="float" /> + <description> + Returns the [code]value[/code] wrapped between [code]0[/code] and the [code]length[/code]. If the limit is reached, the next value the function returned is decreased to the [code]0[/code] side or increased to the [code]length[/code] side (like a triangle wave). If [code]length[/code] is less than zero, it becomes positive. + [codeblock] + pingpong(-3.0, 3.0) # Returns 3 + pingpong(-2.0, 3.0) # Returns 2 + pingpong(-1.0, 3.0) # Returns 1 + pingpong(0.0, 3.0) # Returns 0 + pingpong(1.0, 3.0) # Returns 1 + pingpong(2.0, 3.0) # Returns 2 + pingpong(3.0, 3.0) # Returns 3 + pingpong(4.0, 3.0) # Returns 2 + pingpong(5.0, 3.0) # Returns 1 + pingpong(6.0, 3.0) # Returns 0 + [/codeblock] + </description> + </method> <method name="posmod"> <return type="int" /> <argument index="0" name="x" type="int" /> @@ -703,6 +723,14 @@ [/codeblock] </description> </method> + <method name="randfn"> + <return type="float" /> + <argument index="0" name="mean" type="float" /> + <argument index="1" name="deviation" type="float" /> + <description> + Returns a normally-distributed pseudo-random floating point value using Box-Muller transform with the specified [code]mean[/code] and a standard [code]deviation[/code]. This is also called Gaussian distribution. + </description> + </method> <method name="randi"> <return type="int" /> <description> @@ -1231,7 +1259,7 @@ <constant name="INLINE_ALIGN_BOTTOM" value="14" enum="InlineAlign"> Aligns bottom of the inline object (e.g. image, table) to the bottom of the text. Equvalent to [code]INLINE_ALIGN_BOTTOM_TO | INLINE_ALIGN_TO_BOTTOM[/code]. </constant> - <constant name="SPKEY" value="16777216"> + <constant name="KEY_SPECIAL" value="16777216" enum="Key"> Keycodes with this bit applied are non-printable. </constant> <constant name="KEY_ESCAPE" value="16777217" enum="Key"> @@ -1996,12 +2024,6 @@ <constant name="MOUSE_BUTTON_MIDDLE" value="3" enum="MouseButton"> Middle mouse button. </constant> - <constant name="MOUSE_BUTTON_XBUTTON1" value="8" enum="MouseButton"> - Extra mouse button 1 (only present on some mice). - </constant> - <constant name="MOUSE_BUTTON_XBUTTON2" value="9" enum="MouseButton"> - Extra mouse button 2 (only present on some mice). - </constant> <constant name="MOUSE_BUTTON_WHEEL_UP" value="4" enum="MouseButton"> Mouse wheel up. </constant> @@ -2014,6 +2036,12 @@ <constant name="MOUSE_BUTTON_WHEEL_RIGHT" value="7" enum="MouseButton"> Mouse wheel right button (only present on some mice). </constant> + <constant name="MOUSE_BUTTON_XBUTTON1" value="8" enum="MouseButton"> + Extra mouse button 1 (only present on some mice). + </constant> + <constant name="MOUSE_BUTTON_XBUTTON2" value="9" enum="MouseButton"> + Extra mouse button 2 (only present on some mice). + </constant> <constant name="MOUSE_BUTTON_MASK_LEFT" value="1" enum="MouseButton"> Left mouse button mask. </constant> diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index f353cd19b8..170cfea6f9 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -9,9 +9,9 @@ [b]Note:[/b] Unlike [Rect2], [AABB] does not have a variant that uses integer coordinates. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Vector math">https://docs.godotengine.org/en/latest/tutorials/math/vector_math.html</link> - <link title="Advanced vector math">https://docs.godotengine.org/en/latest/tutorials/math/vectors_advanced.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Vector math">$DOCS_URL/tutorials/math/vector_math.html</link> + <link title="Advanced vector math">$DOCS_URL/tutorials/math/vectors_advanced.html</link> </tutorials> <constructors> <constructor name="AABB"> @@ -54,7 +54,22 @@ <return type="AABB" /> <argument index="0" name="to_point" type="Vector3" /> <description> - Returns this [AABB] expanded to include a given point. + Returns a copy of this [AABB] expanded to include a given point. + [b]Example:[/b] + [codeblocks] + [gdscript] + # position (-3, 2, 0), size (1, 1, 1) + var box = AABB(Vector3(-3, 2, 0), Vector3(1, 1, 1)) + # position (-3, -1, 0), size (3, 4, 2), so we fit both the original AABB and Vector3(0, -1, 2) + var box2 = box.expand(Vector3(0, -1, 2)) + [/gdscript] + [csharp] + // position (-3, 2, 0), size (1, 1, 1) + var box = new AABB(new Vector3(-3, 2, 0), new Vector3(1, 1, 1)); + // position (-3, -1, 0), size (3, 4, 2), so we fit both the original AABB and Vector3(0, -1, 2) + var box2 = box.Expand(new Vector3(0, -1, 2)); + [/csharp] + [/codeblocks] </description> </method> <method name="get_center" qualifiers="const"> @@ -218,12 +233,15 @@ <return type="bool" /> <argument index="0" name="right" type="AABB" /> <description> + Returns [code]true[/code] if the vectors are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="AABB" /> <argument index="0" name="right" type="Transform3D" /> <description> + Inversely transforms (multiplies) the [AABB] by the given [Transform3D] transformation matrix. </description> </operator> <operator name="operator =="> @@ -235,6 +253,8 @@ <return type="bool" /> <argument index="0" name="right" type="AABB" /> <description> + Returns [code]true[/code] if the AABBs are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> </operators> diff --git a/doc/classes/AnimatedSprite2D.xml b/doc/classes/AnimatedSprite2D.xml index b468e1d109..789c6bd960 100644 --- a/doc/classes/AnimatedSprite2D.xml +++ b/doc/classes/AnimatedSprite2D.xml @@ -8,7 +8,7 @@ [b]Note:[/b] You can associate a set of normal or specular maps by creating additional [SpriteFrames] resources with a [code]_normal[/code] or [code]_specular[/code] suffix. For example, having 3 [SpriteFrames] resources [code]run[/code], [code]run_normal[/code], and [code]run_specular[/code] will make it so the [code]run[/code] animation uses normal and specular maps. </description> <tutorials> - <link title="2D Sprite animation">https://docs.godotengine.org/en/latest/tutorials/2d/2d_sprite_animation.html</link> + <link title="2D Sprite animation">$DOCS_URL/tutorials/2d/2d_sprite_animation.html</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> </tutorials> <methods> diff --git a/doc/classes/AnimatedSprite3D.xml b/doc/classes/AnimatedSprite3D.xml index 59d7553ef4..38a87c1b2b 100644 --- a/doc/classes/AnimatedSprite3D.xml +++ b/doc/classes/AnimatedSprite3D.xml @@ -7,7 +7,7 @@ Animations are created using a [SpriteFrames] resource, which can be configured in the editor via the SpriteFrames panel. </description> <tutorials> - <link title="2D Sprite animation (also applies to 3D)">https://docs.godotengine.org/en/latest/tutorials/2d/2d_sprite_animation.html</link> + <link title="2D Sprite animation (also applies to 3D)">$DOCS_URL/tutorials/2d/2d_sprite_animation.html</link> </tutorials> <methods> <method name="is_playing" qualifiers="const"> diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index e3bb60f6de..bb4089d67e 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -28,7 +28,7 @@ Animations are just data containers, and must be added to nodes such as an [AnimationPlayer] to be played back. Animation tracks have different types, each with its own set of dedicated methods. Check [enum TrackType] to see available types. </description> <tutorials> - <link title="Animation documentation index">https://docs.godotengine.org/en/latest/tutorials/animation/index.html</link> + <link title="Animation documentation index">$DOCS_URL/tutorials/animation/index.html</link> </tutorials> <methods> <method name="add_track"> @@ -130,6 +130,14 @@ Sets the stream of the key identified by [code]key_idx[/code] to value [code]stream[/code]. The [code]track_idx[/code] must be the index of an Audio Track. </description> </method> + <method name="bezier_track_get_key_handle_mode" qualifiers="const"> + <return type="int" /> + <argument index="0" name="track_idx" type="int" /> + <argument index="1" name="key_idx" type="int" /> + <description> + Returns the handle mode of the key identified by [code]index[/code]. See [enum HandleMode] for possible values. The [code]track_idx[/code] must be the index of a Bezier Track. + </description> + </method> <method name="bezier_track_get_key_in_handle" qualifiers="const"> <return type="Vector2" /> <argument index="0" name="track_idx" type="int" /> @@ -161,6 +169,7 @@ <argument index="2" name="value" type="float" /> <argument index="3" name="in_handle" type="Vector2" default="Vector2(0, 0)" /> <argument index="4" name="out_handle" type="Vector2" default="Vector2(0, 0)" /> + <argument index="5" name="handle_mode" type="int" enum="Animation.HandleMode" default="1" /> <description> Inserts a Bezier Track key at the given [code]time[/code] in seconds. The [code]track_idx[/code] must be the index of a Bezier Track. [code]in_handle[/code] is the left-side weight of the added Bezier curve point, [code]out_handle[/code] is the right-side one, while [code]value[/code] is the actual value at this point. @@ -174,11 +183,22 @@ Returns the interpolated value at the given [code]time[/code] (in seconds). The [code]track_idx[/code] must be the index of a Bezier Track. </description> </method> + <method name="bezier_track_set_key_handle_mode"> + <return type="void" /> + <argument index="0" name="track_idx" type="int" /> + <argument index="1" name="key_idx" type="int" /> + <argument index="2" name="key_handle_mode" type="int" enum="Animation.HandleMode" /> + <argument index="3" name="balanced_value_time_ratio" type="float" default="1.0" /> + <description> + Changes the handle mode of the keyframe at the given [code]index[/code]. See [enum HandleMode] for possible values. The [code]track_idx[/code] must be the index of a Bezier Track. + </description> + </method> <method name="bezier_track_set_key_in_handle"> <return type="void" /> <argument index="0" name="track_idx" type="int" /> <argument index="1" name="key_idx" type="int" /> <argument index="2" name="in_handle" type="Vector2" /> + <argument index="3" name="balanced_value_time_ratio" type="float" default="1.0" /> <description> Sets the in handle of the key identified by [code]key_idx[/code] to value [code]in_handle[/code]. The [code]track_idx[/code] must be the index of a Bezier Track. </description> @@ -188,6 +208,7 @@ <argument index="0" name="track_idx" type="int" /> <argument index="1" name="key_idx" type="int" /> <argument index="2" name="out_handle" type="Vector2" /> + <argument index="3" name="balanced_value_time_ratio" type="float" default="1.0" /> <description> Sets the out handle of the key identified by [code]key_idx[/code] to value [code]out_handle[/code]. The [code]track_idx[/code] must be the index of a Bezier Track. </description> @@ -551,8 +572,8 @@ The total length of the animation (in seconds). [b]Note:[/b] Length is not delimited by the last key, as this one may be before or after the end to ensure correct interpolation and looping. </member> - <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false"> - A flag indicating that the animation must loop. This is used for correct interpolation of animation cycles, and for hinting the player that it must restart the animation. + <member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="Animation.LoopMode" default="0"> + Determines the behavior of both ends of the animation timeline during animation playback. This is used for correct interpolation of animation cycles, and for hinting the player that it must restart the animation. </member> <member name="step" type="float" setter="set_step" getter="get_step" default="0.1"> The animation step value. @@ -610,5 +631,20 @@ <constant name="UPDATE_CAPTURE" value="3" enum="UpdateMode"> Same as linear interpolation, but also interpolates from the current value (i.e. dynamically at runtime) if the first key isn't at 0 seconds. </constant> + <constant name="LOOP_NONE" value="0" enum="LoopMode"> + At both ends of the animation, the animation will stop playing. + </constant> + <constant name="LOOP_LINEAR" value="1" enum="LoopMode"> + At both ends of the animation, the animation will be repeated without changing the playback direction. + </constant> + <constant name="LOOP_PINGPONG" value="2" enum="LoopMode"> + Repeats playback and reverse playback at both ends of the animation. + </constant> + <constant name="HANDLE_MODE_FREE" value="0" enum="HandleMode"> + Assigning the free handle mode to a Bezier Track's keyframe allows you to edit the keyframe's left and right handles independently from one another. + </constant> + <constant name="HANDLE_MODE_BALANCED" value="1" enum="HandleMode"> + Assigning the balanced handle mode to a Bezier Track's keyframe makes it so the two handles of the keyframe always stay aligned when changing either the keyframe's left or right handle. + </constant> </constants> </class> diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml index 173ff43d2a..c9d8ae9936 100644 --- a/doc/classes/AnimationNode.xml +++ b/doc/classes/AnimationNode.xml @@ -8,7 +8,7 @@ Inherit this when creating nodes mainly for use in [AnimationNodeBlendTree], otherwise [AnimationRootNode] should be used instead. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> <methods> <method name="_get_caption" qualifiers="virtual const"> @@ -73,6 +73,7 @@ <argument index="2" name="delta" type="float" /> <argument index="3" name="seeked" type="bool" /> <argument index="4" name="blend" type="float" /> + <argument index="5" name="pingponged" type="int" default="0" /> <description> Blend an animation by [code]blend[/code] amount (name must be valid in the linked [AnimationPlayer]). A [code]time[/code] and [code]delta[/code] may be passed, as well as whether [code]seek[/code] happened. </description> diff --git a/doc/classes/AnimationNodeAdd2.xml b/doc/classes/AnimationNodeAdd2.xml index 20ee33209b..472f98a5b3 100644 --- a/doc/classes/AnimationNodeAdd2.xml +++ b/doc/classes/AnimationNodeAdd2.xml @@ -7,7 +7,7 @@ A resource to add to an [AnimationNodeBlendTree]. Blends two animations additively based on an amount value in the [code][0.0, 1.0][/code] range. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> <members> <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> diff --git a/doc/classes/AnimationNodeAdd3.xml b/doc/classes/AnimationNodeAdd3.xml index 26738499bb..9ba4023b79 100644 --- a/doc/classes/AnimationNodeAdd3.xml +++ b/doc/classes/AnimationNodeAdd3.xml @@ -11,7 +11,7 @@ - A +add animation to blend with when the blend amount is in the [code][0.0, 1.0][/code] range </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <members> diff --git a/doc/classes/AnimationNodeAnimation.xml b/doc/classes/AnimationNodeAnimation.xml index 668a35226f..3df92ad3d3 100644 --- a/doc/classes/AnimationNodeAnimation.xml +++ b/doc/classes/AnimationNodeAnimation.xml @@ -7,7 +7,7 @@ A resource to add to an [AnimationNodeBlendTree]. Only features one output set using the [member animation] property. Use it as an input for [AnimationNode] that blend animations together. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> @@ -15,5 +15,14 @@ <member name="animation" type="StringName" setter="set_animation" getter="get_animation" default="&"""> Animation to use as an output. It is one of the animations provided by [member AnimationTree.anim_player]. </member> + <member name="play_mode" type="int" setter="set_play_mode" getter="get_play_mode" enum="AnimationNodeAnimation.PlayMode" default="0"> + Determines the playback direction of the animation. + </member> </members> + <constants> + <constant name="PLAY_MODE_FORWARD" value="0" enum="PlayMode"> + </constant> + <constant name="PLAY_MODE_BACKWARD" value="1" enum="PlayMode"> + </constant> + </constants> </class> diff --git a/doc/classes/AnimationNodeBlend2.xml b/doc/classes/AnimationNodeBlend2.xml index 1f7a4c91c8..3b869bc299 100644 --- a/doc/classes/AnimationNodeBlend2.xml +++ b/doc/classes/AnimationNodeBlend2.xml @@ -7,7 +7,7 @@ A resource to add to an [AnimationNodeBlendTree]. Blends two animations linearly based on an amount value in the [code][0.0, 1.0][/code] range. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> diff --git a/doc/classes/AnimationNodeBlend3.xml b/doc/classes/AnimationNodeBlend3.xml index ed827e2535..ae8fce51f2 100644 --- a/doc/classes/AnimationNodeBlend3.xml +++ b/doc/classes/AnimationNodeBlend3.xml @@ -11,7 +11,7 @@ - A +blend animation to blend with when the blend amount is in the [code][0.0, 1.0][/code] range </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> <members> <member name="sync" type="bool" setter="set_use_sync" getter="is_using_sync" default="false"> diff --git a/doc/classes/AnimationNodeBlendSpace1D.xml b/doc/classes/AnimationNodeBlendSpace1D.xml index 6e55a79fd2..831542b64c 100644 --- a/doc/classes/AnimationNodeBlendSpace1D.xml +++ b/doc/classes/AnimationNodeBlendSpace1D.xml @@ -10,7 +10,7 @@ You can set the extents of the axis using the [member min_space] and [member max_space]. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> <methods> <method name="add_blend_point"> diff --git a/doc/classes/AnimationNodeBlendSpace2D.xml b/doc/classes/AnimationNodeBlendSpace2D.xml index 8d51f9aecc..77d1d872e5 100644 --- a/doc/classes/AnimationNodeBlendSpace2D.xml +++ b/doc/classes/AnimationNodeBlendSpace2D.xml @@ -9,7 +9,7 @@ You can add vertices to the blend space with [method add_blend_point] and automatically triangulate it by setting [member auto_triangles] to [code]true[/code]. Otherwise, use [method add_triangle] and [method remove_triangle] to create up the blend space by hand. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <methods> diff --git a/doc/classes/AnimationNodeBlendTree.xml b/doc/classes/AnimationNodeBlendTree.xml index da532dc059..a9f1f7acaa 100644 --- a/doc/classes/AnimationNodeBlendTree.xml +++ b/doc/classes/AnimationNodeBlendTree.xml @@ -7,7 +7,7 @@ This node may contain a sub-tree of any other blend type nodes, such as mix, blend2, blend3, one shot, etc. This is one of the most commonly used roots. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> <methods> <method name="add_node"> diff --git a/doc/classes/AnimationNodeOneShot.xml b/doc/classes/AnimationNodeOneShot.xml index 2ecc0ae07b..116b54e39e 100644 --- a/doc/classes/AnimationNodeOneShot.xml +++ b/doc/classes/AnimationNodeOneShot.xml @@ -7,7 +7,7 @@ A resource to add to an [AnimationNodeBlendTree]. This node will execute a sub-animation and return once it finishes. Blend times for fading in and out can be customized, as well as filters. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <methods> diff --git a/doc/classes/AnimationNodeOutput.xml b/doc/classes/AnimationNodeOutput.xml index 34c96d13ea..6241a0fa49 100644 --- a/doc/classes/AnimationNodeOutput.xml +++ b/doc/classes/AnimationNodeOutput.xml @@ -6,7 +6,7 @@ <description> </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> diff --git a/doc/classes/AnimationNodeStateMachine.xml b/doc/classes/AnimationNodeStateMachine.xml index 17ef565b3a..5adea7308d 100644 --- a/doc/classes/AnimationNodeStateMachine.xml +++ b/doc/classes/AnimationNodeStateMachine.xml @@ -18,7 +18,7 @@ [/codeblocks] </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> <methods> <method name="add_node"> diff --git a/doc/classes/AnimationNodeStateMachinePlayback.xml b/doc/classes/AnimationNodeStateMachinePlayback.xml index 15c6c96302..b299f8654a 100644 --- a/doc/classes/AnimationNodeStateMachinePlayback.xml +++ b/doc/classes/AnimationNodeStateMachinePlayback.xml @@ -18,7 +18,7 @@ [/codeblocks] </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> <methods> <method name="get_current_length" qualifiers="const"> diff --git a/doc/classes/AnimationNodeStateMachineTransition.xml b/doc/classes/AnimationNodeStateMachineTransition.xml index 763bba6e93..948e3506a9 100644 --- a/doc/classes/AnimationNodeStateMachineTransition.xml +++ b/doc/classes/AnimationNodeStateMachineTransition.xml @@ -5,11 +5,11 @@ <description> </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> <members> <member name="advance_condition" type="StringName" setter="set_advance_condition" getter="get_advance_condition" default="&"""> - Turn on auto advance when this condition is set. The provided name will become a boolean parameter on the [AnimationTree] that can be controlled from code (see [url=https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html#controlling-from-code][/url]). For example, if [member AnimationTree.tree_root] is an [AnimationNodeStateMachine] and [member advance_condition] is set to [code]"idle"[/code]: + Turn on auto advance when this condition is set. The provided name will become a boolean parameter on the [AnimationTree] that can be controlled from code (see [url=$DOCS_URL/tutorials/animation/animation_tree.html#controlling-from-code][/url]). For example, if [member AnimationTree.tree_root] is an [AnimationNodeStateMachine] and [member advance_condition] is set to [code]"idle"[/code]: [codeblocks] [gdscript] $animation_tree.set("parameters/conditions/idle", is_on_floor and (linear_velocity.x == 0)) diff --git a/doc/classes/AnimationNodeTimeScale.xml b/doc/classes/AnimationNodeTimeScale.xml index 5b40b39bca..33e0127a52 100644 --- a/doc/classes/AnimationNodeTimeScale.xml +++ b/doc/classes/AnimationNodeTimeScale.xml @@ -7,7 +7,7 @@ Allows scaling the speed of the animation (or reversing it) in any children nodes. Setting it to 0 will pause the animation. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> </tutorials> </class> diff --git a/doc/classes/AnimationNodeTimeSeek.xml b/doc/classes/AnimationNodeTimeSeek.xml index d927c663c8..868319272e 100644 --- a/doc/classes/AnimationNodeTimeSeek.xml +++ b/doc/classes/AnimationNodeTimeSeek.xml @@ -27,6 +27,6 @@ [/codeblocks] </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> </tutorials> </class> diff --git a/doc/classes/AnimationNodeTransition.xml b/doc/classes/AnimationNodeTransition.xml index b297832ac0..48961f51a5 100644 --- a/doc/classes/AnimationNodeTransition.xml +++ b/doc/classes/AnimationNodeTransition.xml @@ -7,7 +7,7 @@ Simple state machine for cases which don't require a more advanced [AnimationNodeStateMachine]. Animations can be connected to the inputs and transition times can be specified. </description> <tutorials> - <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index 2fd923df85..9f68edbc92 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -9,8 +9,8 @@ Updating the target properties of animations occurs at process time. </description> <tutorials> - <link title="2D Sprite animation">https://docs.godotengine.org/en/latest/tutorials/2d/2d_sprite_animation.html</link> - <link title="Animation documentation index">https://docs.godotengine.org/en/latest/tutorials/animation/index.html</link> + <link title="2D Sprite animation">$DOCS_URL/tutorials/2d/2d_sprite_animation.html</link> + <link title="Animation documentation index">$DOCS_URL/tutorials/animation/index.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <methods> diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml index 40dcd950d7..48c5398074 100644 --- a/doc/classes/AnimationTree.xml +++ b/doc/classes/AnimationTree.xml @@ -8,7 +8,7 @@ [b]Note:[/b] When linked with an [AnimationPlayer], several properties and methods of the corresponding [AnimationPlayer] will not function as expected. Playback and transitions should be handled using only the [AnimationTree] and its constituent [AnimationNode](s). The [AnimationPlayer] node should be used solely for adding, deleting, and editing animations. </description> <tutorials> - <link title="Using AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link> + <link title="Using AnimationTree">$DOCS_URL/tutorials/animation/animation_tree.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <methods> diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index c6a3f87042..0f7e6799be 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -7,7 +7,7 @@ 2D area that detects [CollisionObject2D] nodes overlapping, entering, or exiting. Can also alter or override local physics parameters (gravity, damping) and route audio to a custom audio bus. </description> <tutorials> - <link title="Using Area2D">https://docs.godotengine.org/en/latest/tutorials/physics/using_area_2d.html</link> + <link title="Using Area2D">$DOCS_URL/tutorials/physics/using_area_2d.html</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> <link title="2D Pong Demo">https://godotengine.org/asset-library/asset/121</link> <link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/120</link> @@ -50,6 +50,9 @@ The rate at which objects stop spinning in this area. Represents the angular velocity lost per second. See [member ProjectSettings.physics/2d/default_angular_damp] for more details about damping. </member> + <member name="angular_damp_space_override" type="int" setter="set_angular_damp_space_override_mode" getter="get_angular_damp_space_override_mode" enum="Area2D.SpaceOverride" default="0"> + Override mode for angular damping calculations within this area. See [enum SpaceOverride] for possible values. + </member> <member name="audio_bus_name" type="StringName" setter="set_audio_bus_name" getter="get_audio_bus_name" default="&"Master""> The name of the area's audio bus. </member> @@ -57,21 +60,30 @@ If [code]true[/code], the area's audio bus overrides the default audio bus. </member> <member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="980.0"> - The area's gravity intensity (in pixels per second squared). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction. + The area's gravity intensity (in pixels per second squared). This value multiplies the gravity direction. This is useful to alter the force of gravity without altering its direction. </member> - <member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale" default="0.0"> - The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance. + <member name="gravity_direction" type="Vector2" setter="set_gravity_direction" getter="get_gravity_direction" default="Vector2(0, 1)"> + The area's gravity vector (not normalized). </member> <member name="gravity_point" type="bool" setter="set_gravity_is_point" getter="is_gravity_a_point" default="false"> - If [code]true[/code], gravity is calculated from a point (set via [member gravity_vec]). See also [member space_override]. + If [code]true[/code], gravity is calculated from a point (set via [member gravity_point_center]). See also [member gravity_space_override]. </member> - <member name="gravity_vec" type="Vector2" setter="set_gravity_vector" getter="get_gravity_vector" default="Vector2(0, 1)"> - The area's gravity vector (not normalized). If gravity is a point (see [member gravity_point]), this will be the point of attraction. + <member name="gravity_point_center" type="Vector2" setter="set_gravity_point_center" getter="get_gravity_point_center" default="Vector2(0, 1)"> + If gravity is a point (see [member gravity_point]), this will be the point of attraction. + </member> + <member name="gravity_point_distance_scale" type="float" setter="set_gravity_point_distance_scale" getter="get_gravity_point_distance_scale" default="0.0"> + The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance. + </member> + <member name="gravity_space_override" type="int" setter="set_gravity_space_override_mode" getter="get_gravity_space_override_mode" enum="Area2D.SpaceOverride" default="0"> + Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp" default="0.1"> The rate at which objects stop moving in this area. Represents the linear velocity lost per second. See [member ProjectSettings.physics/2d/default_linear_damp] for more details about damping. </member> + <member name="linear_damp_space_override" type="int" setter="set_linear_damp_space_override_mode" getter="get_linear_damp_space_override_mode" enum="Area2D.SpaceOverride" default="0"> + Override mode for linear damping calculations within this area. See [enum SpaceOverride] for possible values. + </member> <member name="monitorable" type="bool" setter="set_monitorable" getter="is_monitorable" default="true"> If [code]true[/code], other monitoring areas can detect this area. </member> @@ -81,9 +93,6 @@ <member name="priority" type="float" setter="set_priority" getter="get_priority" default="0.0"> The area's priority. Higher priority areas are processed first. </member> - <member name="space_override" type="int" setter="set_space_override_mode" getter="get_space_override_mode" enum="Area2D.SpaceOverride" default="0"> - Override mode for gravity and damping calculations within this area. See [enum SpaceOverride] for possible values. - </member> </members> <signals> <signal name="area_entered"> diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index 571fd8cad3..450ed44307 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -48,6 +48,9 @@ The rate at which objects stop spinning in this area. Represents the angular velocity lost per second. See [member ProjectSettings.physics/3d/default_angular_damp] for more details about damping. </member> + <member name="angular_damp_space_override" type="int" setter="set_angular_damp_space_override_mode" getter="get_angular_damp_space_override_mode" enum="Area3D.SpaceOverride" default="0"> + Override mode for angular damping calculations within this area. See [enum SpaceOverride] for possible values. + </member> <member name="audio_bus_name" type="StringName" setter="set_audio_bus_name" getter="get_audio_bus_name" default="&"Master""> The name of the area's audio bus. </member> @@ -55,21 +58,30 @@ If [code]true[/code], the area's audio bus overrides the default audio bus. </member> <member name="gravity" type="float" setter="set_gravity" getter="get_gravity" default="9.8"> - The area's gravity intensity (in meters per second squared). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction. + The area's gravity intensity (in meters per second squared). This value multiplies the gravity direction. This is useful to alter the force of gravity without altering its direction. </member> - <member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale" default="0.0"> - The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance. + <member name="gravity_direction" type="Vector3" setter="set_gravity_direction" getter="get_gravity_direction" default="Vector3(0, -1, 0)"> + The area's gravity vector (not normalized). </member> <member name="gravity_point" type="bool" setter="set_gravity_is_point" getter="is_gravity_a_point" default="false"> - If [code]true[/code], gravity is calculated from a point (set via [member gravity_vec]). See also [member space_override]. + If [code]true[/code], gravity is calculated from a point (set via [member gravity_point_center]). See also [member gravity_space_override]. </member> - <member name="gravity_vec" type="Vector3" setter="set_gravity_vector" getter="get_gravity_vector" default="Vector3(0, -1, 0)"> - The area's gravity vector (not normalized). If gravity is a point (see [member gravity_point]), this will be the point of attraction. + <member name="gravity_point_center" type="Vector3" setter="set_gravity_point_center" getter="get_gravity_point_center" default="Vector3(0, -1, 0)"> + If gravity is a point (see [member gravity_point]), this will be the point of attraction. + </member> + <member name="gravity_point_distance_scale" type="float" setter="set_gravity_point_distance_scale" getter="get_gravity_point_distance_scale" default="0.0"> + The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance. + </member> + <member name="gravity_space_override" type="int" setter="set_gravity_space_override_mode" getter="get_gravity_space_override_mode" enum="Area3D.SpaceOverride" default="0"> + Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp" default="0.1"> The rate at which objects stop moving in this area. Represents the linear velocity lost per second. See [member ProjectSettings.physics/3d/default_linear_damp] for more details about damping. </member> + <member name="linear_damp_space_override" type="int" setter="set_linear_damp_space_override_mode" getter="get_linear_damp_space_override_mode" enum="Area3D.SpaceOverride" default="0"> + Override mode for linear damping calculations within this area. See [enum SpaceOverride] for possible values. + </member> <member name="monitorable" type="bool" setter="set_monitorable" getter="is_monitorable" default="true"> If [code]true[/code], other monitoring areas can detect this area. </member> @@ -91,9 +103,6 @@ <member name="reverb_bus_uniformity" type="float" setter="set_reverb_uniformity" getter="get_reverb_uniformity" default="0.0"> The degree to which this area's reverb is a uniform effect. Ranges from [code]0[/code] to [code]1[/code] with [code]0.1[/code] precision. </member> - <member name="space_override" type="int" setter="set_space_override_mode" getter="get_space_override_mode" enum="Area3D.SpaceOverride" default="0"> - Override mode for gravity and damping calculations within this area. See [enum SpaceOverride] for possible values. - </member> <member name="wind_attenuation_factor" type="float" setter="set_wind_attenuation_factor" getter="get_wind_attenuation_factor" default="0.0"> The exponential rate at which wind force decreases with distance from its origin. </member> diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 275b217247..b74d4c1d3d 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -477,15 +477,19 @@ [b]Note:[/b] You cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior. [codeblocks] [gdscript] - class MyCustomSorter: - static func sort_ascending(a, b): - if a[0] < b[0]: - return true - return false + func sort_ascending(a, b): + if a[0] < b[0]: + return true + return false - var my_items = [[5, "Potato"], [9, "Rice"], [4, "Tomato"]] - my_items.sort_custom(MyCustomSorter.sort_ascending) - print(my_items) # Prints [[4, Tomato], [5, Potato], [9, Rice]]. + func _ready(): + var my_items = [[5, "Potato"], [9, "Rice"], [4, "Tomato"]] + my_items.sort_custom(sort_ascending) + print(my_items) # Prints [[4, Tomato], [5, Potato], [9, Rice]]. + + # Descending, lambda version. + my_items.sort_custom(func(a, b): return a[0] > b[0]) + print(my_items) # Prints [[9, Rice], [5, Potato], [4, Tomato]]. [/gdscript] [csharp] // There is no custom sort support for Godot.Collections.Array diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml index 7b77462322..c986947dfb 100644 --- a/doc/classes/ArrayMesh.xml +++ b/doc/classes/ArrayMesh.xml @@ -47,7 +47,7 @@ [b]Note:[/b] Godot uses clockwise [url=https://learnopengl.com/Advanced-OpenGL/Face-culling]winding order[/url] for front faces of triangle primitive modes. </description> <tutorials> - <link title="Procedural geometry using the ArrayMesh">https://docs.godotengine.org/en/latest/tutorials/3d/procedural_geometry/arraymesh.html</link> + <link title="Procedural geometry using the ArrayMesh">$DOCS_URL/tutorials/3d/procedural_geometry/arraymesh.html</link> </tutorials> <methods> <method name="add_blend_shape"> diff --git a/doc/classes/AudioEffectDistortion.xml b/doc/classes/AudioEffectDistortion.xml index 600ca93028..ed1cb789e0 100644 --- a/doc/classes/AudioEffectDistortion.xml +++ b/doc/classes/AudioEffectDistortion.xml @@ -9,7 +9,7 @@ By distorting the waveform the frequency content change, which will often make the sound "crunchy" or "abrasive". For games, it can simulate sound coming from some saturated device or speaker very efficiently. </description> <tutorials> - <link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link> + <link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link> </tutorials> <members> <member name="drive" type="float" setter="set_drive" getter="get_drive" default="0.0"> diff --git a/doc/classes/AudioEffectFilter.xml b/doc/classes/AudioEffectFilter.xml index 5b43646077..4fb1c0e7c9 100644 --- a/doc/classes/AudioEffectFilter.xml +++ b/doc/classes/AudioEffectFilter.xml @@ -7,7 +7,7 @@ Allows frequencies other than the [member cutoff_hz] to pass. </description> <tutorials> - <link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link> + <link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link> </tutorials> <members> <member name="cutoff_hz" type="float" setter="set_cutoff" getter="get_cutoff" default="2000.0"> diff --git a/doc/classes/AudioEffectHighShelfFilter.xml b/doc/classes/AudioEffectHighShelfFilter.xml index c572824448..28498f6d8e 100644 --- a/doc/classes/AudioEffectHighShelfFilter.xml +++ b/doc/classes/AudioEffectHighShelfFilter.xml @@ -6,6 +6,6 @@ <description> </description> <tutorials> - <link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link> + <link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link> </tutorials> </class> diff --git a/doc/classes/AudioEffectLowShelfFilter.xml b/doc/classes/AudioEffectLowShelfFilter.xml index e78dbf9732..4c839dc257 100644 --- a/doc/classes/AudioEffectLowShelfFilter.xml +++ b/doc/classes/AudioEffectLowShelfFilter.xml @@ -6,6 +6,6 @@ <description> </description> <tutorials> - <link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link> + <link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link> </tutorials> </class> diff --git a/doc/classes/AudioEffectRecord.xml b/doc/classes/AudioEffectRecord.xml index b32206726d..0b6c5287cf 100644 --- a/doc/classes/AudioEffectRecord.xml +++ b/doc/classes/AudioEffectRecord.xml @@ -7,7 +7,7 @@ Allows the user to record sound from a microphone. It sets and gets the format in which the audio file will be recorded (8-bit, 16-bit, or compressed). It checks whether or not the recording is active, and if it is, records the sound. It then returns the recorded sample. </description> <tutorials> - <link title="Recording with microphone">https://docs.godotengine.org/en/latest/tutorials/audio/recording_with_microphone.html</link> + <link title="Recording with microphone">$DOCS_URL/tutorials/audio/recording_with_microphone.html</link> <link title="Audio Mic Record Demo">https://godotengine.org/asset-library/asset/527</link> </tutorials> <methods> diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml index 66fa57cb52..b868cce077 100644 --- a/doc/classes/AudioServer.xml +++ b/doc/classes/AudioServer.xml @@ -7,7 +7,7 @@ [AudioServer] is a low-level server interface for audio access. It is in charge of creating sample data (playable audio) as well as its playback via a voice interface. </description> <tutorials> - <link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link> + <link title="Audio buses">$DOCS_URL/tutorials/audio/audio_buses.html</link> <link title="Audio Device Changer Demo">https://godotengine.org/asset-library/asset/525</link> <link title="Audio Mic Record Demo">https://godotengine.org/asset-library/asset/527</link> <link title="Audio Spectrum Demo">https://godotengine.org/asset-library/asset/528</link> diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml index cff7199c4a..722ff802e7 100644 --- a/doc/classes/AudioStream.xml +++ b/doc/classes/AudioStream.xml @@ -7,7 +7,7 @@ Base class for audio streams. Audio streams are used for sound effects and music playback, and support WAV (via [AudioStreamSample]) and OGG (via [AudioStreamOGGVorbis]) file formats. </description> <tutorials> - <link title="Audio streams">https://docs.godotengine.org/en/latest/tutorials/audio/audio_streams.html</link> + <link title="Audio streams">$DOCS_URL/tutorials/audio/audio_streams.html</link> <link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link> <link title="Audio Mic Record Demo">https://godotengine.org/asset-library/asset/527</link> <link title="Audio Spectrum Demo">https://godotengine.org/asset-library/asset/528</link> diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml index b692ae858e..d20aaff1e8 100644 --- a/doc/classes/AudioStreamPlayer.xml +++ b/doc/classes/AudioStreamPlayer.xml @@ -8,7 +8,7 @@ To play audio positionally, use [AudioStreamPlayer2D] or [AudioStreamPlayer3D] instead of [AudioStreamPlayer]. </description> <tutorials> - <link title="Audio streams">https://docs.godotengine.org/en/latest/tutorials/audio/audio_streams.html</link> + <link title="Audio streams">$DOCS_URL/tutorials/audio/audio_streams.html</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> <link title="Audio Device Changer Demo">https://godotengine.org/asset-library/asset/525</link> <link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link> diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml index 9c76eefbf9..0ad161a6fe 100644 --- a/doc/classes/AudioStreamPlayer2D.xml +++ b/doc/classes/AudioStreamPlayer2D.xml @@ -9,7 +9,7 @@ [b]Note:[/b] Hiding an [AudioStreamPlayer2D] node does not disable its audio output. To temporarily disable an [AudioStreamPlayer2D]'s audio output, set [member volume_db] to a very low value like [code]-100[/code] (which isn't audible to human hearing). </description> <tutorials> - <link title="Audio streams">https://docs.godotengine.org/en/latest/tutorials/audio/audio_streams.html</link> + <link title="Audio streams">$DOCS_URL/tutorials/audio/audio_streams.html</link> </tutorials> <methods> <method name="get_playback_position"> diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml index e8a78d5a4c..ce8a6693db 100644 --- a/doc/classes/AudioStreamPlayer3D.xml +++ b/doc/classes/AudioStreamPlayer3D.xml @@ -10,7 +10,7 @@ [b]Note:[/b] Hiding an [AudioStreamPlayer3D] node does not disable its audio output. To temporarily disable an [AudioStreamPlayer3D]'s audio output, set [member unit_db] to a very low value like [code]-100[/code] (which isn't audible to human hearing). </description> <tutorials> - <link title="Audio streams">https://docs.godotengine.org/en/latest/tutorials/audio/audio_streams.html</link> + <link title="Audio streams">$DOCS_URL/tutorials/audio/audio_streams.html</link> </tutorials> <methods> <method name="get_playback_position"> diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamSample.xml index 7e1155d89b..df7b5ff1c7 100644 --- a/doc/classes/AudioStreamSample.xml +++ b/doc/classes/AudioStreamSample.xml @@ -61,7 +61,7 @@ <constant name="LOOP_FORWARD" value="1" enum="LoopMode"> Audio loops the data between [member loop_begin] and [member loop_end], playing forward only. </constant> - <constant name="LOOP_PING_PONG" value="2" enum="LoopMode"> + <constant name="LOOP_PINGPONG" value="2" enum="LoopMode"> Audio loops the data between [member loop_begin] and [member loop_end], playing back and forth. </constant> <constant name="LOOP_BACKWARD" value="3" enum="LoopMode"> diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 889c703b07..981b3167d9 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -50,7 +50,7 @@ <member name="button_group" type="ButtonGroup" setter="set_button_group" getter="get_button_group"> The [ButtonGroup] associated with the button. Not to be confused with node groups. </member> - <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" default="1"> + <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButton" default="1"> Binary mask to choose which mouse buttons this button will respond to. To allow both left-click and right-click, use [code]MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT[/code]. </member> diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index 818ab50030..f0f49f89d5 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -7,7 +7,7 @@ This provides a default material with a wide variety of rendering features and properties without the need to write shader code. See the tutorial below for details. </description> <tutorials> - <link title="Standard Material 3D">https://docs.godotengine.org/en/latest/tutorials/3d/standard_material_3d.html</link> + <link title="Standard Material 3D">$DOCS_URL/tutorials/3d/standard_material_3d.html</link> </tutorials> <methods> <method name="get_feature" qualifiers="const"> diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index 8ef9cd2e7c..bf3d20c11c 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -10,9 +10,9 @@ For more information, read the "Matrices and transforms" documentation article. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Matrices and transforms">https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html</link> - <link title="Using 3D transforms">https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Matrices and transforms">$DOCS_URL/tutorials/math/matrices_and_transforms.html</link> + <link title="Using 3D transforms">$DOCS_URL/tutorials/3d/using_transforms.html</link> <link title="Matrix Transform Demo">https://godotengine.org/asset-library/asset/584</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> @@ -232,18 +232,22 @@ <return type="bool" /> <argument index="0" name="right" type="Basis" /> <description> + Returns [code]true[/code] if the [Basis] matrices are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="Basis" /> <argument index="0" name="right" type="Basis" /> <description> + Composes these two basis matrices by multiplying them together. This has the effect of transforming the second basis (the child) by the first basis (the parent). </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="Vector3" /> <description> + Transforms (multiplies) the [Vector3] by the given [Basis] matrix. </description> </operator> <operator name="operator *"> @@ -269,12 +273,15 @@ <return type="bool" /> <argument index="0" name="right" type="Basis" /> <description> + Returns [code]true[/code] if the [Basis] matrices are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator []"> <return type="Vector3" /> <argument index="0" name="index" type="int" /> <description> + Access basis components using their index. [code]b[0][/code] is equivalent to [code]b.x[/code], [code]b[1][/code] is equivalent to [code]b.y[/code], and [code]b[2][/code] is equivalent to [code]b.z[/code]. </description> </operator> </operators> diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml index ba55fda59c..d63bad7cad 100644 --- a/doc/classes/Button.xml +++ b/doc/classes/Button.xml @@ -78,6 +78,7 @@ </member> <member name="icon" type="Texture2D" setter="set_button_icon" getter="get_button_icon"> Button's icon, if text is present the icon will be placed before the text. + To edit margin and spacing of the icon, use [code]hseparation[/code] theme property of [Button] and [code]content_margin_*[/code] properties of the used [StyleBox]es. </member> <member name="icon_align" type="int" setter="set_icon_align" getter="get_icon_align" enum="Button.TextAlign" default="0"> Specifies if the icon should be aligned to the left, right, or center of a button. Uses the same [enum TextAlign] constants as the text alignment. If centered, text will draw on top of the icon. diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml index 9226140c1a..0505d8ad36 100644 --- a/doc/classes/CPUParticles2D.xml +++ b/doc/classes/CPUParticles2D.xml @@ -8,7 +8,7 @@ See also [GPUParticles2D], which provides the same functionality with hardware acceleration, but may not run on older devices. </description> <tutorials> - <link title="Particle systems (2D)">https://docs.godotengine.org/en/latest/tutorials/2d/particle_systems_2d.html</link> + <link title="Particle systems (2D)">$DOCS_URL/tutorials/2d/particle_systems_2d.html</link> </tutorials> <methods> <method name="convert_from_particles"> diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index 7be18c1d5c..98437ef296 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -12,8 +12,8 @@ [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg2rad]. </description> <tutorials> - <link title="Viewport and canvas transforms">https://docs.godotengine.org/en/latest/tutorials/2d/2d_transforms.html</link> - <link title="Custom drawing in 2D">https://docs.godotengine.org/en/latest/tutorials/2d/custom_drawing_in_2d.html</link> + <link title="Viewport and canvas transforms">$DOCS_URL/tutorials/2d/2d_transforms.html</link> + <link title="Custom drawing in 2D">$DOCS_URL/tutorials/2d/custom_drawing_in_2d.html</link> <link title="Audio Spectrum Demo">https://godotengine.org/asset-library/asset/528</link> </tutorials> <methods> diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml index 2f99f94893..9ee5ce0dcb 100644 --- a/doc/classes/CanvasLayer.xml +++ b/doc/classes/CanvasLayer.xml @@ -7,8 +7,8 @@ Canvas drawing layer. [CanvasItem] nodes that are direct or indirect children of a [CanvasLayer] will be drawn in that layer. The layer is a numeric index that defines the draw order. The default 2D scene renders with index 0, so a [CanvasLayer] with index -1 will be drawn below, and one with index 1 will be drawn above. This is very useful for HUDs (in layer 1+ or above), or backgrounds (in layer -1 or below). </description> <tutorials> - <link title="Viewport and canvas transforms">https://docs.godotengine.org/en/latest/tutorials/2d/2d_transforms.html</link> - <link title="Canvas layers">https://docs.godotengine.org/en/latest/tutorials/2d/canvas_layers.html</link> + <link title="Viewport and canvas transforms">$DOCS_URL/tutorials/2d/2d_transforms.html</link> + <link title="Canvas layers">$DOCS_URL/tutorials/2d/canvas_layers.html</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> </tutorials> <methods> diff --git a/doc/classes/CharFXTransform.xml b/doc/classes/CharFXTransform.xml index b11d9c341a..d467c8a51d 100644 --- a/doc/classes/CharFXTransform.xml +++ b/doc/classes/CharFXTransform.xml @@ -7,7 +7,7 @@ By setting various properties on this object, you can control how individual characters will be displayed in a [RichTextEffect]. </description> <tutorials> - <link title="BBCode in RichTextLabel">https://docs.godotengine.org/en/latest/tutorials/ui/bbcode_in_richtextlabel.html</link> + <link title="BBCode in RichTextLabel">$DOCS_URL/tutorials/ui/bbcode_in_richtextlabel.html</link> <link title="RichTextEffect test project (third-party)">https://github.com/Eoin-ONeill-Yokai/Godot-Rich-Text-Effect-Test-Project</link> </tutorials> <members> diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml index e14c2dc110..0f573dcd66 100644 --- a/doc/classes/CharacterBody2D.xml +++ b/doc/classes/CharacterBody2D.xml @@ -9,8 +9,8 @@ [b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [AnimatableBody2D]), which allows them to be moved by code and push other bodies on their path. </description> <tutorials> - <link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link> - <link title="Using KinematicBody2D">https://docs.godotengine.org/en/latest/tutorials/physics/using_kinematic_body_2d.html</link> + <link title="Kinematic character (2D)">$DOCS_URL/tutorials/physics/kinematic_character_2d.html</link> + <link title="Using KinematicBody2D">$DOCS_URL/tutorials/physics/using_kinematic_body_2d.html</link> <link title="2D Kinematic Character Demo">https://godotengine.org/asset-library/asset/113</link> <link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/120</link> </tutorials> diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml index 24b26fb16e..c70ce8acf9 100644 --- a/doc/classes/CharacterBody3D.xml +++ b/doc/classes/CharacterBody3D.xml @@ -9,7 +9,7 @@ [b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [AnimatableBody3D]), which allows them to be moved by code and push other bodies on their path. </description> <tutorials> - <link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link> + <link title="Kinematic character (2D)">$DOCS_URL/tutorials/physics/kinematic_character_2d.html</link> <link title="3D Kinematic Character Demo">https://godotengine.org/asset-library/asset/126</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml index ba1ee3909d..63492bf9a0 100644 --- a/doc/classes/CollisionObject2D.xml +++ b/doc/classes/CollisionObject2D.xml @@ -198,11 +198,11 @@ <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> The physics layers this CollisionObject2D is in. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. - [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The physics layers this CollisionObject2D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. - [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject2D.DisableMode" default="0"> Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml index 19bcdcbb27..33305471b8 100644 --- a/doc/classes/CollisionObject3D.xml +++ b/doc/classes/CollisionObject3D.xml @@ -170,11 +170,11 @@ <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> The physics layers this CollisionObject3D [b]is in[/b]. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. - [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The physics layers this CollisionObject3D [b]scans[/b]. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. - [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject3D.DisableMode" default="0"> Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. diff --git a/doc/classes/CollisionShape2D.xml b/doc/classes/CollisionShape2D.xml index 5159b2b15b..c86bf18f24 100644 --- a/doc/classes/CollisionShape2D.xml +++ b/doc/classes/CollisionShape2D.xml @@ -7,7 +7,7 @@ Editor facility for creating and editing collision shapes in 2D space. You can use this node to represent all sorts of collision shapes, for example, add this to an [Area2D] to give it a detection shape, or add it to a [PhysicsBody2D] to create a solid object. [b]IMPORTANT[/b]: this is an Editor-only helper to create shapes, use [method CollisionObject2D.shape_owner_get_shape] to get the actual shape. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> <link title="2D Pong Demo">https://godotengine.org/asset-library/asset/121</link> <link title="2D Kinematic Character Demo">https://godotengine.org/asset-library/asset/113</link> diff --git a/doc/classes/CollisionShape3D.xml b/doc/classes/CollisionShape3D.xml index 84e362c38b..0f96d7c191 100644 --- a/doc/classes/CollisionShape3D.xml +++ b/doc/classes/CollisionShape3D.xml @@ -7,7 +7,7 @@ Editor facility for creating and editing collision shapes in 3D space. You can use this node to represent all sorts of collision shapes, for example, add this to an [Area3D] to give it a detection shape, or add it to a [PhysicsBody3D] to create a solid object. [b]IMPORTANT[/b]: this is an Editor-only helper to create shapes, use [method CollisionObject3D.shape_owner_get_shape] to get the actual shape. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> <link title="3D Kinematic Character Demo">https://godotengine.org/asset-library/asset/126</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index 71ec225cf6..22fb853b40 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -147,6 +147,24 @@ <description> </description> </method> + <method name="from_hsv" qualifiers="static"> + <return type="Color" /> + <argument index="0" name="h" type="float" /> + <argument index="1" name="s" type="float" /> + <argument index="2" name="v" type="float" /> + <argument index="3" name="alpha" type="float" default="1.0" /> + <description> + Constructs a color from an [url=https://en.wikipedia.org/wiki/HSL_and_HSV]HSV profile[/url]. [code]h[/code] (hue), [code]s[/code] (saturation), and [code]v[/code] (value) are typically between 0 and 1. + [codeblocks] + [gdscript] + var c = Color.from_hsv(0.58, 0.5, 0.79, 0.8) + [/gdscript] + [csharp] + var c = Color.FromHsv(0.58f, 0.5f, 0.79f, 0.8f); + [/csharp] + [/codeblocks] + </description> + </method> <method name="from_rgbe9995" qualifiers="static"> <return type="Color" /> <argument index="0" name="rgbe" type="int" /> @@ -863,54 +881,64 @@ <return type="bool" /> <argument index="0" name="right" type="Color" /> <description> + Returns [code]true[/code] if the colors are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="Color" /> <argument index="0" name="right" type="Color" /> <description> + Multiplies each component of the [Color] by the components of the given [Color]. </description> </operator> <operator name="operator *"> <return type="Color" /> <argument index="0" name="right" type="float" /> <description> + Multiplies each component of the [Color] by the given [float]. </description> </operator> <operator name="operator *"> <return type="Color" /> <argument index="0" name="right" type="int" /> <description> + Multiplies each component of the [Color] by the given [int]. </description> </operator> <operator name="operator +"> <return type="Color" /> <argument index="0" name="right" type="Color" /> <description> + Adds each component of the [Color] with the components of the given [Color]. </description> </operator> <operator name="operator -"> <return type="Color" /> <argument index="0" name="right" type="Color" /> <description> + Subtracts each component of the [Color] by the components of the given [Color]. </description> </operator> <operator name="operator /"> <return type="Color" /> <argument index="0" name="right" type="Color" /> <description> + Divides each component of the [Color] by the components of the given [Color]. </description> </operator> <operator name="operator /"> <return type="Color" /> <argument index="0" name="right" type="float" /> <description> + Divides each component of the [Color] by the given [float]. </description> </operator> <operator name="operator /"> <return type="Color" /> <argument index="0" name="right" type="int" /> <description> + Divides each component of the [Color] by the given [int]. </description> </operator> <operator name="operator =="> @@ -922,22 +950,27 @@ <return type="bool" /> <argument index="0" name="right" type="Color" /> <description> + Returns [code]true[/code] if the colors are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator []"> <return type="float" /> <argument index="0" name="index" type="int" /> <description> + Access color components using their index. [code]c[0][/code] is equivalent to [code]c.r[/code], [code]c[1][/code] is equivalent to [code]c.g[/code], [code]c[2][/code] is equivalent to [code]c.b[/code], and [code]c[3][/code] is equivalent to [code]c.a[/code]. </description> </operator> <operator name="operator unary+"> <return type="Color" /> <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. </description> </operator> <operator name="operator unary-"> <return type="Color" /> <description> + Inverts the given color. This is equivalent to [code]Color.WHITE - c[/code] or [code]Color(1 - c.r, 1 - c.g, 1 - c.b, 1 - c.a)[/code]. </description> </operator> </operators> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 63e3eb7a5f..f6bb812070 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -16,9 +16,9 @@ [b]Note:[/b] Theme items are [i]not[/i] [Object] properties. This means you can't access their values using [method Object.get] and [method Object.set]. Instead, use the [code]get_theme_*[/code] and [code]add_theme_*_override[/code] methods provided by this class. </description> <tutorials> - <link title="GUI documentation index">https://docs.godotengine.org/en/latest/tutorials/ui/index.html</link> - <link title="Custom drawing in 2D">https://docs.godotengine.org/en/latest/tutorials/2d/custom_drawing_in_2d.html</link> - <link title="Control node gallery">https://docs.godotengine.org/en/latest/tutorials/ui/control_node_gallery.html</link> + <link title="GUI documentation index">$DOCS_URL/tutorials/ui/index.html</link> + <link title="Custom drawing in 2D">$DOCS_URL/tutorials/2d/custom_drawing_in_2d.html</link> + <link title="Control node gallery">$DOCS_URL/tutorials/ui/control_node_gallery.html</link> <link title="All GUI Demos">https://github.com/godotengine/godot-demo-projects/tree/master/gui</link> </tutorials> <methods> @@ -1043,7 +1043,7 @@ </member> <member name="rect_scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)"> The node's scale, relative to its [member rect_size]. Change this property to scale the node around its [member rect_pivot_offset]. The Control's [member hint_tooltip] will also scale according to this value. - [b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=https://docs.godotengine.org/en/latest/tutorials/viewports/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually. + [b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=$DOCS_URL/tutorials/viewports/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually. [b]Note:[/b] If the Control node is a child of a [Container] node, the scale will be reset to [code]Vector2(1, 1)[/code] when the scene is instantiated. To set the Control's scale when it's instantiated, wait for one frame using [code]await get_tree().process_frame[/code] then set its [member rect_scale] property. </member> <member name="rect_size" type="Vector2" setter="_set_size" getter="get_size" default="Vector2(0, 0)"> diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml index d661da5dd0..7218e3bcb0 100644 --- a/doc/classes/Dictionary.xml +++ b/doc/classes/Dictionary.xml @@ -177,7 +177,7 @@ [b]Note:[/b] When declaring a dictionary with [code]const[/code], the dictionary itself can still be mutated by defining the values of individual keys. Using [code]const[/code] will only prevent assigning the constant with another value after it was initialized. </description> <tutorials> - <link title="GDScript basics: Dictionary">https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_basics.html#dictionary</link> + <link title="GDScript basics: Dictionary">$DOCS_URL/tutorials/scripting/gdscript/gdscript_basics.html#dictionary</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> <link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link> </tutorials> diff --git a/doc/classes/DirectionalLight3D.xml b/doc/classes/DirectionalLight3D.xml index 44d982cbcc..661dbef07c 100644 --- a/doc/classes/DirectionalLight3D.xml +++ b/doc/classes/DirectionalLight3D.xml @@ -7,7 +7,7 @@ A directional light is a type of [Light3D] node that models an infinite number of parallel rays covering the entire scene. It is used for lights with strong intensity that are located far away from the scene to model sunlight or moonlight. The worldspace location of the DirectionalLight3D transform (origin) is ignored. Only the basis is used to determine light direction. </description> <tutorials> - <link title="Lights and shadows">https://docs.godotengine.org/en/latest/tutorials/3d/lights_and_shadows.html</link> + <link title="Lights and shadows">$DOCS_URL/tutorials/3d/lights_and_shadows.html</link> </tutorials> <members> <member name="directional_shadow_blend_splits" type="bool" setter="set_blend_splits" getter="is_blend_splits_enabled" default="false"> diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml index 93f04ff2a2..cd4b8fde1e 100644 --- a/doc/classes/Directory.xml +++ b/doc/classes/Directory.xml @@ -54,7 +54,7 @@ [/codeblocks] </description> <tutorials> - <link title="File system">https://docs.godotengine.org/en/latest/tutorials/scripting/filesystem.html</link> + <link title="File system">$DOCS_URL/tutorials/scripting/filesystem.html</link> </tutorials> <methods> <method name="change_dir"> diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 92d6a220d2..1ca69057b4 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -901,7 +901,7 @@ </constant> <constant name="WINDOW_MODE_FULLSCREEN" value="3" enum="WindowMode"> Fullscreen window mode. Note that this is not [i]exclusive[/i] fullscreen. On Windows and Linux, a borderless window is used to emulate fullscreen. On macOS, a new desktop is used to display the running project. - Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=https://docs.godotengine.org/en/latest/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode. + Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode. </constant> <constant name="WINDOW_FLAG_RESIZE_DISABLED" value="0" enum="WindowFlags"> </constant> diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml index cb33f159ef..1f98781bbd 100644 --- a/doc/classes/EditorImportPlugin.xml +++ b/doc/classes/EditorImportPlugin.xml @@ -111,12 +111,13 @@ To use [EditorImportPlugin], register it using the [method EditorPlugin.add_import_plugin] method first. </description> <tutorials> - <link title="Import plugins">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/import_plugins.html</link> + <link title="Import plugins">$DOCS_URL/tutorials/plugins/editor/import_plugins.html</link> </tutorials> <methods> <method name="_get_import_options" qualifiers="virtual const"> <return type="Array" /> - <argument index="0" name="preset_index" type="int" /> + <argument index="0" name="path" type="String" /> + <argument index="1" name="preset_index" type="int" /> <description> Gets the options and default values for the preset at this index. Returns an Array of Dictionaries with the following keys: [code]name[/code], [code]default_value[/code], [code]property_hint[/code] (optional), [code]hint_string[/code] (optional), [code]usage[/code] (optional). </description> @@ -135,8 +136,9 @@ </method> <method name="_get_option_visibility" qualifiers="virtual const"> <return type="bool" /> - <argument index="0" name="option_name" type="StringName" /> - <argument index="1" name="options" type="Dictionary" /> + <argument index="0" name="path" type="String" /> + <argument index="1" name="option_name" type="StringName" /> + <argument index="2" name="options" type="Dictionary" /> <description> This method can be overridden to hide specific import options if conditions are met. This is mainly useful for hiding options that depend on others if one of them is disabled. For example: [codeblocks] diff --git a/doc/classes/EditorInspectorPlugin.xml b/doc/classes/EditorInspectorPlugin.xml index f65e974d47..08f17cc5b2 100644 --- a/doc/classes/EditorInspectorPlugin.xml +++ b/doc/classes/EditorInspectorPlugin.xml @@ -13,7 +13,7 @@ To use [EditorInspectorPlugin], register it using the [method EditorPlugin.add_inspector_plugin] method first. </description> <tutorials> - <link title="Inspector plugins">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/inspector_plugins.html</link> + <link title="Inspector plugins">$DOCS_URL/tutorials/plugins/editor/inspector_plugins.html</link> </tutorials> <methods> <method name="_can_handle" qualifiers="virtual const"> @@ -25,8 +25,9 @@ </method> <method name="_parse_begin" qualifiers="virtual"> <return type="void" /> + <argument index="0" name="object" type="Object" /> <description> - Called to allow adding controls at the beginning of the list. + Called to allow adding controls at the beginning of the property list for [code]object[/code]. </description> </method> <method name="_parse_category" qualifiers="virtual"> @@ -34,12 +35,22 @@ <argument index="0" name="object" type="Object" /> <argument index="1" name="category" type="String" /> <description> + Called to allow adding controls at the beginning of a category in the property list for [code]object[/code]. </description> </method> <method name="_parse_end" qualifiers="virtual"> <return type="void" /> + <argument index="0" name="object" type="Object" /> + <description> + Called to allow adding controls at the end of the property list for [code]object[/code]. + </description> + </method> + <method name="_parse_group" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="object" type="Object" /> + <argument index="1" name="group" type="String" /> <description> - Called to allow adding controls at the end of the list. + Called to allow adding controls at the beginning of a group or a sub-group in the property list for [code]object[/code]. </description> </method> <method name="_parse_property" qualifiers="virtual"> @@ -52,7 +63,7 @@ <argument index="5" name="usage_flags" type="int" /> <argument index="6" name="wide" type="bool" /> <description> - Called to allow adding property specific editors to the inspector. Usually these inherit [EditorProperty]. Returning [code]true[/code] removes the built-in editor for this property, otherwise allows to insert a custom editor before the built-in one. + Called to allow adding property-specific editors to the property list for [code]object[/code]. The added editor control must extend [EditorProperty]. Returning [code]true[/code] removes the built-in editor for this property, otherwise allows to insert a custom editor before the built-in one. </description> </method> <method name="add_custom_control"> diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml index 08423c4577..3bcd9e7764 100644 --- a/doc/classes/EditorNode3DGizmoPlugin.xml +++ b/doc/classes/EditorNode3DGizmoPlugin.xml @@ -8,7 +8,7 @@ To use [EditorNode3DGizmoPlugin], register it using the [method EditorPlugin.add_spatial_gizmo_plugin] method first. </description> <tutorials> - <link title="Spatial gizmo plugins">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/spatial_gizmos.html</link> + <link title="Spatial gizmo plugins">$DOCS_URL/tutorials/plugins/editor/spatial_gizmos.html</link> </tutorials> <methods> <method name="_can_be_hidden" qualifiers="virtual const"> diff --git a/doc/classes/EditorPaths.xml b/doc/classes/EditorPaths.xml index 92a2cff27f..c4d4c92afe 100644 --- a/doc/classes/EditorPaths.xml +++ b/doc/classes/EditorPaths.xml @@ -1,35 +1,65 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="EditorPaths" inherits="Object" version="4.0"> <brief_description> + Editor-only singleton that returns paths to various OS-specific data folders and files. </brief_description> <description> + This editor-only singleton returns OS-specific paths to various data folders and files. It can be used in editor plugins to ensure files are saved in the correct location on each operating system. + [b]Note:[/b] This singleton is not accessible in exported projects. Attempting to access it in an exported project will result in a script error as the singleton won't be declared. To prevent script errors in exported projects, use [method Engine.has_singleton] to check whether the singleton is available before using it. + [b]Note:[/b] Godot complies with the [url=https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html]XDG Base Directory Specification[/url] on [i]all[/i] platforms. You can override environment variables following the specification to change the editor and project data paths. </description> <tutorials> + <link title="File paths in Godot projects">https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html</link> </tutorials> <methods> <method name="get_cache_dir" qualifiers="const"> <return type="String" /> <description> + Returns the absolute path to the user's cache folder. This folder should be used for temporary data that can be removed safely whenever the editor is closed (such as generated resource thumbnails). + [b]Default paths per platform:[/b] + [codeblock] + - Windows: %LOCALAPPDATA%\Godot\ + - macOS: ~/Library/Caches/Godot/ + - Linux: ~/.cache/godot/ + [/codeblock] </description> </method> <method name="get_config_dir" qualifiers="const"> <return type="String" /> <description> + Returns the absolute path to the user's configuration folder. This folder should be used for [i]persistent[/i] user configuration files. + [b]Default paths per platform:[/b] + [codeblock] + - Windows: %APPDATA%\Godot\ (same as `get_data_dir()`) + - macOS: ~/Library/Application Support/Godot/ (same as `get_data_dir()`) + - Linux: ~/.config/godot/ + [/codeblock] </description> </method> <method name="get_data_dir" qualifiers="const"> <return type="String" /> <description> + Returns the absolute path to the user's data folder. This folder should be used for [i]persistent[/i] user data files such as installed export templates. + [b]Default paths per platform:[/b] + [codeblock] + - Windows: %APPDATA%\Godot\ (same as `get_config_dir()`) + - macOS: ~/Library/Application Support/Godot/ (same as `get_config_dir()`) + - Linux: ~/.local/share/godot/ + [/codeblock] </description> </method> <method name="get_self_contained_file" qualifiers="const"> <return type="String" /> <description> + Returns the absolute path to the self-contained file that makes the current Godot editor instance be considered as self-contained. Returns an empty string if the current Godot editor instance isn't self-contained. See also [method is_self_contained]. </description> </method> <method name="is_self_contained" qualifiers="const"> <return type="bool" /> <description> + Returns [code]true[/code] if the editor is marked as self-contained, [code]false[/code] otherwise. When self-contained mode is enabled, user configuration, data and cache files are saved in an [code]editor_data/[/code] folder next to the editor binary. This makes portable usage easier and ensures the Godot editor minimizes file writes outside its own folder. Self-contained mode is not available for exported projects. + Self-contained mode can be enabled by creating a file named [code]._sc_[/code] or [code]_sc_[/code] in the same folder as the editor binary while the editor is not running. See also [method get_self_contained_file]. + [b]Note:[/b] The Steam release of Godot uses self-contained mode by default. </description> </method> </methods> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 8df6d721d4..7b0a300782 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -7,7 +7,7 @@ Plugins are used by the editor to extend functionality. The most common types of plugins are those which edit a given node or resource type, import plugins and export plugins. See also [EditorScript] to add functions to the editor. </description> <tutorials> - <link title="Editor plugins documentation index">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/index.html</link> + <link title="Editor plugins documentation index">$DOCS_URL/tutorials/plugins/editor/index.html</link> </tutorials> <methods> <method name="_apply_changes" qualifiers="virtual"> diff --git a/doc/classes/EditorSceneFormatImporter.xml b/doc/classes/EditorSceneFormatImporter.xml index 6dbd80604e..5b5d6c4598 100644 --- a/doc/classes/EditorSceneFormatImporter.xml +++ b/doc/classes/EditorSceneFormatImporter.xml @@ -20,6 +20,19 @@ <description> </description> </method> + <method name="_get_import_options" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="path" type="String" /> + <description> + </description> + </method> + <method name="_get_option_visibility" qualifiers="virtual const"> + <return type="Variant" /> + <argument index="0" name="path" type="String" /> + <argument index="1" name="option" type="String" /> + <description> + </description> + </method> <method name="_import_animation" qualifiers="virtual"> <return type="Animation" /> <argument index="0" name="path" type="String" /> diff --git a/doc/classes/EditorScenePostImport.xml b/doc/classes/EditorScenePostImport.xml index 8a731a6d1d..d90af6ed9e 100644 --- a/doc/classes/EditorScenePostImport.xml +++ b/doc/classes/EditorScenePostImport.xml @@ -52,7 +52,7 @@ [/codeblocks] </description> <tutorials> - <link title="Importing 3D scenes: Custom script">https://docs.godotengine.org/en/latest/tutorials/assets_pipeline/importing_scenes.html#custom-script</link> + <link title="Importing 3D scenes: Custom script">$DOCS_URL/tutorials/assets_pipeline/importing_scenes.html#custom-script</link> </tutorials> <methods> <method name="_post_import" qualifiers="virtual"> diff --git a/doc/classes/EditorScenePostImportPlugin.xml b/doc/classes/EditorScenePostImportPlugin.xml index 07d8fa28b9..904b22d9d3 100644 --- a/doc/classes/EditorScenePostImportPlugin.xml +++ b/doc/classes/EditorScenePostImportPlugin.xml @@ -11,6 +11,7 @@ <methods> <method name="_get_import_options" qualifiers="virtual"> <return type="void" /> + <argument index="0" name="path" type="String" /> <description> Override to add general import options. These will appear in the main import dock on the editor. Add options via [method add_import_option] and [method add_import_option_advanced]. </description> @@ -40,7 +41,8 @@ </method> <method name="_get_option_visibility" qualifiers="virtual const"> <return type="Variant" /> - <argument index="0" name="option" type="String" /> + <argument index="0" name="path" type="String" /> + <argument index="1" name="option" type="String" /> <description> Return true or false whether a given option should be visible. Return null to ignore. </description> diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index f05a216301..9756b26dee 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -157,7 +157,7 @@ else: simulate_physics() [/codeblock] - See [url=https://docs.godotengine.org/en/latest/tutorials/plugins/running_code_in_the_editor.html]Running code in the editor[/url] in the documentation for more information. + See [url=$DOCS_URL/tutorials/plugins/running_code_in_the_editor.html]Running code in the editor[/url] in the documentation for more information. [b]Note:[/b] To detect whether the script is run from an editor [i]build[/i] (e.g. when pressing [kbd]F5[/kbd]), use [method OS.has_feature] with the [code]"editor"[/code] argument instead. [code]OS.has_feature("editor")[/code] will evaluate to [code]true[/code] both when the code is running in the editor and when running the project from the editor, but it will evaluate to [code]false[/code] when the code is run from an exported project. </description> </method> diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 4ea7f67eed..c3d1dc4ab6 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -11,8 +11,8 @@ - Adjustments </description> <tutorials> - <link title="Environment and post-processing">https://docs.godotengine.org/en/latest/tutorials/3d/environment_and_post_processing.html</link> - <link title="Light transport in game engines">https://docs.godotengine.org/en/latest/tutorials/3d/high_dynamic_range.html</link> + <link title="Environment and post-processing">$DOCS_URL/tutorials/3d/environment_and_post_processing.html</link> + <link title="Light transport in game engines">$DOCS_URL/tutorials/3d/high_dynamic_range.html</link> <link title="3D Material Testers Demo">https://godotengine.org/asset-library/asset/123</link> <link title="2D HDR Demo">https://godotengine.org/asset-library/asset/110</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> @@ -171,7 +171,8 @@ <member name="sdfgi_cascades" type="int" setter="set_sdfgi_cascades" getter="get_sdfgi_cascades" enum="Environment.SDFGICascades" default="1"> </member> <member name="sdfgi_enabled" type="bool" setter="set_sdfgi_enabled" getter="is_sdfgi_enabled" default="false"> - If [code]true[/code], enables signed distance field global illumination. + If [code]true[/code], enables signed distance field global illumination for meshes that have their [member GeometryInstance3D.gi_mode] set to [constant GeometryInstance3D.GI_MODE_BAKED]. SDFGI is a real-time global illumination technique that works well with procedurally generated and user-built levels, including in situations where geometry is created during gameplay. The signed distance field is automatically generated around the camera as it moves. Dynamic lights are supported, but dynamic occluders and emissive surfaces are not. + [b]Performance:[/b] SDFGI is relatively demanding on the GPU and is not suited to low-end hardware such as integrated graphics (consider [LightmapGI] instead). To improve SDFGI performance, enable [member ProjectSettings.rendering/global_illumination/gi/use_half_resolution] in the Project Settings. [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. </member> <member name="sdfgi_energy" type="float" setter="set_sdfgi_energy" getter="get_sdfgi_energy" default="1.0"> diff --git a/doc/classes/File.xml b/doc/classes/File.xml index 811aeb8aab..276c1f0223 100644 --- a/doc/classes/File.xml +++ b/doc/classes/File.xml @@ -40,12 +40,12 @@ } [/csharp] [/codeblocks] - In the example above, the file will be saved in the user data folder as specified in the [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]Data paths[/url] documentation. + In the example above, the file will be saved in the user data folder as specified in the [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] documentation. [b]Note:[/b] To access project resources once exported, it is recommended to use [ResourceLoader] instead of the [File] API, as some files are converted to engine-specific formats and their original source files might not be present in the exported PCK package. [b]Note:[/b] Files are automatically closed only if the process exits "normally" (such as by clicking the window manager's close button or pressing [b]Alt + F4[/b]). If you stop the project execution by pressing [b]F8[/b] while the project is running, the file won't be closed as the game process will be killed. You can work around this by calling [method flush] at regular intervals. </description> <tutorials> - <link title="File system">https://docs.godotengine.org/en/latest/tutorials/scripting/filesystem.html</link> + <link title="File system">$DOCS_URL/tutorials/scripting/filesystem.html</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> <methods> diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 72bd6a6411..72adc49742 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -8,7 +8,7 @@ Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. </description> <tutorials> - <link title="Particle systems (2D)">https://docs.godotengine.org/en/latest/tutorials/2d/particle_systems_2d.html</link> + <link title="Particle systems (2D)">$DOCS_URL/tutorials/2d/particle_systems_2d.html</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> </tutorials> <methods> diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index 0bed561de3..771056cb93 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -8,7 +8,7 @@ Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. </description> <tutorials> - <link title="Controlling thousands of fish with Particles">https://docs.godotengine.org/en/latest/tutorials/performance/vertex_animation/controlling_thousands_of_fish.html</link> + <link title="Controlling thousands of fish with Particles">$DOCS_URL/tutorials/performance/vertex_animation/controlling_thousands_of_fish.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <methods> diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index 0a2c0fbe81..b8514c67b8 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -38,8 +38,10 @@ The extra distance added to the GeometryInstance3D's bounding box ([AABB]) to increase its cull box. </member> <member name="gi_lightmap_scale" type="int" setter="set_lightmap_scale" getter="get_lightmap_scale" enum="GeometryInstance3D.LightmapScale" default="0"> + The texel density to use for lightmapping in [LightmapGI]. Greater scale values provide higher resolution in the lightmap, which can result in sharper shadows for lights that have both direct and indirect light baked. However, greater scale values will also increase the space taken by the mesh in the lightmap texture, which increases the memory, storage, and bake time requirements. When using a single mesh at different scales, consider adjusting this value to keep the lightmap texel density consistent across meshes. </member> <member name="gi_mode" type="int" setter="set_gi_mode" getter="get_gi_mode" enum="GeometryInstance3D.GIMode" default="0"> + The global illumination mode to use for the whole geometry. Use a mode that matches the purpose </member> <member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling" default="false"> </member> @@ -70,7 +72,7 @@ </members> <constants> <constant name="SHADOW_CASTING_SETTING_OFF" value="0" enum="ShadowCastingSetting"> - Will not cast any shadows. + Will not cast any shadows. Use this to improve performance for small geometry that is unlikely to cast noticeable shadows (such as debris). </constant> <constant name="SHADOW_CASTING_SETTING_ON" value="1" enum="ShadowCastingSetting"> Will cast shadows from all visible faces in the GeometryInstance3D. @@ -85,20 +87,28 @@ In other words, the actual mesh will not be visible, only the shadows casted from the mesh will be. </constant> <constant name="GI_MODE_DISABLED" value="0" enum="GIMode"> + Disabled global illumination mode. Use for dynamic objects that do not contribute to global illumination (such as characters). When using [VoxelGI] and SDFGI, the geometry will [i]receive[/i] indirect lighting and reflections but will not be considered in GI baking. When using [LightmapGI], the object will receive indirect lighting using lightmap probes instead of using the lightmap texture. </constant> <constant name="GI_MODE_BAKED" value="1" enum="GIMode"> + Baked global illumination mode. Use for static objects that contribute to global illumination (such as level geometry). This GI mode is effective when using [VoxelGI], SDFGI and [LightmapGI]. </constant> <constant name="GI_MODE_DYNAMIC" value="2" enum="GIMode"> + Dynamic global illumination mode. Use for dynamic objects that contribute to global illumination. This GI mode is only effective when using [VoxelGI], but it has a higher performance impact than [constant GI_MODE_BAKED]. </constant> <constant name="LIGHTMAP_SCALE_1X" value="0" enum="LightmapScale"> + The standard texel density for lightmapping with [LightmapGI]. </constant> <constant name="LIGHTMAP_SCALE_2X" value="1" enum="LightmapScale"> + Multiplies texel density by 2× for lightmapping with [LightmapGI]. To ensure consistency in texel density, use this when scaling a mesh by a factor between 1.5 and 3.0. </constant> <constant name="LIGHTMAP_SCALE_4X" value="2" enum="LightmapScale"> + Multiplies texel density by 4× for lightmapping with [LightmapGI]. To ensure consistency in texel density, use this when scaling a mesh by a factor between 3.0 and 6.0. </constant> <constant name="LIGHTMAP_SCALE_8X" value="3" enum="LightmapScale"> + Multiplies texel density by 8× for lightmapping with [LightmapGI]. To ensure consistency in texel density, use this when scaling a mesh by a factor greater than 6.0. </constant> <constant name="LIGHTMAP_SCALE_MAX" value="4" enum="LightmapScale"> + Represents the size of the [enum LightmapScale] enum. </constant> <constant name="VISIBILITY_RANGE_FADE_DISABLED" value="0" enum="VisibilityRangeFadeMode"> Will not fade itself nor its visibility dependencies, hysteresis will be used instead. See [member visibility_range_begin] and [member Node3D.visibility_parent] for more information. diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index 9f33c400f4..a50983853d 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -15,8 +15,8 @@ [b]Warning:[/b] SSL/TLS certificate revocation and certificate pinning are currently not supported. Revoked certificates are accepted as long as they are otherwise valid. If this is a concern, you may want to use automatically managed certificates with a short validity period. </description> <tutorials> - <link title="HTTP client class">https://docs.godotengine.org/en/latest/tutorials/networking/http_client_class.html</link> - <link title="SSL certificates">https://docs.godotengine.org/en/latest/tutorials/networking/ssl_certificates.html</link> + <link title="HTTP client class">$DOCS_URL/tutorials/networking/http_client_class.html</link> + <link title="SSL certificates">$DOCS_URL/tutorials/networking/ssl_certificates.html</link> </tutorials> <methods> <method name="close"> diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index 558e51aefe..aaaf863c69 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -153,8 +153,8 @@ [b]Gzipped response bodies[/b]: HTTPRequest will automatically handle decompression of response bodies. A [code]Accept-Encoding[/code] header will be automatically added to each of your requests, unless one is already specified. Any response with a [code]Content-Encoding: gzip[/code] header will automatically be decompressed and delivered to you as uncompressed bytes. </description> <tutorials> - <link title="Making HTTP requests">https://docs.godotengine.org/en/latest/tutorials/networking/http_request_class.html</link> - <link title="SSL certificates">https://docs.godotengine.org/en/latest/tutorials/networking/ssl_certificates.html</link> + <link title="Making HTTP requests">$DOCS_URL/tutorials/networking/http_request_class.html</link> + <link title="SSL certificates">$DOCS_URL/tutorials/networking/ssl_certificates.html</link> </tutorials> <methods> <method name="cancel_request"> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 492bddca1f..d2b1b5c004 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -9,7 +9,7 @@ [b]Note:[/b] The maximum image size is 16384×16384 pixels due to graphics hardware limitations. Larger images may fail to import. </description> <tutorials> - <link title="Importing images">https://docs.godotengine.org/en/latest/tutorials/assets_pipeline/importing_images.html</link> + <link title="Importing images">$DOCS_URL/tutorials/assets_pipeline/importing_images.html</link> </tutorials> <methods> <method name="adjust_bcs"> @@ -278,7 +278,7 @@ <return type="int" enum="Error" /> <argument index="0" name="path" type="String" /> <description> - Loads an image from file [code]path[/code]. See [url=https://docs.godotengine.org/en/latest/getting_started/workflow/assets/importing_images.html#supported-image-formats]Supported image formats[/url] for a list of supported image formats and limitations. + Loads an image from file [code]path[/code]. See [url=$DOCS_URL/getting_started/workflow/assets/importing_images.html#supported-image-formats]Supported image formats[/url] for a list of supported image formats and limitations. [b]Warning:[/b] This method should only be used in the editor or in cases when you need to load external images at run-time, such as images located at the [code]user://[/code] directory, and may not work in exported projects. See also [ImageTexture] description for usage examples. </description> diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml index af7178db95..3f96d357b6 100644 --- a/doc/classes/ImageTexture.xml +++ b/doc/classes/ImageTexture.xml @@ -28,7 +28,7 @@ [b]Note:[/b] The maximum texture size is 16384×16384 pixels due to graphics hardware limitations. </description> <tutorials> - <link title="Importing images">https://docs.godotengine.org/en/latest/tutorials/assets_pipeline/importing_images.html</link> + <link title="Importing images">$DOCS_URL/tutorials/assets_pipeline/importing_images.html</link> </tutorials> <methods> <method name="create_from_image"> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 1fded42db2..4ee319f554 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -7,7 +7,7 @@ A singleton that deals with inputs. This includes key presses, mouse buttons and movement, joypads, and input actions. Actions and their events can be set in the [b]Input Map[/b] tab in the [b]Project > Project Settings[/b], or with the [InputMap] class. </description> <tutorials> - <link title="Inputs documentation index">https://docs.godotengine.org/en/latest/tutorials/inputs/index.html</link> + <link title="Inputs documentation index">$DOCS_URL/tutorials/inputs/index.html</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> @@ -155,7 +155,7 @@ </description> </method> <method name="get_mouse_button_mask" qualifiers="const"> - <return type="int" /> + <return type="int" enum="MouseButton" /> <description> Returns mouse buttons as a bitmask. If multiple mouse buttons are pressed at the same time, the bits are added together. </description> diff --git a/doc/classes/InputEvent.xml b/doc/classes/InputEvent.xml index 9dc8fbeffa..09fbe776bf 100644 --- a/doc/classes/InputEvent.xml +++ b/doc/classes/InputEvent.xml @@ -7,8 +7,8 @@ Base class of all sort of input event. See [method Node._input]. </description> <tutorials> - <link title="InputEvent">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> - <link title="Viewport and canvas transforms">https://docs.godotengine.org/en/latest/tutorials/2d/2d_transforms.html</link> + <link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link> + <link title="Viewport and canvas transforms">$DOCS_URL/tutorials/2d/2d_transforms.html</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> diff --git a/doc/classes/InputEventAction.xml b/doc/classes/InputEventAction.xml index f09af1a34d..e9c280732a 100644 --- a/doc/classes/InputEventAction.xml +++ b/doc/classes/InputEventAction.xml @@ -7,7 +7,7 @@ Contains a generic action which can be targeted from several types of inputs. Actions can be created from the [b]Input Map[/b] tab in the [b]Project > Project Settings[/b] menu. See [method Node._input]. </description> <tutorials> - <link title="InputEvent: Actions">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html#actions</link> + <link title="InputEvent: Actions">$DOCS_URL/tutorials/inputs/inputevent.html#actions</link> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> diff --git a/doc/classes/InputEventJoypadButton.xml b/doc/classes/InputEventJoypadButton.xml index ff82913385..3e625c1003 100644 --- a/doc/classes/InputEventJoypadButton.xml +++ b/doc/classes/InputEventJoypadButton.xml @@ -7,7 +7,7 @@ Input event type for gamepad buttons. For gamepad analog sticks and joysticks, see [InputEventJoypadMotion]. </description> <tutorials> - <link title="InputEvent">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> + <link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link> </tutorials> <members> <member name="button_index" type="int" setter="set_button_index" getter="get_button_index" enum="JoyButton" default="0"> diff --git a/doc/classes/InputEventJoypadMotion.xml b/doc/classes/InputEventJoypadMotion.xml index 92161974ba..b3f9013553 100644 --- a/doc/classes/InputEventJoypadMotion.xml +++ b/doc/classes/InputEventJoypadMotion.xml @@ -7,7 +7,7 @@ Stores information about joystick motions. One [InputEventJoypadMotion] represents one axis at a time. </description> <tutorials> - <link title="InputEvent">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> + <link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link> </tutorials> <members> <member name="axis" type="int" setter="set_axis" getter="get_axis" enum="JoyAxis" default="0"> diff --git a/doc/classes/InputEventKey.xml b/doc/classes/InputEventKey.xml index 9cf6872655..8044bf5b99 100644 --- a/doc/classes/InputEventKey.xml +++ b/doc/classes/InputEventKey.xml @@ -7,18 +7,18 @@ Stores key presses on the keyboard. Supports key presses, key releases and [member echo] events. </description> <tutorials> - <link title="InputEvent">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> + <link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link> </tutorials> <methods> <method name="get_keycode_with_modifiers" qualifiers="const"> - <return type="int" /> + <return type="int" enum="Key" /> <description> Returns the keycode combined with modifier keys such as [kbd]Shift[/kbd] or [kbd]Alt[/kbd]. See also [InputEventWithModifiers]. To get a human-readable representation of the [InputEventKey] with modifiers, use [code]OS.get_keycode_string(event.get_keycode_with_modifiers())[/code] where [code]event[/code] is the [InputEventKey]. </description> </method> <method name="get_physical_keycode_with_modifiers" qualifiers="const"> - <return type="int" /> + <return type="int" enum="Key" /> <description> Returns the physical keycode combined with modifier keys such as [kbd]Shift[/kbd] or [kbd]Alt[/kbd]. See also [InputEventWithModifiers]. To get a human-readable representation of the [InputEventKey] with modifiers, use [code]OS.get_keycode_string(event.get_physical_keycode_with_modifiers())[/code] where [code]event[/code] is the [InputEventKey]. diff --git a/doc/classes/InputEventMouse.xml b/doc/classes/InputEventMouse.xml index b06068aff3..4878090996 100644 --- a/doc/classes/InputEventMouse.xml +++ b/doc/classes/InputEventMouse.xml @@ -7,10 +7,10 @@ Stores general mouse events information. </description> <tutorials> - <link title="InputEvent">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> + <link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link> </tutorials> <members> - <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" default="0"> + <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButton" default="0"> The mouse button mask identifier, one of or a bitwise combination of the [enum MouseButton] button masks. </member> <member name="global_position" type="Vector2" setter="set_global_position" getter="get_global_position" default="Vector2(0, 0)"> diff --git a/doc/classes/InputEventMouseButton.xml b/doc/classes/InputEventMouseButton.xml index dcfe0d6c71..699217525e 100644 --- a/doc/classes/InputEventMouseButton.xml +++ b/doc/classes/InputEventMouseButton.xml @@ -7,7 +7,7 @@ Contains mouse click information. See [method Node._input]. </description> <tutorials> - <link title="Mouse and input coordinates">https://docs.godotengine.org/en/latest/tutorials/inputs/mouse_and_input_coordinates.html</link> + <link title="Mouse and input coordinates">$DOCS_URL/tutorials/inputs/mouse_and_input_coordinates.html</link> </tutorials> <members> <member name="button_index" type="int" setter="set_button_index" getter="get_button_index" enum="MouseButton" default="0"> diff --git a/doc/classes/InputEventMouseMotion.xml b/doc/classes/InputEventMouseMotion.xml index 9a0156510e..bd1ae367c2 100644 --- a/doc/classes/InputEventMouseMotion.xml +++ b/doc/classes/InputEventMouseMotion.xml @@ -8,7 +8,7 @@ [b]Note:[/b] By default, this event is only emitted once per frame rendered at most. If you need more precise input reporting, call [method Input.set_use_accumulated_input] with [code]false[/code] to make events emitted as often as possible. If you use InputEventMouseMotion to draw lines, consider implementing [url=https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to avoid visible gaps in lines if the user is moving the mouse quickly. </description> <tutorials> - <link title="Mouse and input coordinates">https://docs.godotengine.org/en/latest/tutorials/inputs/mouse_and_input_coordinates.html</link> + <link title="Mouse and input coordinates">$DOCS_URL/tutorials/inputs/mouse_and_input_coordinates.html</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> <members> diff --git a/doc/classes/InputEventScreenDrag.xml b/doc/classes/InputEventScreenDrag.xml index f86b5f3b4d..19c26e3a98 100644 --- a/doc/classes/InputEventScreenDrag.xml +++ b/doc/classes/InputEventScreenDrag.xml @@ -7,7 +7,7 @@ Contains screen drag information. See [method Node._input]. </description> <tutorials> - <link title="InputEvent">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> + <link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link> </tutorials> <members> <member name="index" type="int" setter="set_index" getter="get_index" default="0"> diff --git a/doc/classes/InputEventScreenTouch.xml b/doc/classes/InputEventScreenTouch.xml index c731044c98..0694b2eabc 100644 --- a/doc/classes/InputEventScreenTouch.xml +++ b/doc/classes/InputEventScreenTouch.xml @@ -8,7 +8,7 @@ Stores multi-touch press/release information. Supports touch press, touch release and [member index] for multi-touch count and order. </description> <tutorials> - <link title="InputEvent">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> + <link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link> </tutorials> <members> <member name="index" type="int" setter="set_index" getter="get_index" default="0"> diff --git a/doc/classes/InputEventWithModifiers.xml b/doc/classes/InputEventWithModifiers.xml index 1b9212bf65..cd4a8aecd0 100644 --- a/doc/classes/InputEventWithModifiers.xml +++ b/doc/classes/InputEventWithModifiers.xml @@ -7,7 +7,7 @@ Contains keys events information with modifiers support like [kbd]Shift[/kbd] or [kbd]Alt[/kbd]. See [method Node._input]. </description> <tutorials> - <link title="InputEvent">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> + <link title="InputEvent">$DOCS_URL/tutorials/inputs/inputevent.html</link> </tutorials> <members> <member name="alt_pressed" type="bool" setter="set_alt_pressed" getter="is_alt_pressed" default="false"> diff --git a/doc/classes/InputMap.xml b/doc/classes/InputMap.xml index 855d5b5d71..24f220e892 100644 --- a/doc/classes/InputMap.xml +++ b/doc/classes/InputMap.xml @@ -7,7 +7,7 @@ Manages all [InputEventAction] which can be created/modified from the project settings menu [b]Project > Project Settings > Input Map[/b] or in code with [method add_action] and [method action_add_event]. See [method Node._input]. </description> <tutorials> - <link title="InputEvent: InputMap">https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html#inputmap</link> + <link title="InputEvent: InputMap">$DOCS_URL/tutorials/inputs/inputevent.html#inputmap</link> </tutorials> <methods> <method name="action_add_event"> diff --git a/doc/classes/JNISingleton.xml b/doc/classes/JNISingleton.xml index ce39e1f567..c887f72767 100644 --- a/doc/classes/JNISingleton.xml +++ b/doc/classes/JNISingleton.xml @@ -7,6 +7,6 @@ The JNISingleton is implemented only in the Android export. It's used to call methods and connect signals from an Android plugin written in Java or Kotlin. Methods and signals can be called and connected to the JNISingleton as if it is a Node. See [url=https://en.wikipedia.org/wiki/Java_Native_Interface]Java Native Interface - Wikipedia[/url] for more information. </description> <tutorials> - <link title="Creating Android plugins">https://docs.godotengine.org/en/latest/tutorials/platform/android/android_plugin.html#doc-android-plugin</link> + <link title="Creating Android plugins">$DOCS_URL/tutorials/platform/android/android_plugin.html#doc-android-plugin</link> </tutorials> </class> diff --git a/doc/classes/JavaScript.xml b/doc/classes/JavaScript.xml index 2bb2666df4..aeaf8ac1f5 100644 --- a/doc/classes/JavaScript.xml +++ b/doc/classes/JavaScript.xml @@ -5,10 +5,10 @@ </brief_description> <description> The JavaScript singleton is implemented only in the HTML5 export. It's used to access the browser's JavaScript context. This allows interaction with embedding pages or calling third-party JavaScript APIs. - [b]Note:[/b] This singleton can be disabled at build-time to improve security. By default, the JavaScript singleton is enabled. Official export templates also have the JavaScript singleton enabled. See [url=https://docs.godotengine.org/en/latest/development/compiling/compiling_for_web.html]Compiling for the Web[/url] in the documentation for more information. + [b]Note:[/b] This singleton can be disabled at build-time to improve security. By default, the JavaScript singleton is enabled. Official export templates also have the JavaScript singleton enabled. See [url=$DOCS_URL/development/compiling/compiling_for_web.html]Compiling for the Web[/url] in the documentation for more information. </description> <tutorials> - <link title="Exporting for the Web: Calling JavaScript from script">https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_web.html#calling-javascript-from-script</link> + <link title="Exporting for the Web: Calling JavaScript from script">$DOCS_URL/tutorials/export/exporting_for_web.html#calling-javascript-from-script</link> </tutorials> <methods> <method name="create_callback"> diff --git a/doc/classes/Light2D.xml b/doc/classes/Light2D.xml index 918e8a5c8a..039425b15f 100644 --- a/doc/classes/Light2D.xml +++ b/doc/classes/Light2D.xml @@ -8,7 +8,7 @@ [b]Note:[/b] Light2D can also be used as a mask. </description> <tutorials> - <link title="2D lights and shadows">https://docs.godotengine.org/en/latest/tutorials/2d/2d_lights_and_shadows.html</link> + <link title="2D lights and shadows">$DOCS_URL/tutorials/2d/2d_lights_and_shadows.html</link> </tutorials> <methods> <method name="get_height" qualifiers="const"> diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index dbda22d618..009ad1f609 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -7,7 +7,7 @@ Light3D is the [i]abstract[/i] base class for light nodes. As it can't be instantiated, it shouldn't be used directly. Other types of light nodes inherit from it. Light3D contains the common variables and parameters used for lighting. </description> <tutorials> - <link title="3D lights and shadows">https://docs.godotengine.org/en/latest/tutorials/3d/lights_and_shadows.html</link> + <link title="3D lights and shadows">$DOCS_URL/tutorials/3d/lights_and_shadows.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <methods> diff --git a/doc/classes/LightOccluder2D.xml b/doc/classes/LightOccluder2D.xml index ba795a29a1..d883128ac3 100644 --- a/doc/classes/LightOccluder2D.xml +++ b/doc/classes/LightOccluder2D.xml @@ -7,7 +7,7 @@ Occludes light cast by a Light2D, casting shadows. The LightOccluder2D must be provided with an [OccluderPolygon2D] in order for the shadow to be computed. </description> <tutorials> - <link title="2D lights and shadows">https://docs.godotengine.org/en/latest/tutorials/2d/2d_lights_and_shadows.html</link> + <link title="2D lights and shadows">$DOCS_URL/tutorials/2d/2d_lights_and_shadows.html</link> </tutorials> <members> <member name="occluder" type="OccluderPolygon2D" setter="set_occluder_polygon" getter="get_occluder_polygon"> diff --git a/doc/classes/LightmapGI.xml b/doc/classes/LightmapGI.xml index 0cdf9f820f..b7d4c93fd5 100644 --- a/doc/classes/LightmapGI.xml +++ b/doc/classes/LightmapGI.xml @@ -1,8 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="LightmapGI" inherits="VisualInstance3D" version="4.0"> <brief_description> + Computes and stores baked lightmaps for fast global illumination. </brief_description> <description> + The [LightmapGI] node is used to compute and store baked lightmaps. Lightmaps are used to provide high-quality indirect lighting with very little light leaking. [LightmapGI] can also provide rough reflections using spherical harmonics if [member directional] is enabled. Dynamic objects can receive indirect lighting thanks to [i]light probes[/i], which can be automatically placed by setting [member generate_probes_subdiv]. Additional lightmap probes can also be added by creating [LightmapProbe] nodes. The downside is that lightmaps are fully static and cannot be baked in an exported project. Baking a [LightmapGI] node is also slower compared to [VoxelGI]. + [b]Procedural generation:[/b] Lightmap baking functionality is only available in the editor. This means [LightmapGI] is not suited to procedurally generated or user-built levels. For procedurally generated or user-built levels, use [VoxelGI] or SDFGI instead (see [member Environment.sdfgi_enabled]). + [b]Performance:[/b] [LightmapGI] provides the best possible run-time performance for global illumination. It is suitable for low-end hardware including integrated graphics and mobile devices. </description> <tutorials> </tutorials> diff --git a/doc/classes/MeshInstance2D.xml b/doc/classes/MeshInstance2D.xml index c7b66c8ea3..6873edb3ae 100644 --- a/doc/classes/MeshInstance2D.xml +++ b/doc/classes/MeshInstance2D.xml @@ -7,7 +7,7 @@ Node used for displaying a [Mesh] in 2D. Can be constructed from an existing [Sprite2D] via a tool in the editor toolbar. Select "Sprite2D" then "Convert to Mesh2D", select settings in popup and press "Create Mesh2D". </description> <tutorials> - <link title="2D meshes">https://docs.godotengine.org/en/latest/tutorials/2d/2d_meshes.html</link> + <link title="2D meshes">$DOCS_URL/tutorials/2d/2d_meshes.html</link> </tutorials> <members> <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh"> diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml index 7890bbcc33..cf3b395b7b 100644 --- a/doc/classes/MultiMesh.xml +++ b/doc/classes/MultiMesh.xml @@ -10,8 +10,8 @@ Since instances may have any behavior, the AABB used for visibility must be provided by the user. </description> <tutorials> - <link title="Animating thousands of fish with MultiMeshInstance">https://docs.godotengine.org/en/latest/tutorials/performance/vertex_animation/animating_thousands_of_fish.html</link> - <link title="Optimization using MultiMeshes">https://docs.godotengine.org/en/latest/tutorials/performance/using_multimesh.html</link> + <link title="Animating thousands of fish with MultiMeshInstance">$DOCS_URL/tutorials/performance/vertex_animation/animating_thousands_of_fish.html</link> + <link title="Optimization using MultiMeshes">$DOCS_URL/tutorials/performance/using_multimesh.html</link> </tutorials> <methods> <method name="get_aabb" qualifiers="const"> diff --git a/doc/classes/MultiMeshInstance3D.xml b/doc/classes/MultiMeshInstance3D.xml index 158579e952..d78a045aca 100644 --- a/doc/classes/MultiMeshInstance3D.xml +++ b/doc/classes/MultiMeshInstance3D.xml @@ -8,9 +8,9 @@ This is useful to optimize the rendering of a high amount of instances of a given mesh (for example trees in a forest or grass strands). </description> <tutorials> - <link title="Animating thousands of fish with MultiMeshInstance">https://docs.godotengine.org/en/latest/tutorials/performance/vertex_animation/animating_thousands_of_fish.html</link> - <link title="Using MultiMeshInstance">https://docs.godotengine.org/en/latest/tutorials/3d/using_multi_mesh_instance.html</link> - <link title="Optimization using MultiMeshes">https://docs.godotengine.org/en/latest/tutorials/performance/using_multimesh.html</link> + <link title="Animating thousands of fish with MultiMeshInstance">$DOCS_URL/tutorials/performance/vertex_animation/animating_thousands_of_fish.html</link> + <link title="Using MultiMeshInstance">$DOCS_URL/tutorials/3d/using_multi_mesh_instance.html</link> + <link title="Optimization using MultiMeshes">$DOCS_URL/tutorials/performance/using_multimesh.html</link> </tutorials> <members> <member name="multimesh" type="MultiMesh" setter="set_multimesh" getter="get_multimesh"> diff --git a/doc/classes/MultiplayerPeer.xml b/doc/classes/MultiplayerPeer.xml index 67d3161aba..b7bd7bef36 100644 --- a/doc/classes/MultiplayerPeer.xml +++ b/doc/classes/MultiplayerPeer.xml @@ -9,7 +9,7 @@ [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android. </description> <tutorials> - <link title="High-level multiplayer">https://docs.godotengine.org/en/latest/tutorials/networking/high_level_multiplayer.html</link> + <link title="High-level multiplayer">$DOCS_URL/tutorials/networking/high_level_multiplayer.html</link> <link title="WebRTC Signaling Demo">https://godotengine.org/asset-library/asset/537</link> </tutorials> <methods> diff --git a/doc/classes/Mutex.xml b/doc/classes/Mutex.xml index a840cb2ec7..90c81686b1 100644 --- a/doc/classes/Mutex.xml +++ b/doc/classes/Mutex.xml @@ -7,7 +7,7 @@ A synchronization mutex (mutual exclusion). This is used to synchronize multiple [Thread]s, and is equivalent to a binary [Semaphore]. It guarantees that only one thread can ever acquire the lock at a time. A mutex can be used to protect a critical section; however, be careful to avoid deadlocks. </description> <tutorials> - <link title="Using multiple threads">https://docs.godotengine.org/en/latest/tutorials/performance/using_multiple_threads.html</link> + <link title="Using multiple threads">$DOCS_URL/tutorials/performance/using_multiple_threads.html</link> </tutorials> <methods> <method name="lock"> diff --git a/doc/classes/NavigationPolygon.xml b/doc/classes/NavigationPolygon.xml index 5b5b7c42ef..7ecdca8793 100644 --- a/doc/classes/NavigationPolygon.xml +++ b/doc/classes/NavigationPolygon.xml @@ -28,7 +28,7 @@ var polygon = NavigationPolygon.new() var vertices = PackedVector2Array([Vector2(0, 0), Vector2(0, 50), Vector2(50, 50), Vector2(50, 0)]) polygon.vertices = vertices - var indices = PackedInt32Array(0, 3, 1) + var indices = PackedInt32Array([0, 1, 2, 3]) polygon.add_polygon(indices) $NavigationRegion2D.navpoly = polygon [/gdscript] @@ -36,7 +36,7 @@ var polygon = new NavigationPolygon(); var vertices = new Vector2[] { new Vector2(0, 0), new Vector2(0, 50), new Vector2(50, 50), new Vector2(50, 0) }; polygon.Vertices = vertices; - var indices = new int[] { 0, 3, 1 }; + var indices = new int[] { 0, 1, 2, 3 }; polygon.AddPolygon(indices); GetNode<NavigationRegion2D>("NavigationRegion2D").Navpoly = polygon; [/csharp] diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 843db8c174..423002d058 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -17,7 +17,7 @@ [b]Networking with nodes:[/b] After connecting to a server (or making one, see [ENetMultiplayerPeer]), it is possible to use the built-in RPC (remote procedure call) system to communicate over the network. By calling [method rpc] with a method name, it will be called locally and in all connected peers (peers = clients and the server that accepts connections). To identify which node receives the RPC call, Godot will use its [NodePath] (make sure node names are the same on all peers). Also, take a look at the high-level networking tutorial and corresponding demos. </description> <tutorials> - <link title="Nodes and scenes">https://docs.godotengine.org/en/latest/getting_started/step_by_step/nodes_and_scenes.htmltml</link> + <link title="Nodes and scenes">$DOCS_URL/getting_started/step_by_step/nodes_and_scenes.html</link> <link title="All Demos">https://github.com/godotengine/godot-demo-projects/</link> </tutorials> <methods> @@ -228,11 +228,6 @@ If [code]include_internal[/code] is [code]false[/code], the returned array won't include internal children (see [code]internal[/code] parameter in [method add_child]). </description> </method> - <method name="get_editor_description" qualifiers="const"> - <return type="String" /> - <description> - </description> - </method> <method name="get_groups" qualifiers="const"> <return type="Array" /> <description> @@ -618,12 +613,6 @@ Sets the editable children state of [code]node[/code] relative to this node. This method is only intended for use with editor tooling. </description> </method> - <method name="set_editor_description"> - <return type="void" /> - <argument index="0" name="editor_description" type="String" /> - <description> - </description> - </method> <method name="set_multiplayer_authority"> <return type="void" /> <argument index="0" name="id" type="int" /> @@ -702,6 +691,9 @@ <member name="custom_multiplayer" type="MultiplayerAPI" setter="set_custom_multiplayer" getter="get_custom_multiplayer"> The override to the default [MultiplayerAPI]. Set to [code]null[/code] to use the default [SceneTree] one. </member> + <member name="editor_description" type="String" setter="set_editor_description" getter="get_editor_description" default=""""> + Add a custom description to a node. + </member> <member name="multiplayer" type="MultiplayerAPI" setter="" getter="get_multiplayer"> The [MultiplayerAPI] instance associated with this node. Either the [member custom_multiplayer], or the default SceneTree one (if inside tree). </member> diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml index ef5f9ee5c9..b8bf342680 100644 --- a/doc/classes/Node2D.xml +++ b/doc/classes/Node2D.xml @@ -7,7 +7,7 @@ A 2D game object, with a transform (position, rotation, and scale). All 2D nodes, including physics objects and sprites, inherit from Node2D. Use Node2D as a parent node to move, scale and rotate children in a 2D project. Also gives control of the node's render order. </description> <tutorials> - <link title="Custom drawing in 2D">https://docs.godotengine.org/en/latest/tutorials/2d/custom_drawing_in_2d.html</link> + <link title="Custom drawing in 2D">$DOCS_URL/tutorials/2d/custom_drawing_in_2d.html</link> <link title="All 2D Demos">https://github.com/godotengine/godot-demo-projects/tree/master/2d</link> </tutorials> <methods> diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml index 2ca664e2b5..1036c1fbcf 100644 --- a/doc/classes/Node3D.xml +++ b/doc/classes/Node3D.xml @@ -9,7 +9,7 @@ [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg2rad]. </description> <tutorials> - <link title="Introduction to 3D">https://docs.godotengine.org/en/latest/tutorials/3d/introduction_to_3d.html</link> + <link title="Introduction to 3D">$DOCS_URL/tutorials/3d/introduction_to_3d.html</link> <link title="All 3D Demos">https://github.com/godotengine/godot-demo-projects/tree/master/3d</link> </tutorials> <methods> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index f4d48f5db2..d06a06a2ee 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -133,7 +133,7 @@ </description> </method> <method name="find_keycode_from_string" qualifiers="const"> - <return type="int" /> + <return type="int" enum="Key" /> <argument index="0" name="string" type="String" /> <description> Returns the keycode of the given string (e.g. "Escape"). @@ -142,7 +142,7 @@ <method name="get_cache_dir" qualifiers="const"> <return type="String" /> <description> - Returns the [i]global[/i] cache data directory according to the operating system's standards. On desktop platforms, this path can be overridden by setting the [code]XDG_CACHE_HOME[/code] environment variable before starting the project. See [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_config_dir] and [method get_data_dir]. + Returns the [i]global[/i] cache data directory according to the operating system's standards. On desktop platforms, this path can be overridden by setting the [code]XDG_CACHE_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_config_dir] and [method get_data_dir]. Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path. </description> </method> @@ -179,7 +179,7 @@ <method name="get_config_dir" qualifiers="const"> <return type="String" /> <description> - Returns the [i]global[/i] user configuration directory according to the operating system's standards. On desktop platforms, this path can be overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable before starting the project. See [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_cache_dir] and [method get_data_dir]. + Returns the [i]global[/i] user configuration directory according to the operating system's standards. On desktop platforms, this path can be overridden by setting the [code]XDG_CONFIG_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_cache_dir] and [method get_data_dir]. Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path. </description> </method> @@ -194,7 +194,7 @@ <method name="get_data_dir" qualifiers="const"> <return type="String" /> <description> - Returns the [i]global[/i] user data directory according to the operating system's standards. On desktop platforms, this path can be overridden by setting the [code]XDG_DATA_HOME[/code] environment variable before starting the project. See [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_cache_dir] and [method get_config_dir]. + Returns the [i]global[/i] user data directory according to the operating system's standards. On desktop platforms, this path can be overridden by setting the [code]XDG_DATA_HOME[/code] environment variable before starting the project. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] in the documentation for more information. See also [method get_cache_dir] and [method get_config_dir]. Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path. </description> </method> @@ -222,7 +222,7 @@ </method> <method name="get_keycode_string" qualifiers="const"> <return type="String" /> - <argument index="0" name="code" type="int" /> + <argument index="0" name="code" type="int" enum="Key" /> <description> Returns the given keycode as a string (e.g. Return values: [code]"Escape"[/code], [code]"Shift+Escape"[/code]). See also [member InputEventKey.keycode] and [method InputEventKey.get_keycode_with_modifiers]. @@ -332,7 +332,7 @@ <return type="bool" /> <argument index="0" name="tag_name" type="String" /> <description> - Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on the platform, build, etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=https://docs.godotengine.org/en/latest/getting_started/workflow/export/feature_tags.html]Feature Tags[/url] documentation for more details. + Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on the platform, build, etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=$DOCS_URL/getting_started/workflow/export/feature_tags.html]Feature Tags[/url] documentation for more details. [b]Note:[/b] Tag names are case-sensitive. </description> </method> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 5a84364b92..df9da7561e 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -29,7 +29,7 @@ [b]Note:[/b] Unlike references to a [RefCounted], references to an Object stored in a variable can become invalid without warning. Therefore, it's recommended to use [RefCounted] for data classes instead of [Object]. </description> <tutorials> - <link title="When and how to avoid using nodes for everything">https://docs.godotengine.org/en/latest/tutorials/best_practices/node_alternatives.html</link> + <link title="When and how to avoid using nodes for everything">$DOCS_URL/tutorials/best_practices/node_alternatives.html</link> </tutorials> <methods> <method name="_get" qualifiers="virtual"> @@ -567,7 +567,7 @@ <description> Translates a message using translation catalogs configured in the Project Settings. An additional context could be used to specify the translation context. Only works if message translation is enabled (which it is by default), otherwise it returns the [code]message[/code] unchanged. See [method set_message_translation]. - See [url=https://docs.godotengine.org/en/latest/tutorials/i18n/internationalizing_games.html]Internationalizing games[/url] for examples of the usage of this method. + See [url=$DOCS_URL/tutorials/i18n/internationalizing_games.html]Internationalizing games[/url] for examples of the usage of this method. </description> </method> <method name="tr_n" qualifiers="const"> @@ -581,7 +581,7 @@ Only works if message translation is enabled (which it is by default), otherwise it returns the [code]message[/code] or [code]plural_message[/code] unchanged. See [method set_message_translation]. The number [code]n[/code] is the number or quantity of the plural object. It will be used to guide the translation system to fetch the correct plural form for the selected language. [b]Note:[/b] Negative and floating-point values usually represent physical entities for which singular and plural don't clearly apply. In such cases, use [method tr]. - See [url=https://docs.godotengine.org/en/latest/tutorials/i18n/localization_using_gettext.html]Localization using gettext[/url] for examples of the usage of this method. + See [url=$DOCS_URL/tutorials/i18n/localization_using_gettext.html]Localization using gettext[/url] for examples of the usage of this method. </description> </method> </methods> diff --git a/doc/classes/OmniLight3D.xml b/doc/classes/OmniLight3D.xml index e8d5977199..013ad0cc42 100644 --- a/doc/classes/OmniLight3D.xml +++ b/doc/classes/OmniLight3D.xml @@ -7,7 +7,7 @@ An Omnidirectional light is a type of [Light3D] that emits light in all directions. The light is attenuated by distance and this attenuation can be configured by changing its energy, radius, and attenuation parameters. </description> <tutorials> - <link title="3D lights and shadows">https://docs.godotengine.org/en/latest/tutorials/3d/lights_and_shadows.html</link> + <link title="3D lights and shadows">$DOCS_URL/tutorials/3d/lights_and_shadows.html</link> </tutorials> <members> <member name="omni_attenuation" type="float" setter="set_param" getter="get_param" default="1.0"> diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml index e108ab6298..08f9de53ca 100644 --- a/doc/classes/PhysicsBody2D.xml +++ b/doc/classes/PhysicsBody2D.xml @@ -7,7 +7,7 @@ PhysicsBody2D is an abstract base class for implementing a physics body. All *Body2D types inherit from it. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> </tutorials> <methods> <method name="add_collision_exception_with"> @@ -30,7 +30,7 @@ <argument index="2" name="safe_margin" type="float" default="0.08" /> <description> Moves the body along the vector [code]linear_velocity[/code]. This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. - The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision. + The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision when stopped, or when touching another body along the motion. If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given. [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody2D.collision/safe_margin] for more details). </description> @@ -50,8 +50,8 @@ <argument index="3" name="safe_margin" type="float" default="0.08" /> <description> Checks for collisions without moving the body. This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. - Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]linear_velocity[/code]. Returns [code]true[/code] if a collision would occur. - [code]collision[/code] is an optional object of type [KinematicCollision2D], which contains additional information about the collision (should there be one). + Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]linear_velocity[/code]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path. + [code]collision[/code] is an optional object of type [KinematicCollision2D], which contains additional information about the collision when stopped, or when touching another body along the motion. [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody2D.collision/safe_margin] for more details). </description> </method> diff --git a/doc/classes/PhysicsBody3D.xml b/doc/classes/PhysicsBody3D.xml index 8718c0caa2..3c52850eec 100644 --- a/doc/classes/PhysicsBody3D.xml +++ b/doc/classes/PhysicsBody3D.xml @@ -7,7 +7,7 @@ PhysicsBody3D is an abstract base class for implementing a physics body. All *Body types inherit from it. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> </tutorials> <methods> <method name="add_collision_exception_with"> @@ -38,7 +38,7 @@ <argument index="3" name="max_collisions" type="int" default="1" /> <description> Moves the body along the vector [code]linear_velocity[/code]. This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. - The body will stop if it collides. Returns a [KinematicCollision3D], which contains information about the collision. + The body will stop if it collides. Returns a [KinematicCollision3D], which contains information about the collision when stopped, or when touching another body along the motion. If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given. [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody3D.collision/safe_margin] for more details). [code]max_collisions[/code] allows to retrieve more than one collision result. @@ -68,8 +68,8 @@ <argument index="4" name="max_collisions" type="int" default="1" /> <description> Checks for collisions without moving the body. This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. - Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [code]linear_velocity[/code]. Returns [code]true[/code] if a collision would occur. - [code]collision[/code] is an optional object of type [KinematicCollision3D], which contains additional information about the collision (should there be one). + Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [code]linear_velocity[/code]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path. + [code]collision[/code] is an optional object of type [KinematicCollision3D], which contains additional information about the collision when stopped, or when touching another body along the motion. [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody3D.collision/safe_margin] for more details). [code]max_collisions[/code] allows to retrieve more than one collision result. </description> diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml index 3fe9cd776c..c33bd930be 100644 --- a/doc/classes/PhysicsDirectBodyState2D.xml +++ b/doc/classes/PhysicsDirectBodyState2D.xml @@ -7,8 +7,8 @@ Provides direct access to a physics body in the [PhysicsServer2D], allowing safe changes to physics properties. This object is passed via the direct state callback of dynamic bodies, and is intended for changing the direct state of that body. See [method RigidDynamicBody2D._integrate_forces]. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> - <link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> + <link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link> </tutorials> <methods> <method name="add_central_force"> diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml index efa9eb9cd6..7aa46dec2f 100644 --- a/doc/classes/PhysicsDirectBodyState3D.xml +++ b/doc/classes/PhysicsDirectBodyState3D.xml @@ -7,8 +7,8 @@ Provides direct access to a physics body in the [PhysicsServer3D], allowing safe changes to physics properties. This object is passed via the direct state callback of dynamic bodies, and is intended for changing the direct state of that body. See [method RigidDynamicBody3D._integrate_forces]. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> - <link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> + <link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link> </tutorials> <methods> <method name="add_central_force"> diff --git a/doc/classes/PhysicsDirectSpaceState2D.xml b/doc/classes/PhysicsDirectSpaceState2D.xml index 5892ef266f..fb82aaf36a 100644 --- a/doc/classes/PhysicsDirectSpaceState2D.xml +++ b/doc/classes/PhysicsDirectSpaceState2D.xml @@ -7,8 +7,8 @@ Direct access object to a space in the [PhysicsServer2D]. It's used mainly to do queries against objects and areas residing in a given space. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> - <link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> + <link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link> </tutorials> <methods> <method name="cast_motion"> @@ -64,7 +64,7 @@ Intersects a ray in a given space. Ray position and other parameters are defined through [PhysicsRayQueryParameters2D]. The returned object is a dictionary with the following fields: [code]collider[/code]: The colliding object. [code]collider_id[/code]: The colliding object's ID. - [code]normal[/code]: The object's surface normal at the intersection point. + [code]normal[/code]: The object's surface normal at the intersection point, or [code]Vector2(0, 0)[/code] if the ray starts inside the shape and [member PhysicsRayQueryParameters2D.hit_from_inside] is [code]true[/code]. [code]position[/code]: The intersection point. [code]rid[/code]: The intersecting object's [RID]. [code]shape[/code]: The shape index of the colliding shape. diff --git a/doc/classes/PhysicsDirectSpaceState3D.xml b/doc/classes/PhysicsDirectSpaceState3D.xml index 6a7fe46518..177fca9ce3 100644 --- a/doc/classes/PhysicsDirectSpaceState3D.xml +++ b/doc/classes/PhysicsDirectSpaceState3D.xml @@ -7,8 +7,8 @@ Direct access object to a space in the [PhysicsServer3D]. It's used mainly to do queries against objects and areas residing in a given space. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> - <link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> + <link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link> </tutorials> <methods> <method name="cast_motion"> @@ -65,7 +65,7 @@ Intersects a ray in a given space. Ray position and other parameters are defined through [PhysicsRayQueryParameters3D]. The returned object is a dictionary with the following fields: [code]collider[/code]: The colliding object. [code]collider_id[/code]: The colliding object's ID. - [code]normal[/code]: The object's surface normal at the intersection point. + [code]normal[/code]: The object's surface normal at the intersection point, or [code]Vector3(0, 0, 0)[/code] if the ray starts inside the shape and [member PhysicsRayQueryParameters3D.hit_from_inside] is [code]true[/code]. [code]position[/code]: The intersection point. [code]rid[/code]: The intersecting object's [RID]. [code]shape[/code]: The shape index of the colliding shape. diff --git a/doc/classes/PhysicsPointQueryParameters2D.xml b/doc/classes/PhysicsPointQueryParameters2D.xml index 6acd83b101..b4cb2145cf 100644 --- a/doc/classes/PhysicsPointQueryParameters2D.xml +++ b/doc/classes/PhysicsPointQueryParameters2D.xml @@ -19,7 +19,7 @@ If [code]true[/code], the query will take [PhysicsBody2D]s into account. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> - The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> The list of objects or object [RID]s that will be excluded from collisions. diff --git a/doc/classes/PhysicsPointQueryParameters3D.xml b/doc/classes/PhysicsPointQueryParameters3D.xml index 488f56872d..51e8f8c5b4 100644 --- a/doc/classes/PhysicsPointQueryParameters3D.xml +++ b/doc/classes/PhysicsPointQueryParameters3D.xml @@ -16,7 +16,7 @@ If [code]true[/code], the query will take [PhysicsBody3D]s into account. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> - The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> The list of objects or object [RID]s that will be excluded from collisions. diff --git a/doc/classes/PhysicsRayQueryParameters2D.xml b/doc/classes/PhysicsRayQueryParameters2D.xml index 0e99e47286..7e317c18bf 100644 --- a/doc/classes/PhysicsRayQueryParameters2D.xml +++ b/doc/classes/PhysicsRayQueryParameters2D.xml @@ -16,7 +16,7 @@ If [code]true[/code], the query will take [PhysicsBody2D]s into account. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> - The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> The list of objects or object [RID]s that will be excluded from collisions. @@ -24,6 +24,9 @@ <member name="from" type="Vector2" setter="set_from" getter="get_from" default="Vector2(0, 0)"> The starting point of the ray being queried for, in global coordinates. </member> + <member name="hit_from_inside" type="bool" setter="set_hit_from_inside" getter="is_hit_from_inside_enabled" default="false"> + If [code]true[/code], the query will detect a hit when starting inside shapes. In this case the collision normal will be [code]Vector2(0, 0)[/code]. Does not affect concave polygon shapes. + </member> <member name="to" type="Vector2" setter="set_to" getter="get_to" default="Vector2(0, 0)"> The ending point of the ray being queried for, in global coordinates. </member> diff --git a/doc/classes/PhysicsRayQueryParameters3D.xml b/doc/classes/PhysicsRayQueryParameters3D.xml index dbd09e5128..c378325a3c 100644 --- a/doc/classes/PhysicsRayQueryParameters3D.xml +++ b/doc/classes/PhysicsRayQueryParameters3D.xml @@ -16,7 +16,7 @@ If [code]true[/code], the query will take [PhysicsBody3D]s into account. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> - The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> The list of objects or object [RID]s that will be excluded from collisions. @@ -24,6 +24,12 @@ <member name="from" type="Vector3" setter="set_from" getter="get_from" default="Vector3(0, 0, 0)"> The starting point of the ray being queried for, in global coordinates. </member> + <member name="hit_back_faces" type="bool" setter="set_hit_back_faces" getter="is_hit_back_faces_enabled" default="true"> + If [code]true[/code], the query will hit back faces with concave polygon shapes with back face enabled or heightmap shapes. + </member> + <member name="hit_from_inside" type="bool" setter="set_hit_from_inside" getter="is_hit_from_inside_enabled" default="false"> + If [code]true[/code], the query will detect a hit when starting inside shapes. In this case the collision normal will be [code]Vector3(0, 0, 0)[/code]. Does not affect concave polygon shapes or heightmap shapes. + </member> <member name="to" type="Vector3" setter="set_to" getter="get_to" default="Vector3(0, 0, 0)"> The ending point of the ray being queried for, in global coordinates. </member> diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 7368fe06ab..868b58ea9f 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -98,13 +98,6 @@ Returns the space assigned to the area. </description> </method> - <method name="area_get_space_override_mode" qualifiers="const"> - <return type="int" enum="PhysicsServer2D.AreaSpaceOverrideMode" /> - <argument index="0" name="area" type="RID" /> - <description> - Returns the space override mode for the area. - </description> - </method> <method name="area_get_transform" qualifiers="const"> <return type="Transform2D" /> <argument index="0" name="area" type="RID" /> @@ -207,14 +200,6 @@ Assigns a space to the area. </description> </method> - <method name="area_set_space_override_mode"> - <return type="void" /> - <argument index="0" name="area" type="RID" /> - <argument index="1" name="mode" type="int" enum="PhysicsServer2D.AreaSpaceOverrideMode" /> - <description> - Sets the space override mode for the area. See [enum AreaSpaceOverrideMode] for a list of available modes. - </description> - </method> <method name="area_set_transform"> <return type="void" /> <argument index="0" name="area" type="RID" /> @@ -346,7 +331,7 @@ <return type="PhysicsDirectBodyState2D" /> <argument index="0" name="body" type="RID" /> <description> - Returns the [PhysicsDirectBodyState2D] of the body. + Returns the [PhysicsDirectBodyState2D] of the body. Returns [code]null[/code] if the body is destroyed or removed from the physics space. </description> </method> <method name="body_get_max_contacts_reported" qualifiers="const"> @@ -855,28 +840,37 @@ <constant name="SHAPE_CUSTOM" value="8" enum="ShapeType"> This constant is used internally by the engine. Any attempt to create this kind of shape results in an error. </constant> - <constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_OVERRIDE_MODE" value="0" enum="AreaParameter"> + Constant to set/get gravity override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. + </constant> + <constant name="AREA_PARAM_GRAVITY" value="1" enum="AreaParameter"> Constant to set/get gravity strength in an area. </constant> - <constant name="AREA_PARAM_GRAVITY_VECTOR" value="1" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_VECTOR" value="2" enum="AreaParameter"> Constant to set/get gravity vector/center in an area. </constant> - <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="2" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter"> Constant to set/get whether the gravity vector of an area is a direction, or a center point. </constant> - <constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="3" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="4" enum="AreaParameter"> Constant to set/get the falloff factor for point gravity of an area. The greater this value is, the faster the strength of gravity decreases with the square of distance. </constant> - <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="5" enum="AreaParameter"> This constant was used to set/get the falloff factor for point gravity. It has been superseded by [constant AREA_PARAM_GRAVITY_DISTANCE_SCALE]. </constant> - <constant name="AREA_PARAM_LINEAR_DAMP" value="5" enum="AreaParameter"> - Constant to set/get the linear dampening factor of an area. + <constant name="AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE" value="6" enum="AreaParameter"> + Constant to set/get linear damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. + </constant> + <constant name="AREA_PARAM_LINEAR_DAMP" value="7" enum="AreaParameter"> + Constant to set/get the linear damping factor of an area. + </constant> + <constant name="AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE" value="8" enum="AreaParameter"> + Constant to set/get angular damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. </constant> - <constant name="AREA_PARAM_ANGULAR_DAMP" value="6" enum="AreaParameter"> - Constant to set/get the angular dampening factor of an area. + <constant name="AREA_PARAM_ANGULAR_DAMP" value="9" enum="AreaParameter"> + Constant to set/get the angular damping factor of an area. </constant> - <constant name="AREA_PARAM_PRIORITY" value="7" enum="AreaParameter"> + <constant name="AREA_PARAM_PRIORITY" value="10" enum="AreaParameter"> Constant to set/get the priority (order of processing) of an area. </constant> <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode"> diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index 0f02cdf92f..dd8003be1d 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -85,13 +85,6 @@ Returns the space assigned to the area. </description> </method> - <method name="area_get_space_override_mode" qualifiers="const"> - <return type="int" enum="PhysicsServer3D.AreaSpaceOverrideMode" /> - <argument index="0" name="area" type="RID" /> - <description> - Returns the space override mode for the area. - </description> - </method> <method name="area_get_transform" qualifiers="const"> <return type="Transform3D" /> <argument index="0" name="area" type="RID" /> @@ -201,14 +194,6 @@ Assigns a space to the area. </description> </method> - <method name="area_set_space_override_mode"> - <return type="void" /> - <argument index="0" name="area" type="RID" /> - <argument index="1" name="mode" type="int" enum="PhysicsServer3D.AreaSpaceOverrideMode" /> - <description> - Sets the space override mode for the area. The modes are described in the [enum AreaSpaceOverrideMode] constants. - </description> - </method> <method name="area_set_transform"> <return type="void" /> <argument index="0" name="area" type="RID" /> @@ -320,7 +305,7 @@ <return type="PhysicsDirectBodyState3D" /> <argument index="0" name="body" type="RID" /> <description> - Returns the [PhysicsDirectBodyState3D] of the body. + Returns the [PhysicsDirectBodyState3D] of the body. Returns [code]null[/code] if the body is destroyed or removed from the physics space. </description> </method> <method name="body_get_max_contacts_reported" qualifiers="const"> @@ -1211,40 +1196,49 @@ <constant name="SHAPE_CUSTOM" value="10" enum="ShapeType"> This constant is used internally by the engine. Any attempt to create this kind of shape results in an error. </constant> - <constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_OVERRIDE_MODE" value="0" enum="AreaParameter"> + Constant to set/get gravity override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. + </constant> + <constant name="AREA_PARAM_GRAVITY" value="1" enum="AreaParameter"> Constant to set/get gravity strength in an area. </constant> - <constant name="AREA_PARAM_GRAVITY_VECTOR" value="1" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_VECTOR" value="2" enum="AreaParameter"> Constant to set/get gravity vector/center in an area. </constant> - <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="2" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter"> Constant to set/get whether the gravity vector of an area is a direction, or a center point. </constant> - <constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="3" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="4" enum="AreaParameter"> Constant to set/get the falloff factor for point gravity of an area. The greater this value is, the faster the strength of gravity decreases with the square of distance. </constant> - <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="4" enum="AreaParameter"> + <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="5" enum="AreaParameter"> This constant was used to set/get the falloff factor for point gravity. It has been superseded by [constant AREA_PARAM_GRAVITY_DISTANCE_SCALE]. </constant> - <constant name="AREA_PARAM_LINEAR_DAMP" value="5" enum="AreaParameter"> - Constant to set/get the linear dampening factor of an area. + <constant name="AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE" value="6" enum="AreaParameter"> + Constant to set/get linear damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. + </constant> + <constant name="AREA_PARAM_LINEAR_DAMP" value="7" enum="AreaParameter"> + Constant to set/get the linear damping factor of an area. + </constant> + <constant name="AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE" value="8" enum="AreaParameter"> + Constant to set/get angular damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. </constant> - <constant name="AREA_PARAM_ANGULAR_DAMP" value="6" enum="AreaParameter"> - Constant to set/get the angular dampening factor of an area. + <constant name="AREA_PARAM_ANGULAR_DAMP" value="9" enum="AreaParameter"> + Constant to set/get the angular damping factor of an area. </constant> - <constant name="AREA_PARAM_PRIORITY" value="7" enum="AreaParameter"> + <constant name="AREA_PARAM_PRIORITY" value="10" enum="AreaParameter"> Constant to set/get the priority (order of processing) of an area. </constant> - <constant name="AREA_PARAM_WIND_FORCE_MAGNITUDE" value="8" enum="AreaParameter"> + <constant name="AREA_PARAM_WIND_FORCE_MAGNITUDE" value="11" enum="AreaParameter"> Constant to set/get the magnitude of area-specific wind force. </constant> - <constant name="AREA_PARAM_WIND_SOURCE" value="9" enum="AreaParameter"> + <constant name="AREA_PARAM_WIND_SOURCE" value="12" enum="AreaParameter"> Constant to set/get the 3D vector that specifies the origin from which an area-specific wind blows. </constant> - <constant name="AREA_PARAM_WIND_DIRECTION" value="10" enum="AreaParameter"> + <constant name="AREA_PARAM_WIND_DIRECTION" value="13" enum="AreaParameter"> Constant to set/get the 3D vector that specifies the direction in which an area-specific wind blows. </constant> - <constant name="AREA_PARAM_WIND_ATTENUATION_FACTOR" value="11" enum="AreaParameter"> + <constant name="AREA_PARAM_WIND_ATTENUATION_FACTOR" value="14" enum="AreaParameter"> Constant to set/get the exponential rate at which wind force decreases with distance from its origin. </constant> <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode"> diff --git a/doc/classes/PhysicsShapeQueryParameters2D.xml b/doc/classes/PhysicsShapeQueryParameters2D.xml index abd19f1326..455f0b67dc 100644 --- a/doc/classes/PhysicsShapeQueryParameters2D.xml +++ b/doc/classes/PhysicsShapeQueryParameters2D.xml @@ -16,7 +16,7 @@ If [code]true[/code], the query will take [PhysicsBody2D]s into account. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> - The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> The list of objects or object [RID]s that will be excluded from collisions. diff --git a/doc/classes/PhysicsShapeQueryParameters3D.xml b/doc/classes/PhysicsShapeQueryParameters3D.xml index 2dffd5347a..789ce0a6c3 100644 --- a/doc/classes/PhysicsShapeQueryParameters3D.xml +++ b/doc/classes/PhysicsShapeQueryParameters3D.xml @@ -16,7 +16,7 @@ If [code]true[/code], the query will take [PhysicsBody3D]s into account. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="4294967295"> - The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers the query will detect (as a bitmask). By default, all collision layers are detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="exclude" type="Array" setter="set_exclude" getter="get_exclude" default="[]"> The list of objects or object [RID]s that will be excluded from collisions. diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml index a20607d0a7..37a8e00b49 100644 --- a/doc/classes/Plane.xml +++ b/doc/classes/Plane.xml @@ -7,7 +7,7 @@ Plane represents a normalized plane equation. Basically, "normal" is the normal of the plane (a,b,c normalized), and "d" is the distance from the origin to the plane (in the direction of "normal"). "Over" or "Above" the plane is considered the side of the plane towards where the normal is pointing. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> </tutorials> <constructors> <constructor name="Plane"> @@ -180,6 +180,8 @@ <return type="bool" /> <argument index="0" name="right" type="Plane" /> <description> + Returns [code]true[/code] if the planes are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator =="> @@ -191,16 +193,20 @@ <return type="bool" /> <argument index="0" name="right" type="Plane" /> <description> + Returns [code]true[/code] if the planes are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator unary+"> <return type="Plane" /> <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. </description> </operator> <operator name="operator unary-"> <return type="Plane" /> <description> + Returns the negative value of the [Plane]. This is the same as writing [code]Plane(-p.normal, -p.d)[/code]. This operation flips the direction of the normal vector and also flips the distance value, resulting in a Plane that is in the same place, but facing the opposite direction. </description> </operator> </operators> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 044325afbe..4eb3ef34b4 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -15,7 +15,7 @@ <return type="void" /> <argument index="0" name="label" type="String" /> <argument index="1" name="id" type="int" default="-1" /> - <argument index="2" name="accel" type="int" default="0" /> + <argument index="2" name="accel" type="int" enum="Key" default="0" /> <description> Adds a new checkable item with text [code]label[/code]. An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators. @@ -38,7 +38,7 @@ <argument index="0" name="texture" type="Texture2D" /> <argument index="1" name="label" type="String" /> <argument index="2" name="id" type="int" default="-1" /> - <argument index="3" name="accel" type="int" default="0" /> + <argument index="3" name="accel" type="int" enum="Key" default="0" /> <description> Adds a new checkable item with text [code]label[/code] and icon [code]texture[/code]. An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators. @@ -62,7 +62,7 @@ <argument index="0" name="texture" type="Texture2D" /> <argument index="1" name="label" type="String" /> <argument index="2" name="id" type="int" default="-1" /> - <argument index="3" name="accel" type="int" default="0" /> + <argument index="3" name="accel" type="int" enum="Key" default="0" /> <description> Adds a new item with text [code]label[/code] and icon [code]texture[/code]. An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators. @@ -73,7 +73,7 @@ <argument index="0" name="texture" type="Texture2D" /> <argument index="1" name="label" type="String" /> <argument index="2" name="id" type="int" default="-1" /> - <argument index="3" name="accel" type="int" default="0" /> + <argument index="3" name="accel" type="int" enum="Key" default="0" /> <description> Same as [method add_icon_check_item], but uses a radio check button. </description> @@ -103,7 +103,7 @@ <return type="void" /> <argument index="0" name="label" type="String" /> <argument index="1" name="id" type="int" default="-1" /> - <argument index="2" name="accel" type="int" default="0" /> + <argument index="2" name="accel" type="int" enum="Key" default="0" /> <description> Adds a new item with text [code]label[/code]. An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators. @@ -115,7 +115,7 @@ <argument index="1" name="max_states" type="int" /> <argument index="2" name="default_state" type="int" default="0" /> <argument index="3" name="id" type="int" default="-1" /> - <argument index="4" name="accel" type="int" default="0" /> + <argument index="4" name="accel" type="int" enum="Key" default="0" /> <description> Adds a new multistate item with text [code]label[/code]. Contrarily to normal binary items, multistate items can have more than two states, as defined by [code]max_states[/code]. Each press or activate of the item will increase the state by one. The default value is defined by [code]default_state[/code]. @@ -126,7 +126,7 @@ <return type="void" /> <argument index="0" name="label" type="String" /> <argument index="1" name="id" type="int" default="-1" /> - <argument index="2" name="accel" type="int" default="0" /> + <argument index="2" name="accel" type="int" enum="Key" default="0" /> <description> Adds a new radio check button with text [code]label[/code]. An [code]id[/code] can optionally be provided, as well as an accelerator ([code]accel[/code]). If no [code]id[/code] is provided, one will be created from the index. If no [code]accel[/code] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators. @@ -193,7 +193,7 @@ </description> </method> <method name="get_item_accelerator" qualifiers="const"> - <return type="int" /> + <return type="int" enum="Key" /> <argument index="0" name="idx" type="int" /> <description> Returns the accelerator of the item at index [code]idx[/code]. Accelerators are special combinations of keys that activate the item, no matter which control is focused. @@ -333,7 +333,7 @@ <method name="set_item_accelerator"> <return type="void" /> <argument index="0" name="idx" type="int" /> - <argument index="1" name="accel" type="int" /> + <argument index="1" name="accel" type="int" enum="Key" /> <description> Sets the accelerator of the item at index [code]idx[/code]. Accelerators are special combinations of keys that activate the item, no matter which control is focused. </description> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 205987f5be..cb26d8d445 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -6,8 +6,8 @@ <description> Contains global variables accessible from everywhere. Use [method get_setting], [method set_setting] or [method has_setting] to access them. Variables stored in [code]project.godot[/code] are also loaded into ProjectSettings, making this object very useful for reading custom game configuration options. When naming a Project Settings property, use the full path to the setting including the category. For example, [code]"application/config/name"[/code] for the project name. Category and property names can be viewed in the Project Settings dialog. - [b]Feature tags:[/b] Project settings can be overridden for specific platforms and configurations (debug, release, ...) using [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url]. - [b]Overriding:[/b] Any project setting can be overridden by creating a file named [code]override.cfg[/code] in the project's root directory. This can also be used in exported projects by placing this file in the same directory as the project binary. Overriding will still take the base project settings' [url=https://docs.godotengine.org/en/latest/tutorials/export/feature_tags.html]feature tags[/url] in account. Therefore, make sure to [i]also[/i] override the setting with the desired feature tags if you want them to override base project settings on all platforms and configurations. + [b]Feature tags:[/b] Project settings can be overridden for specific platforms and configurations (debug, release, ...) using [url=$DOCS_URL/tutorials/export/feature_tags.html]feature tags[/url]. + [b]Overriding:[/b] Any project setting can be overridden by creating a file named [code]override.cfg[/code] in the project's root directory. This can also be used in exported projects by placing this file in the same directory as the project binary. Overriding will still take the base project settings' [url=$DOCS_URL/tutorials/export/feature_tags.html]feature tags[/url] in account. Therefore, make sure to [i]also[/i] override the setting with the desired feature tags if you want them to override base project settings on all platforms and configurations. </description> <tutorials> <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link> @@ -87,7 +87,7 @@ <return type="String" /> <argument index="0" name="path" type="String" /> <description> - Returns the absolute, native OS path corresponding to the localized [code]path[/code] (starting with [code]res://[/code] or [code]user://[/code]). The returned path will vary depending on the operating system and user preferences. See [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]File paths in Godot projects[/url] to see what those paths convert to. See also [method localize_path]. + Returns the absolute, native OS path corresponding to the localized [code]path[/code] (starting with [code]res://[/code] or [code]user://[/code]). The returned path will vary depending on the operating system and user preferences. See [url=$DOCS_URL/tutorials/io/data_paths.html]File paths in Godot projects[/url] to see what those paths convert to. See also [method localize_path]. [b]Note:[/b] [method globalize_path] with [code]res://[/code] will not work in an exported project. Instead, prepend the executable's base directory to the path when running from an exported project: [codeblock] var path = "" @@ -219,7 +219,7 @@ </member> <member name="application/config/name" type="String" setter="" getter="" default=""""> The project's name. It is used both by the Project Manager and by exporters. The project name can be translated by translating its value in localization files. The window title will be set to match the project name automatically on startup. - [b]Note:[/b] Changing this value will also change the user data folder's path if [member application/config/use_custom_user_dir] is [code]false[/code]. After renaming the project, you will no longer be able to access existing data in [code]user://[/code] unless you rename the old folder to match the new project name. See [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]Data paths[/url] in the documentation for more information. + [b]Note:[/b] Changing this value will also change the user data folder's path if [member application/config/use_custom_user_dir] is [code]false[/code]. After renaming the project, you will no longer be able to access existing data in [code]user://[/code] unless you rename the old folder to match the new project name. See [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] in the documentation for more information. </member> <member name="application/config/project_settings_override" type="String" setter="" getter="" default=""""> Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code]. See "Overriding" in the [ProjectSettings] class description at the top for more information. @@ -289,7 +289,9 @@ Safer override for [member audio/driver/mix_rate] in the Web platform. Here [code]0[/code] means "let the browser choose" (since some browsers do not like forcing the mix rate). </member> <member name="audio/driver/output_latency" type="int" setter="" getter="" default="15"> - Output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware. + Specifies the preferred output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware. + Audio output latency may be constrained by the host operating system and audio hardware drivers. If the host can not provide the specified audio output latency then Godot will attempt to use the nearest latency allowed by the host. As such you should always use [method AudioServer.get_output_latency] to determine the actual audio output latency. + [b]Note:[/b] This setting is ignored on all versions of Windows prior to Windows 10. </member> <member name="audio/driver/output_latency.web" type="int" setter="" getter="" default="50"> Safer override for [member audio/driver/output_latency] in the Web platform, to avoid audio issues especially on mobile devices. @@ -493,7 +495,7 @@ </member> <member name="display/window/size/fullscreen" type="bool" setter="" getter="" default="false"> Sets the main window to full screen when the project starts. Note that this is not [i]exclusive[/i] fullscreen. On Windows and Linux, a borderless window is used to emulate fullscreen. On macOS, a new desktop is used to display the running project. - Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=https://docs.godotengine.org/en/latest/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode. + Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode. [b]Note:[/b] This setting is ignored on iOS, Android, and HTML5. </member> <member name="display/window/size/height" type="int" setter="" getter="" default="600"> @@ -1315,7 +1317,9 @@ </member> <member name="mono/profiler/enabled" type="bool" setter="" getter="" default="false"> </member> - <member name="mono/unhandled_exception_policy" type="int" setter="" getter="" default="0"> + <member name="mono/runtime/unhandled_exception_policy" type="int" setter="" getter="" default="0"> + The policy to use for unhandled Mono (C#) exceptions. The default "Terminate Application" exits the project as soon as an unhandled exception is thrown. "Log Error" logs an error message to the console instead, and will not interrupt the project execution when an unhandled exception is thrown. + [b]Note:[/b] The unhandled exception policy is always set to "Log Error" in the editor, which also includes C# [code]tool[/code] scripts running within the editor as well as editor plugin code. </member> <member name="navigation/2d/default_cell_size" type="int" setter="" getter="" default="10"> Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size]. diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml index 95b2316bf3..9fa2d9b60b 100644 --- a/doc/classes/Quaternion.xml +++ b/doc/classes/Quaternion.xml @@ -9,7 +9,7 @@ Due to its compactness and the way it is stored in memory, certain operations (obtaining axis-angle and performing SLERP, in particular) are more efficient and robust against floating-point errors. </description> <tutorials> - <link title="Using 3D transforms">https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html#interpolating-with-quaternions</link> + <link title="Using 3D transforms">$DOCS_URL/tutorials/3d/using_transforms.html#interpolating-with-quaternions</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <constructors> @@ -195,54 +195,64 @@ <return type="bool" /> <argument index="0" name="right" type="Quaternion" /> <description> + Returns [code]true[/code] if the quaternions are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="Quaternion" /> <argument index="0" name="right" type="Quaternion" /> <description> + Composes these two quaternions by multiplying them together. This has the effect of rotating the second quaternion (the child) by the first quaternion (the parent). </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="Vector3" /> <description> + Rotates (multiplies) the [Vector3] by the given [Quaternion]. </description> </operator> <operator name="operator *"> <return type="Quaternion" /> <argument index="0" name="right" type="float" /> <description> + Multiplies each component of the [Quaternion] by the given value. This operation is not meaningful on its own, but it can be used as a part of a larger expression. </description> </operator> <operator name="operator *"> <return type="Quaternion" /> <argument index="0" name="right" type="int" /> <description> + Multiplies each component of the [Quaternion] by the given value. This operation is not meaningful on its own, but it can be used as a part of a larger expression. </description> </operator> <operator name="operator +"> <return type="Quaternion" /> <argument index="0" name="right" type="Quaternion" /> <description> + Adds each component of the left [Quaternion] to the right [Quaternion]. This operation is not meaningful on its own, but it can be used as a part of a larger expression, such as approximating an intermediate rotation between two nearby rotations. </description> </operator> <operator name="operator -"> <return type="Quaternion" /> <argument index="0" name="right" type="Quaternion" /> <description> + Subtracts each component of the left [Quaternion] by the right [Quaternion]. This operation is not meaningful on its own, but it can be used as a part of a larger expression. </description> </operator> <operator name="operator /"> <return type="Quaternion" /> <argument index="0" name="right" type="float" /> <description> + Divides each component of the [Quaternion] by the given value. This operation is not meaningful on its own, but it can be used as a part of a larger expression. </description> </operator> <operator name="operator /"> <return type="Quaternion" /> <argument index="0" name="right" type="int" /> <description> + Divides each component of the [Quaternion] by the given value. This operation is not meaningful on its own, but it can be used as a part of a larger expression. </description> </operator> <operator name="operator =="> @@ -254,22 +264,27 @@ <return type="bool" /> <argument index="0" name="right" type="Quaternion" /> <description> + Returns [code]true[/code] if the quaternions are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator []"> <return type="float" /> <argument index="0" name="index" type="int" /> <description> + Access quaternion components using their index. [code]q[0][/code] is equivalent to [code]q.x[/code], [code]q[1][/code] is equivalent to [code]q.y[/code], [code]q[2][/code] is equivalent to [code]q.z[/code], and [code]q[3][/code] is equivalent to [code]q.w[/code]. </description> </operator> <operator name="operator unary+"> <return type="Quaternion" /> <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. </description> </operator> <operator name="operator unary-"> <return type="Quaternion" /> <description> + Returns the negative value of the [Quaternion]. This is the same as writing [code]Quaternion(-q.x, -q.y, -q.z, -q.w)[/code]. This operation results in a quaternion that represents the same rotation. </description> </operator> </operators> diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml index c011755df1..53d1554272 100644 --- a/doc/classes/RandomNumberGenerator.xml +++ b/doc/classes/RandomNumberGenerator.xml @@ -16,7 +16,7 @@ [b]Note:[/b] The default values of [member seed] and [member state] properties are pseudo-random, and changes when calling [method randomize]. The [code]0[/code] value documented here is a placeholder, and not the actual default seed. </description> <tutorials> - <link title="Random number generation">https://docs.godotengine.org/en/latest/tutorials/math/random_number_generation.html</link> + <link title="Random number generation">$DOCS_URL/tutorials/math/random_number_generation.html</link> </tutorials> <methods> <method name="randf"> diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml index 592c074a77..fe2885378a 100644 --- a/doc/classes/RayCast2D.xml +++ b/doc/classes/RayCast2D.xml @@ -11,7 +11,7 @@ RayCast2D calculates intersection every physics frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between physics frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast. </description> <tutorials> - <link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link> + <link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link> </tutorials> <methods> <method name="add_exception"> @@ -63,7 +63,7 @@ <method name="get_collision_normal" qualifiers="const"> <return type="Vector2" /> <description> - Returns the normal of the intersecting object's shape at the collision point. + Returns the normal of the intersecting object's shape at the collision point, or [code]Vector2(0, 0)[/code] if the ray starts inside the shape and [member hit_from_inside] is [code]true[/code]. </description> </method> <method name="get_collision_point" qualifiers="const"> @@ -110,7 +110,7 @@ If [code]true[/code], collision with [PhysicsBody2D]s will be reported. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> If [code]true[/code], collisions will be reported. @@ -118,6 +118,9 @@ <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> If [code]true[/code], the parent node will be excluded from collision detection. </member> + <member name="hit_from_inside" type="bool" setter="set_hit_from_inside" getter="is_hit_from_inside_enabled" default="false"> + If [code]true[/code], the ray will detect a hit when starting inside shapes. In this case the collision normal will be [code]Vector2(0, 0)[/code]. Does not affect concave polygon shapes. + </member> <member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2(0, 50)"> The ray's destination point, relative to the RayCast's [code]position[/code]. </member> diff --git a/doc/classes/RayCast3D.xml b/doc/classes/RayCast3D.xml index c7253e81c4..8abd3f84b1 100644 --- a/doc/classes/RayCast3D.xml +++ b/doc/classes/RayCast3D.xml @@ -11,7 +11,7 @@ RayCast3D calculates intersection every physics frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between physics frames (or during the same frame), use [method force_raycast_update] after adjusting the raycast. </description> <tutorials> - <link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link> + <link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> <methods> @@ -65,7 +65,7 @@ <method name="get_collision_normal" qualifiers="const"> <return type="Vector3" /> <description> - Returns the normal of the intersecting object's shape at the collision point. + Returns the normal of the intersecting object's shape at the collision point, or [code]Vector3(0, 0, 0)[/code] if the ray starts inside the shape and [member hit_from_inside] is [code]true[/code]. </description> </method> <method name="get_collision_point" qualifiers="const"> @@ -112,7 +112,7 @@ If [code]true[/code], collision with [PhysicsBody3D]s will be reported. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="debug_shape_custom_color" type="Color" setter="set_debug_shape_custom_color" getter="get_debug_shape_custom_color" default="Color(0, 0, 0, 1)"> The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [RayCast3D] is colliding with something. @@ -127,6 +127,9 @@ <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> If [code]true[/code], collisions will be ignored for this RayCast3D's immediate parent. </member> + <member name="hit_from_inside" type="bool" setter="set_hit_from_inside" getter="is_hit_from_inside_enabled" default="false"> + If [code]true[/code], the ray will detect a hit when starting inside shapes. In this case the collision normal will be [code]Vector3(0, 0, 0)[/code]. Does not affect shapes with no volume like concave polygon or heightmap. + </member> <member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3(0, -1, 0)"> The ray's destination point, relative to the RayCast's [code]position[/code]. </member> diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml index 01bec10ed8..4dc3859ca5 100644 --- a/doc/classes/Rect2.xml +++ b/doc/classes/Rect2.xml @@ -9,9 +9,9 @@ The 3D counterpart to [Rect2] is [AABB]. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Vector math">https://docs.godotengine.org/en/latest/tutorials/math/vector_math.html</link> - <link title="Advanced vector math">https://docs.godotengine.org/en/latest/tutorials/math/vectors_advanced.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Vector math">$DOCS_URL/tutorials/math/vector_math.html</link> + <link title="Advanced vector math">$DOCS_URL/tutorials/math/vectors_advanced.html</link> </tutorials> <constructors> <constructor name="Rect2"> @@ -71,7 +71,22 @@ <return type="Rect2" /> <argument index="0" name="to" type="Vector2" /> <description> - Returns this [Rect2] expanded to include a given point. + Returns a copy of this [Rect2] expanded to include a given point. + [b]Example:[/b] + [codeblocks] + [gdscript] + # position (-3, 2), size (1, 1) + var rect = Rect2(Vector2(-3, 2), Vector2(1, 1)) + # position (-3, -1), size (3, 4), so we fit both rect and Vector2(0, -1) + var rect2 = rect.expand(Vector2(0, -1)) + [/gdscript] + [csharp] + # position (-3, 2), size (1, 1) + var rect = new Rect2(new Vector2(-3, 2), new Vector2(1, 1)); + # position (-3, -1), size (3, 4), so we fit both rect and Vector2(0, -1) + var rect2 = rect.Expand(new Vector2(0, -1)); + [/csharp] + [/codeblocks] </description> </method> <method name="get_area" qualifiers="const"> @@ -121,7 +136,8 @@ <return type="bool" /> <argument index="0" name="point" type="Vector2" /> <description> - Returns [code]true[/code] if the [Rect2] contains a point. + Returns [code]true[/code] if the [Rect2] contains a point. By convention, the right and bottom edges of the [Rect2] are considered exclusive, so points on these edges are [b]not[/b] included. + [b]Note:[/b] This method is not reliable for [Rect2] with a [i]negative size[/i]. Use [method abs] to get a positive sized equivalent rectangle to check for contained points. </description> </method> <method name="intersection" qualifiers="const"> @@ -178,12 +194,15 @@ <return type="bool" /> <argument index="0" name="right" type="Rect2" /> <description> + Returns [code]true[/code] if the rectangles are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="Rect2" /> <argument index="0" name="right" type="Transform2D" /> <description> + Inversely transforms (multiplies) the [Rect2] by the given [Transform2D] transformation matrix. </description> </operator> <operator name="operator =="> @@ -195,6 +214,8 @@ <return type="bool" /> <argument index="0" name="right" type="Rect2" /> <description> + Returns [code]true[/code] if the rectangles are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> </operators> diff --git a/doc/classes/Rect2i.xml b/doc/classes/Rect2i.xml index fc27c64fa5..d66b589ec1 100644 --- a/doc/classes/Rect2i.xml +++ b/doc/classes/Rect2i.xml @@ -8,8 +8,8 @@ It uses integer coordinates. If you need floating-point coordinates, use [Rect2] instead. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Vector math">https://docs.godotengine.org/en/latest/tutorials/math/vector_math.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Vector math">$DOCS_URL/tutorials/math/vector_math.html</link> </tutorials> <constructors> <constructor name="Rect2i"> @@ -69,7 +69,21 @@ <return type="Rect2i" /> <argument index="0" name="to" type="Vector2i" /> <description> - Returns this [Rect2i] expanded to include a given point. + Returns a copy of this [Rect2i] expanded to include a given point. + [codeblocks] + [gdscript] + # position (-3, 2), size (1, 1) + var rect = Rect2i(Vector2i(-3, 2), Vector2i(1, 1)) + # position (-3, -1), size (3, 4), so we fit both rect and Vector2i(0, -1) + var rect2 = rect.expand(Vector2i(0, -1)) + [/gdscript] + [csharp] + # position (-3, 2), size (1, 1) + var rect = new Rect2i(new Vector2i(-3, 2), new Vector2i(1, 1)); + # position (-3, -1), size (3, 4), so we fit both rect and Vector2i(0, -1) + var rect2 = rect.Expand(new Vector2i(0, -1)); + [/csharp] + [/codeblocks] </description> </method> <method name="get_area" qualifiers="const"> @@ -120,7 +134,8 @@ <return type="bool" /> <argument index="0" name="point" type="Vector2i" /> <description> - Returns [code]true[/code] if the [Rect2i] contains a point. + Returns [code]true[/code] if the [Rect2i] contains a point. By convention, the right and bottom edges of the [Rect2i] are considered exclusive, so points on these edges are [b]not[/b] included. + [b]Note:[/b] This method is not reliable for [Rect2i] with a [i]negative size[/i]. Use [method abs] to get a positive sized equivalent rectangle to check for contained points. </description> </method> <method name="intersection" qualifiers="const"> @@ -169,6 +184,7 @@ <return type="bool" /> <argument index="0" name="right" type="Rect2i" /> <description> + Returns [code]true[/code] if the rectangles are not equal. </description> </operator> <operator name="operator =="> @@ -180,6 +196,7 @@ <return type="bool" /> <argument index="0" name="right" type="Rect2i" /> <description> + Returns [code]true[/code] if the rectangles are equal. </description> </operator> </operators> diff --git a/doc/classes/RefCounted.xml b/doc/classes/RefCounted.xml index de314fbcb7..378df6f155 100644 --- a/doc/classes/RefCounted.xml +++ b/doc/classes/RefCounted.xml @@ -10,7 +10,7 @@ [b]Note:[/b] In C#, reference-counted objects will not be freed instantly after they are no longer in use. Instead, garbage collection will run periodically and will free reference-counted objects that are no longer in use. This means that unused ones will linger on for a while before being removed. </description> <tutorials> - <link title="When and how to avoid using nodes for everything">https://docs.godotengine.org/en/latest/tutorials/best_practices/node_alternatives.html</link> + <link title="When and how to avoid using nodes for everything">$DOCS_URL/tutorials/best_practices/node_alternatives.html</link> </tutorials> <methods> <method name="init_ref"> diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml index 7f2bd118d6..8bf8534334 100644 --- a/doc/classes/ReflectionProbe.xml +++ b/doc/classes/ReflectionProbe.xml @@ -8,7 +8,7 @@ The [ReflectionProbe] is used to create high-quality reflections at the cost of performance. It can be combined with [VoxelGI]s and Screen Space Reflections to achieve high quality reflections. [ReflectionProbe]s render all objects within their [member cull_mask], so updating them can be quite expensive. It is best to update them once with the important static objects and then leave them. </description> <tutorials> - <link title="Reflection probes">https://docs.godotengine.org/en/latest/tutorials/3d/reflection_probes.html</link> + <link title="Reflection probes">$DOCS_URL/tutorials/3d/reflection_probes.html</link> </tutorials> <members> <member name="ambient_color" type="Color" setter="set_ambient_color" getter="get_ambient_color" default="Color(0, 0, 0, 1)"> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 68b79ff749..7f4d5cf1cd 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -15,7 +15,7 @@ In 2D, all visible objects are some form of canvas item. In order to be visible, a canvas item needs to be the child of a canvas attached to a viewport, or it needs to be the child of another canvas item that is eventually attached to the canvas. </description> <tutorials> - <link title="Optimization using Servers">https://docs.godotengine.org/en/latest/tutorials/performance/using_servers.html</link> + <link title="Optimization using Servers">$DOCS_URL/tutorials/performance/using_servers.html</link> </tutorials> <methods> <method name="bake_render_uv2"> @@ -2661,8 +2661,10 @@ <return type="RID" /> <argument index="0" name="shader" type="RID" /> <argument index="1" name="param" type="StringName" /> + <argument index="2" name="index" type="int" default="0" /> <description> Returns a default texture from a shader searched by name. + [b]Note:[/b] If the sampler array is used use [code]index[/code] to access the specified texture. </description> </method> <method name="shader_get_param_default" qualifiers="const"> @@ -2684,8 +2686,10 @@ <argument index="0" name="shader" type="RID" /> <argument index="1" name="param" type="StringName" /> <argument index="2" name="texture" type="RID" /> + <argument index="3" name="index" type="int" default="0" /> <description> Sets a shader's default texture. Overwrites the texture given by name. + [b]Note:[/b] If the sampler array is used use [code]index[/code] to access the specified texture. </description> </method> <method name="shadows_quality_set"> diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml index 327183893b..02d1c7e97d 100644 --- a/doc/classes/Resource.xml +++ b/doc/classes/Resource.xml @@ -8,8 +8,8 @@ [b]Note:[/b] In C#, resources will not be freed instantly after they are no longer in use. Instead, garbage collection will run periodically and will free resources that are no longer in use. This means that unused resources will linger on for a while before being removed. </description> <tutorials> - <link title="Resources">https://docs.godotengine.org/en/latest/tutorials/scripting/resources.html</link> - <link title="When and how to avoid using nodes for everything">https://docs.godotengine.org/en/latest/tutorials/best_practices/node_alternatives.html</link> + <link title="Resources">$DOCS_URL/tutorials/scripting/resources.html</link> + <link title="When and how to avoid using nodes for everything">$DOCS_URL/tutorials/best_practices/node_alternatives.html</link> </tutorials> <methods> <method name="duplicate" qualifiers="const"> diff --git a/doc/classes/ResourceImporter.xml b/doc/classes/ResourceImporter.xml index 9f551ad1d2..f20b55fbc8 100644 --- a/doc/classes/ResourceImporter.xml +++ b/doc/classes/ResourceImporter.xml @@ -7,7 +7,7 @@ This is the base class for the resource importers implemented in core. To implement your own resource importers using editor plugins, see [EditorImportPlugin]. </description> <tutorials> - <link title="Import plugins">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/import_plugins.html</link> + <link title="Import plugins">$DOCS_URL/tutorials/plugins/editor/import_plugins.html</link> </tutorials> <constants> <constant name="IMPORT_ORDER_DEFAULT" value="0" enum="ImportOrder"> diff --git a/doc/classes/RichTextEffect.xml b/doc/classes/RichTextEffect.xml index 62323722f7..4329ccfdf5 100644 --- a/doc/classes/RichTextEffect.xml +++ b/doc/classes/RichTextEffect.xml @@ -19,7 +19,7 @@ [b]Note:[/b] As soon as a [RichTextLabel] contains at least one [RichTextEffect], it will continuously process the effect unless the project is paused. This may impact battery life negatively. </description> <tutorials> - <link title="BBCode in RichTextLabel">https://docs.godotengine.org/en/latest/tutorials/ui/bbcode_in_richtextlabel.html</link> + <link title="BBCode in RichTextLabel">$DOCS_URL/tutorials/ui/bbcode_in_richtextlabel.html</link> <link title="RichTextEffect test project (third-party)">https://github.com/Eoin-ONeill-Yokai/Godot-Rich-Text-Effect-Test-Project</link> </tutorials> <methods> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 3255c748b7..6bfaca8928 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -11,7 +11,7 @@ [b]Note:[/b] Unlike [Label], RichTextLabel doesn't have a [i]property[/i] to horizontally align text to the center. Instead, enable [member bbcode_enabled] and surround the text in a [code][center][/code] tag as follows: [code][center]Example[/center][/code]. There is currently no built-in way to vertically align text either, but this can be emulated by relying on anchors/containers and the [member fit_content_height] property. </description> <tutorials> - <link title="BBCode in RichTextLabel">https://docs.godotengine.org/en/latest/tutorials/ui/bbcode_in_richtextlabel.html</link> + <link title="BBCode in RichTextLabel">$DOCS_URL/tutorials/ui/bbcode_in_richtextlabel.html</link> <link title="GUI Rich Text/BBcode Demo">https://godotengine.org/asset-library/asset/132</link> <link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link> </tutorials> diff --git a/doc/classes/RigidDynamicBody3D.xml b/doc/classes/RigidDynamicBody3D.xml index ba9acdf4bf..c75055e0df 100644 --- a/doc/classes/RigidDynamicBody3D.xml +++ b/doc/classes/RigidDynamicBody3D.xml @@ -10,7 +10,7 @@ If you need to override the default physics behavior, you can write a custom force integration function. See [member custom_integrator]. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> <link title="3D Truck Town Demo">https://godotengine.org/asset-library/asset/524</link> <link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link> </tutorials> diff --git a/doc/classes/RootMotionView.xml b/doc/classes/RootMotionView.xml index 5db13de44f..203a48996f 100644 --- a/doc/classes/RootMotionView.xml +++ b/doc/classes/RootMotionView.xml @@ -8,7 +8,7 @@ [b]Note:[/b] [RootMotionView] is only visible in the editor. It will be hidden automatically in the running project, and will also be converted to a plain [Node] in the running project. This means a script attached to a [RootMotionView] node [i]must[/i] have [code]extends Node[/code] instead of [code]extends RootMotionView[/code]. Additionally, it must not be a [code]@tool[/code] script. </description> <tutorials> - <link title="Using AnimationTree - Root motion">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html#root-motion</link> + <link title="Using AnimationTree - Root motion">$DOCS_URL/tutorials/animation/animation_tree.html#root-motion</link> </tutorials> <members> <member name="animation_path" type="NodePath" setter="set_animation_path" getter="get_animation_path"> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 6d0ec44b69..c1dca44896 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -9,8 +9,8 @@ [SceneTree] is the default [MainLoop] implementation used by scenes, and is thus in charge of the game loop. </description> <tutorials> - <link title="SceneTree">https://docs.godotengine.org/en/latest/tutorials/scripting/scene_tree.html</link> - <link title="Multiple resolutions">https://docs.godotengine.org/en/latest/tutorials/rendering/multiple_resolutions.html</link> + <link title="SceneTree">$DOCS_URL/tutorials/scripting/scene_tree.html</link> + <link title="Multiple resolutions">$DOCS_URL/tutorials/rendering/multiple_resolutions.html</link> </tutorials> <methods> <method name="call_group" qualifiers="vararg"> diff --git a/doc/classes/Script.xml b/doc/classes/Script.xml index 7c59e87848..ab88bdaa73 100644 --- a/doc/classes/Script.xml +++ b/doc/classes/Script.xml @@ -8,7 +8,7 @@ The [code]new[/code] method of a script subclass creates a new instance. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes. </description> <tutorials> - <link title="Scripting documentation index">https://docs.godotengine.org/en/latest/tutorials/scripting/index.html</link> + <link title="Scripting documentation index">$DOCS_URL/tutorials/scripting/index.html</link> </tutorials> <methods> <method name="can_instantiate" qualifiers="const"> diff --git a/doc/classes/Semaphore.xml b/doc/classes/Semaphore.xml index 9ff9cc0c87..9e1d8012b7 100644 --- a/doc/classes/Semaphore.xml +++ b/doc/classes/Semaphore.xml @@ -7,7 +7,7 @@ A synchronization semaphore which can be used to synchronize multiple [Thread]s. Initialized to zero on creation. Be careful to avoid deadlocks. For a binary version, see [Mutex]. </description> <tutorials> - <link title="Using multiple threads">https://docs.godotengine.org/en/latest/tutorials/performance/using_multiple_threads.html</link> + <link title="Using multiple threads">$DOCS_URL/tutorials/performance/using_multiple_threads.html</link> </tutorials> <methods> <method name="post"> diff --git a/doc/classes/Shader.xml b/doc/classes/Shader.xml index 99e38e969d..d81b4bc372 100644 --- a/doc/classes/Shader.xml +++ b/doc/classes/Shader.xml @@ -7,15 +7,17 @@ This class allows you to define a custom shader program that can be used by a [ShaderMaterial]. Shaders allow you to write your own custom behavior for rendering objects or updating particle information. For a detailed explanation and usage, please see the tutorials linked below. </description> <tutorials> - <link title="Shaders documentation index">https://docs.godotengine.org/en/latest/tutorials/shaders/index.html</link> + <link title="Shaders documentation index">$DOCS_URL/tutorials/shaders/index.html</link> </tutorials> <methods> <method name="get_default_texture_param" qualifiers="const"> <return type="Texture2D" /> <argument index="0" name="param" type="StringName" /> + <argument index="1" name="index" type="int" default="0" /> <description> Returns the texture that is set as default for the specified parameter. [b]Note:[/b] [code]param[/code] must match the name of the uniform in the code exactly. + [b]Note:[/b] If the sampler array is used use [code]index[/code] to access the specified texture. </description> </method> <method name="get_mode" qualifiers="const"> @@ -36,9 +38,11 @@ <return type="void" /> <argument index="0" name="param" type="StringName" /> <argument index="1" name="texture" type="Texture2D" /> + <argument index="2" name="index" type="int" default="0" /> <description> Sets the default texture to be used with a texture uniform. The default is used if a texture is not set in the [ShaderMaterial]. [b]Note:[/b] [code]param[/code] must match the name of the uniform in the code exactly. + [b]Note:[/b] If the sampler array is used use [code]index[/code] to access the specified texture. </description> </method> </methods> diff --git a/doc/classes/ShaderMaterial.xml b/doc/classes/ShaderMaterial.xml index d5fc3fd210..04f0fac104 100644 --- a/doc/classes/ShaderMaterial.xml +++ b/doc/classes/ShaderMaterial.xml @@ -7,7 +7,7 @@ A material that uses a custom [Shader] program to render either items to screen or process particles. You can create multiple materials for the same shader but configure different values for the uniforms defined in the shader. </description> <tutorials> - <link title="Shaders documentation index">https://docs.godotengine.org/en/latest/tutorials/shaders/index.html</link> + <link title="Shaders documentation index">$DOCS_URL/tutorials/shaders/index.html</link> </tutorials> <methods> <method name="get_shader_param" qualifiers="const"> diff --git a/doc/classes/Shape2D.xml b/doc/classes/Shape2D.xml index 04f91d19da..9746519173 100644 --- a/doc/classes/Shape2D.xml +++ b/doc/classes/Shape2D.xml @@ -7,7 +7,7 @@ Base class for all 2D shapes. All 2D shape types inherit from this. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> </tutorials> <methods> <method name="collide"> diff --git a/doc/classes/Shape3D.xml b/doc/classes/Shape3D.xml index 96f8833486..67af52768f 100644 --- a/doc/classes/Shape3D.xml +++ b/doc/classes/Shape3D.xml @@ -7,7 +7,7 @@ Base class for all 3D shape resources. Nodes that inherit from this can be used as shapes for a [PhysicsBody3D] or [Area3D] objects. </description> <tutorials> - <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> + <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> </tutorials> <methods> <method name="get_debug_mesh"> diff --git a/doc/classes/ShapeCast2D.xml b/doc/classes/ShapeCast2D.xml new file mode 100644 index 0000000000..74ebafe069 --- /dev/null +++ b/doc/classes/ShapeCast2D.xml @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ShapeCast2D" inherits="Node2D" version="4.0"> + <brief_description> + Node for physics collision sweep and immediate overlap queries. Similar to the [RayCast2D] node. + </brief_description> + <description> + Shape casting allows to detect collision objects by sweeping the [member shape] along the cast direction determined by [member target_position] (useful for things like beam weapons). + Immediate collision overlaps can be done with the [member target_position] set to [code]Vector2(0, 0)[/code] and by calling [method force_shapecast_update] within the same [b]physics_frame[/b]. This also helps to overcome some limitations of [Area2D] when used as a continuous detection area, often requiring waiting a couple of frames before collision information is available to [Area2D] nodes, and when using the signals creates unnecessary complexity. + The node can detect multiple collision objects, but usually the first detected collision + [b]Note:[/b] shape casting is more computationally expensive compared to ray casting. + </description> + <tutorials> + </tutorials> + <methods> + <method name="add_exception"> + <return type="void" /> + <argument index="0" name="node" type="Object" /> + <description> + Adds a collision exception so the shape does not report collisions with the specified node. + </description> + </method> + <method name="add_exception_rid"> + <return type="void" /> + <argument index="0" name="rid" type="RID" /> + <description> + Adds a collision exception so the shape does not report collisions with the specified [RID]. + </description> + </method> + <method name="clear_exceptions"> + <return type="void" /> + <description> + Removes all collision exceptions for this shape. + </description> + </method> + <method name="force_shapecast_update"> + <return type="void" /> + <description> + Updates the collision information for the shape. Use this method to update the collision information immediately instead of waiting for the next [code]_physics_process[/code] call, for example if the shape or its parent has changed state. + [b]Note:[/b] [code]enabled == true[/code] is not required for this to work. + </description> + </method> + <method name="get_closest_collision_safe_fraction" qualifiers="const"> + <return type="float" /> + <description> + The fraction of the motion (between 0 and 1) of how far the shape can move without triggering a collision. The motion is determined by [member target_position]. + </description> + </method> + <method name="get_closest_collision_unsafe_fraction" qualifiers="const"> + <return type="float" /> + <description> + The fraction of the motion (between 0 and 1) when the shape triggers a collision. The motion is determined by [member target_position]. + </description> + </method> + <method name="get_collider" qualifiers="const"> + <return type="Object" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the [Object] of one of the multiple collisions at [code]index[/code], or [code]null[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]). + </description> + </method> + <method name="get_collider_shape" qualifiers="const"> + <return type="int" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the shape ID of one of the multiple collisions at [code]index[/code] that the shape intersects, or [code]0[/code] if no object is intersecting the shape (i.e. [method is_colliding] returns [code]false[/code]). + </description> + </method> + <method name="get_collision_count" qualifiers="const"> + <return type="int" /> + <description> + The number of collisions detected at the point of impact. Use this to iterate over multiple collisions as provided by [method get_collider], [method get_collider_shape], [method get_collision_point], and [method get_collision_normal] methods. + </description> + </method> + <method name="get_collision_mask_value" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="layer_number" type="int" /> + <description> + Returns whether or not the specified layer of the [member collision_mask] is enabled, given a [code]layer_number[/code] between 1 and 32. + </description> + </method> + <method name="get_collision_normal" qualifiers="const"> + <return type="Vector2" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the normal containing one of the multiple collisions at [code]index[/code] of the intersecting object. + </description> + </method> + <method name="get_collision_point" qualifiers="const"> + <return type="Vector2" /> + <argument index="0" name="index" type="int" /> + <description> + Returns the collision point containing one of the multiple collisions at [code]index[/code] at which the shape intersects the object. + [b]Note:[/b] this point is in the [b]global[/b] coordinate system. + </description> + </method> + <method name="is_colliding" qualifiers="const"> + <return type="bool" /> + <description> + Returns whether any object is intersecting with the shape's vector (considering the vector length). + </description> + </method> + <method name="remove_exception"> + <return type="void" /> + <argument index="0" name="node" type="Object" /> + <description> + Removes a collision exception so the shape does report collisions with the specified node. + </description> + </method> + <method name="remove_exception_rid"> + <return type="void" /> + <argument index="0" name="rid" type="RID" /> + <description> + Removes a collision exception so the shape does report collisions with the specified [RID]. + </description> + </method> + <method name="set_collision_mask_value"> + <return type="void" /> + <argument index="0" name="layer_number" type="int" /> + <argument index="1" name="value" type="bool" /> + <description> + Based on [code]value[/code], enables or disables the specified layer in the [member collision_mask], given a [code]layer_number[/code] between 1 and 32. + </description> + </method> + </methods> + <members> + <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> + If [code]true[/code], collision with [Area2D]s will be reported. + </member> + <member name="collide_with_bodies" type="bool" setter="set_collide_with_bodies" getter="is_collide_with_bodies_enabled" default="true"> + If [code]true[/code], collision with [PhysicsBody2D]s will be reported. + </member> + <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> + The shape's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. + </member> + <member name="collision_result" type="Array" setter="" getter="_get_collision_result" default="[]"> + A complete collision information. The data returned is the same as in the [method PhysicsDirectSpaceState2D.get_rest_info] method. + </member> + <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> + If [code]true[/code], collisions will be reported. + </member> + <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> + If [code]true[/code], the parent node will be excluded from collision detection. + </member> + <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0"> + The collision margin for the shape. A larger margin helps detecting collisions more consistently, at the cost of precision. + </member> + <member name="max_results" type="int" setter="set_max_results" getter="get_max_results" default="32"> + The number of intersections can be limited with this parameter, to reduce the processing time. + </member> + <member name="shape" type="Shape2D" setter="set_shape" getter="get_shape"> + Any [Shape2D] derived shape used for collision queries. + </member> + <member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2(0, 50)"> + The shape's destination point, relative to this node's [code]position[/code]. + </member> + </members> +</class> diff --git a/doc/classes/Skeleton2D.xml b/doc/classes/Skeleton2D.xml index 7aa06985bf..20bec14795 100644 --- a/doc/classes/Skeleton2D.xml +++ b/doc/classes/Skeleton2D.xml @@ -8,7 +8,7 @@ To setup different types of inverse kinematics for the given Skeleton2D, a [SkeletonModificationStack2D] should be created. They can be applied by creating the desired number of modifications, which can be done by increasing [member SkeletonModificationStack2D.modification_count]. </description> <tutorials> - <link title="2D skeletons">https://docs.godotengine.org/en/latest/tutorials/animation/2d_skeletons.html</link> + <link title="2D skeletons">$DOCS_URL/tutorials/animation/2d_skeletons.html</link> </tutorials> <methods> <method name="execute_modifications"> diff --git a/doc/classes/SoftDynamicBody3D.xml b/doc/classes/SoftDynamicBody3D.xml index f999f77e78..fceebddf35 100644 --- a/doc/classes/SoftDynamicBody3D.xml +++ b/doc/classes/SoftDynamicBody3D.xml @@ -7,7 +7,7 @@ A deformable physics body. Used to create elastic or deformable objects such as cloth, rubber, or other flexible materials. </description> <tutorials> - <link title="SoftBody">https://docs.godotengine.org/en/latest/tutorials/physics/soft_body.html</link> + <link title="SoftBody">$DOCS_URL/tutorials/physics/soft_body.html</link> </tutorials> <methods> <method name="add_collision_exception_with"> @@ -92,11 +92,11 @@ <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> The physics layers this SoftDynamicBody3D [b]is in[/b]. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. - [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The physics layers this SoftDynamicBody3D [b]scans[/b]. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. - [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01"> </member> diff --git a/doc/classes/SpotLight3D.xml b/doc/classes/SpotLight3D.xml index 8c10ec36a8..f9f9a62baa 100644 --- a/doc/classes/SpotLight3D.xml +++ b/doc/classes/SpotLight3D.xml @@ -7,7 +7,7 @@ A Spotlight is a type of [Light3D] node that emits lights in a specific direction, in the shape of a cone. The light is attenuated through the distance. This attenuation can be configured by changing the energy, radius and attenuation parameters of [Light3D]. </description> <tutorials> - <link title="3D lights and shadows">https://docs.godotengine.org/en/latest/tutorials/3d/lights_and_shadows.html</link> + <link title="3D lights and shadows">$DOCS_URL/tutorials/3d/lights_and_shadows.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <members> diff --git a/doc/classes/SpringArm3D.xml b/doc/classes/SpringArm3D.xml index 2cd8fa71cf..a54578cff4 100644 --- a/doc/classes/SpringArm3D.xml +++ b/doc/classes/SpringArm3D.xml @@ -41,7 +41,7 @@ </methods> <members> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The layers against which the collision check shall be done. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The layers against which the collision check shall be done. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.01"> When the collision check is made, a candidate length for the SpringArm3D is given. diff --git a/doc/classes/StandardMaterial3D.xml b/doc/classes/StandardMaterial3D.xml index 43ba95e345..1a8bf0e202 100644 --- a/doc/classes/StandardMaterial3D.xml +++ b/doc/classes/StandardMaterial3D.xml @@ -5,6 +5,6 @@ <description> </description> <tutorials> - <link title="Standard Material 3D">https://docs.godotengine.org/en/latest/tutorials/3d/standard_material_3d.html</link> + <link title="Standard Material 3D">$DOCS_URL/tutorials/3d/standard_material_3d.html</link> </tutorials> </class> diff --git a/doc/classes/StreamPeerSSL.xml b/doc/classes/StreamPeerSSL.xml index 50389f912d..5e6e07fe36 100644 --- a/doc/classes/StreamPeerSSL.xml +++ b/doc/classes/StreamPeerSSL.xml @@ -8,7 +8,7 @@ [b]Note:[/b] When exporting to Android, make sure to enable the [code]INTERNET[/code] permission in the Android export preset before exporting the project or using one-click deploy. Otherwise, network communication of any kind will be blocked by Android. </description> <tutorials> - <link title="SSL certificates">https://docs.godotengine.org/en/latest/tutorials/networking/ssl_certificates.html</link> + <link title="SSL certificates">$DOCS_URL/tutorials/networking/ssl_certificates.html</link> </tutorials> <methods> <method name="accept_stream"> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index a58bfd5c15..ce902c1216 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -7,7 +7,7 @@ This is the built-in string class (and the one used by GDScript). It supports Unicode and provides all necessary means for string handling. Strings are reference-counted and use a copy-on-write approach, so passing them around is cheap in resources. </description> <tutorials> - <link title="GDScript format strings">https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_format_string.html</link> + <link title="GDScript format strings">$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html</link> </tutorials> <constructors> <constructor name="String"> diff --git a/doc/classes/SubViewport.xml b/doc/classes/SubViewport.xml index c2a76b587f..f0b85cdad5 100644 --- a/doc/classes/SubViewport.xml +++ b/doc/classes/SubViewport.xml @@ -6,8 +6,8 @@ <description> </description> <tutorials> - <link title="Using Viewports">https://docs.godotengine.org/en/latest/tutorials/rendering/viewports.html</link> - <link title="Viewport and canvas transforms">https://docs.godotengine.org/en/latest/tutorials/2d/2d_transforms.html</link> + <link title="Using Viewports">$DOCS_URL/tutorials/rendering/viewports.html</link> + <link title="Viewport and canvas transforms">$DOCS_URL/tutorials/2d/2d_transforms.html</link> <link title="GUI in 3D Demo">https://godotengine.org/asset-library/asset/127</link> <link title="3D in 2D Demo">https://godotengine.org/asset-library/asset/128</link> <link title="2D in 3D Demo">https://godotengine.org/asset-library/asset/129</link> diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml index 52a419ce0f..d1a48fda55 100644 --- a/doc/classes/Theme.xml +++ b/doc/classes/Theme.xml @@ -8,7 +8,7 @@ Theme resources can alternatively be loaded by writing them in a [code].theme[/code] file, see the documentation for more information. </description> <tutorials> - <link title="GUI skinning">https://docs.godotengine.org/en/latest/tutorials/ui/gui_skinning.html</link> + <link title="GUI skinning">$DOCS_URL/tutorials/ui/gui_skinning.html</link> </tutorials> <methods> <method name="clear"> diff --git a/doc/classes/Thread.xml b/doc/classes/Thread.xml index eb2df8a4f9..bd9a6c865a 100644 --- a/doc/classes/Thread.xml +++ b/doc/classes/Thread.xml @@ -8,8 +8,8 @@ [b]Note:[/b] Breakpoints won't break on code if it's running in a thread. This is a current limitation of the GDScript debugger. </description> <tutorials> - <link title="Using multiple threads">https://docs.godotengine.org/en/latest/tutorials/performance/using_multiple_threads.html</link> - <link title="Thread-safe APIs">https://docs.godotengine.org/en/latest/tutorials/performance/thread_safe_apis.html</link> + <link title="Using multiple threads">$DOCS_URL/tutorials/performance/using_multiple_threads.html</link> + <link title="Thread-safe APIs">$DOCS_URL/tutorials/performance/thread_safe_apis.html</link> <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> <methods> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index 22d61c7285..6e552e3649 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -7,7 +7,7 @@ Node for 2D tile-based maps. Tilemaps use a [TileSet] which contain a list of tiles which are used to create grid-based maps. A TileMap may have several layers, layouting tiles on top of each other. </description> <tutorials> - <link title="Using Tilemaps">https://docs.godotengine.org/en/latest/tutorials/2d/using_tilemaps.html</link> + <link title="Using Tilemaps">$DOCS_URL/tutorials/2d/using_tilemaps.html</link> <link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/120</link> <link title="2D Isometric Demo">https://godotengine.org/asset-library/asset/112</link> <link title="2D Hexagonal Demo">https://godotengine.org/asset-library/asset/111</link> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index 45d6f9ca6c..5d9065f823 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -13,7 +13,7 @@ See the functions to add new layers for more information. </description> <tutorials> - <link title="Using Tilemaps">https://docs.godotengine.org/en/latest/tutorials/2d/using_tilemaps.html</link> + <link title="Using Tilemaps">$DOCS_URL/tutorials/2d/using_tilemaps.html</link> <link title="2D Platformer Demo">https://godotengine.org/asset-library/asset/120</link> <link title="2D Isometric Demo">https://godotengine.org/asset-library/asset/112</link> <link title="2D Hexagonal Demo">https://godotengine.org/asset-library/asset/111</link> diff --git a/doc/classes/TileSetAtlasSource.xml b/doc/classes/TileSetAtlasSource.xml index 881a1c3d07..6580c6bd4c 100644 --- a/doc/classes/TileSetAtlasSource.xml +++ b/doc/classes/TileSetAtlasSource.xml @@ -45,6 +45,21 @@ Returns the alternative ID a following call to [method create_alternative_tile] would return. </description> </method> + <method name="get_runtime_texture" qualifiers="const"> + <return type="Texture2D" /> + <description> + If [member use_texture_padding] is [code]false[/code], returns [member texture]. Otherwise, returns and internal [ImageTexture] created that includes the padding. + </description> + </method> + <method name="get_runtime_tile_texture_region" qualifiers="const"> + <return type="Rect2i" /> + <argument index="0" name="atlas_coords" type="Vector2i" /> + <argument index="1" name="frame" type="int" /> + <description> + Returns the region of the tile at coordinates [code]atlas_coords[/code] for frame [code]frame[/code] inside the texture returned by [method get_runtime_texture]. + [b]Note:[/b] If [member use_texture_padding] is [code]false[/code], returns the same as [method get_tile_texture_region]. + </description> + </method> <method name="get_tile_animation_columns" qualifiers="const"> <return type="int" /> <argument index="0" name="atlas_coords" type="Vector2i" /> @@ -232,5 +247,9 @@ <member name="texture_region_size" type="Vector2i" setter="set_texture_region_size" getter="get_texture_region_size" default="Vector2i(16, 16)"> The base tile size in the texture (in pixel). This size must be bigger than the TileSet's [code]tile_size[/code] value. </member> + <member name="use_texture_padding" type="bool" setter="set_use_texture_padding" getter="get_use_texture_padding" default="true"> + If [code]true[/code], generates an internal texture with an additional one pixel padding around each tile. Texture padding avoids a common artifact where lines appear between tiles. + Disabling this setting might lead a small performance improvement, as generating the internal texture requires both memory and processing time when the TileSetAtlasSource resource is modified. + </member> </members> </class> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index ab7632e08e..be41cdde99 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -8,8 +8,8 @@ For more information, read the "Matrices and transforms" documentation article. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Matrices and transforms">https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Matrices and transforms">$DOCS_URL/tutorials/math/matrices_and_transforms.html</link> <link title="Matrix Transform Demo">https://godotengine.org/asset-library/asset/584</link> <link title="2.5D Demo">https://godotengine.org/asset-library/asset/583</link> </tutorials> @@ -213,30 +213,36 @@ <return type="bool" /> <argument index="0" name="right" type="Transform2D" /> <description> + Returns [code]true[/code] if the transforms are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="PackedVector2Array" /> <argument index="0" name="right" type="PackedVector2Array" /> <description> + Transforms (multiplies) each element of the [Vector2] array by the given [Transform2D] matrix. </description> </operator> <operator name="operator *"> <return type="Transform2D" /> <argument index="0" name="right" type="Transform2D" /> <description> + Composes these two transformation matrices by multiplying them together. This has the effect of transforming the second transform (the child) by the first transform (the parent). </description> </operator> <operator name="operator *"> <return type="Rect2" /> <argument index="0" name="right" type="Rect2" /> <description> + Transforms (multiplies) the [Rect2] by the given [Transform2D] matrix. </description> </operator> <operator name="operator *"> <return type="Vector2" /> <argument index="0" name="right" type="Vector2" /> <description> + Transforms (multiplies) the [Vector2] by the given [Transform2D] matrix. </description> </operator> <operator name="operator *"> @@ -262,12 +268,15 @@ <return type="bool" /> <argument index="0" name="right" type="Transform2D" /> <description> + Returns [code]true[/code] if the transforms are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator []"> <return type="Vector2" /> <argument index="0" name="index" type="int" /> <description> + Access transform components using their index. [code]t[0][/code] is equivalent to [code]t.x[/code], [code]t[1][/code] is equivalent to [code]t.y[/code], and [code]t[2][/code] is equivalent to [code]t.origin[/code]. </description> </operator> </operators> diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml index 8c4965abb4..511574f6aa 100644 --- a/doc/classes/Transform3D.xml +++ b/doc/classes/Transform3D.xml @@ -8,9 +8,9 @@ For more information, read the "Matrices and transforms" documentation article. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Matrices and transforms">https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html</link> - <link title="Using 3D transforms">https://docs.godotengine.org/en/latest/tutorials/3d/using_transforms.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Matrices and transforms">$DOCS_URL/tutorials/math/matrices_and_transforms.html</link> + <link title="Using 3D transforms">$DOCS_URL/tutorials/3d/using_transforms.html</link> <link title="Matrix Transform Demo">https://godotengine.org/asset-library/asset/584</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="2.5D Demo">https://godotengine.org/asset-library/asset/583</link> @@ -147,30 +147,36 @@ <return type="bool" /> <argument index="0" name="right" type="Transform3D" /> <description> + Returns [code]true[/code] if the transforms are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="PackedVector3Array" /> <argument index="0" name="right" type="PackedVector3Array" /> <description> + Transforms (multiplies) each element of the [Vector3] array by the given [Transform3D] matrix. </description> </operator> <operator name="operator *"> <return type="Transform3D" /> <argument index="0" name="right" type="Transform3D" /> <description> + Composes these two transformation matrices by multiplying them together. This has the effect of transforming the second transform (the child) by the first transform (the parent). </description> </operator> <operator name="operator *"> <return type="AABB" /> <argument index="0" name="right" type="AABB" /> <description> + Transforms (multiplies) the [AABB] by the given [Transform3D] matrix. </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="Vector3" /> <description> + Transforms (multiplies) the [Vector3] by the given [Transform3D] matrix. </description> </operator> <operator name="operator *"> @@ -196,6 +202,8 @@ <return type="bool" /> <argument index="0" name="right" type="Transform3D" /> <description> + Returns [code]true[/code] if the transforms are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> </operators> diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml index 2a0695d42e..defebf7ab4 100644 --- a/doc/classes/Translation.xml +++ b/doc/classes/Translation.xml @@ -7,8 +7,8 @@ Translations are resources that can be loaded and unloaded on demand. They map a string to another string. </description> <tutorials> - <link title="Internationalizing games">https://docs.godotengine.org/en/latest/tutorials/i18n/internationalizing_games.html</link> - <link title="Locales">https://docs.godotengine.org/en/latest/tutorials/i18n/locales.html</link> + <link title="Internationalizing games">$DOCS_URL/tutorials/i18n/internationalizing_games.html</link> + <link title="Locales">$DOCS_URL/tutorials/i18n/locales.html</link> </tutorials> <methods> <method name="_get_message" qualifiers="virtual const"> diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml index 8a6fa3571a..519e1cb041 100644 --- a/doc/classes/TranslationServer.xml +++ b/doc/classes/TranslationServer.xml @@ -7,8 +7,8 @@ Server that manages all translations. Translations can be set to it and removed from it. </description> <tutorials> - <link title="Internationalizing games">https://docs.godotengine.org/en/latest/tutorials/i18n/internationalizing_games.html</link> - <link title="Locales">https://docs.godotengine.org/en/latest/tutorials/i18n/locales.html</link> + <link title="Internationalizing games">$DOCS_URL/tutorials/i18n/internationalizing_games.html</link> + <link title="Locales">$DOCS_URL/tutorials/i18n/locales.html</link> </tutorials> <methods> <method name="add_translation"> diff --git a/doc/classes/Variant.xml b/doc/classes/Variant.xml index 88644e2f8a..b8649a2836 100644 --- a/doc/classes/Variant.xml +++ b/doc/classes/Variant.xml @@ -72,6 +72,6 @@ Modifications to a container will modify all references to it. A [Mutex] should be created to lock it if multi-threaded access is desired. </description> <tutorials> - <link title="Variant class">https://docs.godotengine.org/en/latest/development/cpp/variant_class.html</link> + <link title="Variant class">$DOCS_URL/development/cpp/variant_class.html</link> </tutorials> </class> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index eaaf41561a..595af6222c 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -9,9 +9,9 @@ [b]Note:[/b] In a boolean context, a Vector2 will evaluate to [code]false[/code] if it's equal to [code]Vector2(0, 0)[/code]. Otherwise, a Vector2 will always evaluate to [code]true[/code]. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Vector math">https://docs.godotengine.org/en/latest/tutorials/math/vector_math.html</link> - <link title="Advanced vector math">https://docs.godotengine.org/en/latest/tutorials/math/vectors_advanced.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Vector math">$DOCS_URL/tutorials/math/vector_math.html</link> + <link title="Advanced vector math">$DOCS_URL/tutorials/math/vectors_advanced.html</link> <link title="3Blue1Brown Essence of Linear Algebra">https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab</link> <link title="Matrix Transform Demo">https://godotengine.org/asset-library/asset/584</link> <link title="All 2D Demos">https://github.com/godotengine/godot-demo-projects/tree/master/2d</link> @@ -75,6 +75,7 @@ <argument index="0" name="to" type="Vector2" /> <description> Returns the angle between the line connecting the two points and the X axis, in radians. + [code]a.angle_to_point(b)[/code] is equivalent of doing [code](b - a).angle()[/code]. [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/vector2_angle_to_point.png]Illustration of the returned angle.[/url] </description> </method> @@ -351,72 +352,97 @@ <return type="bool" /> <argument index="0" name="right" type="Vector2" /> <description> + Returns [code]true[/code] if the vectors are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="Vector2" /> <argument index="0" name="right" type="Vector2" /> <description> + Multiplies each component of the [Vector2] by the components of the given [Vector2]. + [codeblock] + print(Vector2(10, 20) * Vector2(3, 4)) # Prints "(30, 80)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector2" /> <argument index="0" name="right" type="Transform2D" /> <description> + Inversely transforms (multiplies) the [Vector2] by the given [Transform2D] transformation matrix. </description> </operator> <operator name="operator *"> <return type="Vector2" /> <argument index="0" name="right" type="float" /> <description> + Multiplies each component of the [Vector2] by the given [float]. </description> </operator> <operator name="operator *"> <return type="Vector2" /> <argument index="0" name="right" type="int" /> <description> + Multiplies each component of the [Vector2] by the given [int]. </description> </operator> <operator name="operator +"> <return type="Vector2" /> <argument index="0" name="right" type="Vector2" /> <description> + Adds each component of the [Vector2] by the components of the given [Vector2]. + [codeblock] + print(Vector2(10, 20) + Vector2(3, 4)) # Prints "(13, 24)" + [/codeblock] </description> </operator> <operator name="operator -"> <return type="Vector2" /> <argument index="0" name="right" type="Vector2" /> <description> + Subtracts each component of the [Vector2] by the components of the given [Vector2]. + [codeblock] + print(Vector2(10, 20) - Vector2(3, 4)) # Prints "(7, 16)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector2" /> <argument index="0" name="right" type="Vector2" /> <description> + Divides each component of the [Vector2] by the components of the given [Vector2]. + [codeblock] + print(Vector2(10, 20) / Vector2(2, 5)) # Prints "(5, 4)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector2" /> <argument index="0" name="right" type="float" /> <description> + Divides each component of the [Vector2] by the given [float]. </description> </operator> <operator name="operator /"> <return type="Vector2" /> <argument index="0" name="right" type="int" /> <description> + Divides each component of the [Vector2] by the given [int]. </description> </operator> <operator name="operator <"> <return type="bool" /> <argument index="0" name="right" type="Vector2" /> <description> + Compares two [Vector2] vectors by first checking if the X value of the left vector is less than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors. This operator is useful for sorting vectors. </description> </operator> <operator name="operator <="> <return type="bool" /> <argument index="0" name="right" type="Vector2" /> <description> + Compares two [Vector2] vectors by first checking if the X value of the left vector is less than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors. This operator is useful for sorting vectors. </description> </operator> <operator name="operator =="> @@ -428,34 +454,41 @@ <return type="bool" /> <argument index="0" name="right" type="Vector2" /> <description> + Returns [code]true[/code] if the vectors are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator >"> <return type="bool" /> <argument index="0" name="right" type="Vector2" /> <description> + Compares two [Vector2] vectors by first checking if the X value of the left vector is greater than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors. This operator is useful for sorting vectors. </description> </operator> <operator name="operator >="> <return type="bool" /> <argument index="0" name="right" type="Vector2" /> <description> + Compares two [Vector2] vectors by first checking if the X value of the left vector is greater than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors. This operator is useful for sorting vectors. </description> </operator> <operator name="operator []"> <return type="float" /> <argument index="0" name="index" type="int" /> <description> + Access vector components using their index. [code]v[0][/code] is equivalent to [code]v.x[/code], and [code]v[1][/code] is equivalent to [code]v.y[/code]. </description> </operator> <operator name="operator unary+"> <return type="Vector2" /> <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. </description> </operator> <operator name="operator unary-"> <return type="Vector2" /> <description> + Returns the negative value of the [Vector2]. This is the same as writing [code]Vector2(-v.x, -v.y)[/code]. This operation flips the direction of the vector while keeping the same magnitude. With floats, the number zero can be either positive or negative. </description> </operator> </operators> diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml index 71882e5b0c..62362409a5 100644 --- a/doc/classes/Vector2i.xml +++ b/doc/classes/Vector2i.xml @@ -9,8 +9,8 @@ [b]Note:[/b] In a boolean context, a Vector2i will evaluate to [code]false[/code] if it's equal to [code]Vector2i(0, 0)[/code]. Otherwise, a Vector2i will always evaluate to [code]true[/code]. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Vector math">https://docs.godotengine.org/en/latest/tutorials/math/vector_math.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Vector math">$DOCS_URL/tutorials/math/vector_math.html</link> <link title="3Blue1Brown Essence of Linear Algebra">https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab</link> </tutorials> <constructors> @@ -115,78 +115,115 @@ <return type="bool" /> <argument index="0" name="right" type="Vector2i" /> <description> + Returns [code]true[/code] if the vectors are not equal. </description> </operator> <operator name="operator %"> <return type="Vector2i" /> <argument index="0" name="right" type="Vector2i" /> <description> + Gets the remainder of each component of the [Vector2i] with the components of the given [Vector2i]. This operation uses truncated division, which is often not desired as it does not work well with negative numbers. Consider using [method @GlobalScope.posmod] instead if you want to handle negative numbers. + [codeblock] + print(Vector2i(10, -20) % Vector2i(7, 8)) # Prints "(3, -4)" + [/codeblock] </description> </operator> <operator name="operator %"> <return type="Vector2i" /> <argument index="0" name="right" type="int" /> <description> + Gets the remainder of each component of the [Vector2i] with the the given [int]. This operation uses truncated division, which is often not desired as it does not work well with negative numbers. Consider using [method @GlobalScope.posmod] instead if you want to handle negative numbers. + [codeblock] + print(Vector2i(10, -20) % 7) # Prints "(3, -6)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector2i" /> <argument index="0" name="right" type="Vector2i" /> <description> + Multiplies each component of the [Vector2i] by the components of the given [Vector2i]. + [codeblock] + print(Vector2i(10, 20) * Vector2i(3, 4)) # Prints "(30, 80)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector2i" /> <argument index="0" name="right" type="float" /> <description> + Multiplies each component of the [Vector2i] by the given [float] truncated to an integer. + [codeblock] + print(Vector2i(10, 20) * 0.9) # Prints "(0, 0)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector2i" /> <argument index="0" name="right" type="int" /> <description> + Multiplies each component of the [Vector2i] by the given [int]. </description> </operator> <operator name="operator +"> <return type="Vector2i" /> <argument index="0" name="right" type="Vector2i" /> <description> + Adds each component of the [Vector2i] by the components of the given [Vector2i]. + [codeblock] + print(Vector2i(10, 20) + Vector2i(3, 4)) # Prints "(13, 24)" + [/codeblock] </description> </operator> <operator name="operator -"> <return type="Vector2i" /> <argument index="0" name="right" type="Vector2i" /> <description> + Subtracts each component of the [Vector2i] by the components of the given [Vector2i]. + [codeblock] + print(Vector2i(10, 20) - Vector2i(3, 4)) # Prints "(7, 16)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector2i" /> <argument index="0" name="right" type="Vector2i" /> <description> + Divides each component of the [Vector2i] by the components of the given [Vector2i]. + [codeblock] + print(Vector2i(10, 20) / Vector2i(2, 5)) # Prints "(5, 4)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector2i" /> <argument index="0" name="right" type="float" /> <description> + Divides each component of the [Vector2i] by the given [float] truncated to an integer. + [codeblock] + print(Vector2i(10, 20) / 2.9) # Prints "(5, 10)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector2i" /> <argument index="0" name="right" type="int" /> <description> + Divides each component of the [Vector2i] by the given [int]. </description> </operator> <operator name="operator <"> <return type="bool" /> <argument index="0" name="right" type="Vector2i" /> <description> + Compares two [Vector2i] vectors by first checking if the X value of the left vector is less than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors. This operator is useful for sorting vectors. </description> </operator> <operator name="operator <="> <return type="bool" /> <argument index="0" name="right" type="Vector2i" /> <description> + Compares two [Vector2i] vectors by first checking if the X value of the left vector is less than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors. This operator is useful for sorting vectors. </description> </operator> <operator name="operator =="> @@ -198,34 +235,40 @@ <return type="bool" /> <argument index="0" name="right" type="Vector2i" /> <description> + Returns [code]true[/code] if the vectors are equal. </description> </operator> <operator name="operator >"> <return type="bool" /> <argument index="0" name="right" type="Vector2i" /> <description> + Compares two [Vector2i] vectors by first checking if the X value of the left vector is greater than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors. This operator is useful for sorting vectors. </description> </operator> <operator name="operator >="> <return type="bool" /> <argument index="0" name="right" type="Vector2i" /> <description> + Compares two [Vector2i] vectors by first checking if the X value of the left vector is greater than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors. This operator is useful for sorting vectors. </description> </operator> <operator name="operator []"> <return type="int" /> <argument index="0" name="index" type="int" /> <description> + Access vector components using their index. [code]v[0][/code] is equivalent to [code]v.x[/code], and [code]v[1][/code] is equivalent to [code]v.y[/code]. </description> </operator> <operator name="operator unary+"> <return type="Vector2i" /> <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. </description> </operator> <operator name="operator unary-"> <return type="Vector2i" /> <description> + Returns the negative value of the [Vector2i]. This is the same as writing [code]Vector2i(-v.x, -v.y)[/code]. This operation flips the direction of the vector while keeping the same magnitude. </description> </operator> </operators> diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index a94cc0086f..62d467c505 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -9,9 +9,9 @@ [b]Note:[/b] In a boolean context, a Vector3 will evaluate to [code]false[/code] if it's equal to [code]Vector3(0, 0, 0)[/code]. Otherwise, a Vector3 will always evaluate to [code]true[/code]. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Vector math">https://docs.godotengine.org/en/latest/tutorials/math/vector_math.html</link> - <link title="Advanced vector math">https://docs.godotengine.org/en/latest/tutorials/math/vectors_advanced.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Vector math">$DOCS_URL/tutorials/math/vector_math.html</link> + <link title="Advanced vector math">$DOCS_URL/tutorials/math/vectors_advanced.html</link> <link title="3Blue1Brown Essence of Linear Algebra">https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab</link> <link title="Matrix Transform Demo">https://godotengine.org/asset-library/asset/584</link> <link title="All 3D Demos">https://github.com/godotengine/godot-demo-projects/tree/master/3d</link> @@ -367,84 +367,111 @@ <return type="bool" /> <argument index="0" name="right" type="Vector3" /> <description> + Returns [code]true[/code] if the vectors are not equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="Vector3" /> <description> + Multiplies each component of the [Vector3] by the components of the given [Vector3]. + [codeblock] + print(Vector3(10, 20, 30) * Vector3(3, 4, 5)) # Prints "(30, 80, 150)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="Basis" /> <description> + Inversely transforms (multiplies) the [Vector3] by the given [Basis] matrix. </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="Quaternion" /> <description> + Inversely transforms (multiplies) the [Vector3] by the given [Quaternion]. </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="Transform3D" /> <description> + Inversely transforms (multiplies) the [Vector3] by the given [Transform3D] transformation matrix. </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="float" /> <description> + Multiplies each component of the [Vector3] by the given [float]. </description> </operator> <operator name="operator *"> <return type="Vector3" /> <argument index="0" name="right" type="int" /> <description> + Multiplies each component of the [Vector3] by the given [int]. </description> </operator> <operator name="operator +"> <return type="Vector3" /> <argument index="0" name="right" type="Vector3" /> <description> + Adds each component of the [Vector3] by the components of the given [Vector3]. + [codeblock] + print(Vector3(10, 20, 30) + Vector3(3, 4, 5)) # Prints "(13, 24, 35)" + [/codeblock] </description> </operator> <operator name="operator -"> <return type="Vector3" /> <argument index="0" name="right" type="Vector3" /> <description> + Subtracts each component of the [Vector3] by the components of the given [Vector3]. + [codeblock] + print(Vector3(10, 20, 30) - Vector3(3, 4, 5)) # Prints "(7, 16, 25)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector3" /> <argument index="0" name="right" type="Vector3" /> <description> + Divides each component of the [Vector3] by the components of the given [Vector3]. + [codeblock] + print(Vector3(10, 20, 30) / Vector3(2, 5, 3)) # Prints "(5, 4, 10)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector3" /> <argument index="0" name="right" type="float" /> <description> + Divides each component of the [Vector3] by the given [float]. </description> </operator> <operator name="operator /"> <return type="Vector3" /> <argument index="0" name="right" type="int" /> <description> + Divides each component of the [Vector3] by the given [int]. </description> </operator> <operator name="operator <"> <return type="bool" /> <argument index="0" name="right" type="Vector3" /> <description> + Compares two [Vector3] vectors by first checking if the X value of the left vector is less than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, and then with the Z values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator <="> <return type="bool" /> <argument index="0" name="right" type="Vector3" /> <description> + Compares two [Vector3] vectors by first checking if the X value of the left vector is less than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, and then with the Z values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator =="> @@ -456,34 +483,41 @@ <return type="bool" /> <argument index="0" name="right" type="Vector3" /> <description> + Returns [code]true[/code] if the vectors are exactly equal. + [b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable. </description> </operator> <operator name="operator >"> <return type="bool" /> <argument index="0" name="right" type="Vector3" /> <description> + Compares two [Vector3] vectors by first checking if the X value of the left vector is greater than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, and then with the Z values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator >="> <return type="bool" /> <argument index="0" name="right" type="Vector3" /> <description> + Compares two [Vector3] vectors by first checking if the X value of the left vector is greater than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, and then with the Z values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator []"> <return type="float" /> <argument index="0" name="index" type="int" /> <description> + Access vector components using their index. [code]v[0][/code] is equivalent to [code]v.x[/code], [code]v[1][/code] is equivalent to [code]v.y[/code], and [code]v[2][/code] is equivalent to [code]v.z[/code]. </description> </operator> <operator name="operator unary+"> <return type="Vector3" /> <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. </description> </operator> <operator name="operator unary-"> <return type="Vector3" /> <description> + Returns the negative value of the [Vector3]. This is the same as writing [code]Vector3(-v.x, -v.y, -v.z)[/code]. This operation flips the direction of the vector while keeping the same magnitude. With floats, the number zero can be either positive or negative. </description> </operator> </operators> diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml index 5cd458a2be..17febdea83 100644 --- a/doc/classes/Vector3i.xml +++ b/doc/classes/Vector3i.xml @@ -9,8 +9,8 @@ [b]Note:[/b] In a boolean context, a Vector3i will evaluate to [code]false[/code] if it's equal to [code]Vector3i(0, 0, 0)[/code]. Otherwise, a Vector3i will always evaluate to [code]true[/code]. </description> <tutorials> - <link title="Math documentation index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> - <link title="Vector math">https://docs.godotengine.org/en/latest/tutorials/math/vector_math.html</link> + <link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link> + <link title="Vector math">$DOCS_URL/tutorials/math/vector_math.html</link> <link title="3Blue1Brown Essence of Linear Algebra">https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab</link> </tutorials> <constructors> @@ -133,78 +133,115 @@ <return type="bool" /> <argument index="0" name="right" type="Vector3i" /> <description> + Returns [code]true[/code] if the vectors are not equal. </description> </operator> <operator name="operator %"> <return type="Vector3i" /> <argument index="0" name="right" type="Vector3i" /> <description> + Gets the remainder of each component of the [Vector3i] with the components of the given [Vector3i]. This operation uses truncated division, which is often not desired as it does not work well with negative numbers. Consider using [method @GlobalScope.posmod] instead if you want to handle negative numbers. + [codeblock] + print(Vector3i(10, -20, 30) % Vector3i(7, 8, 9)) # Prints "(3, -4, 3)" + [/codeblock] </description> </operator> <operator name="operator %"> <return type="Vector3i" /> <argument index="0" name="right" type="int" /> <description> + Gets the remainder of each component of the [Vector3i] with the the given [int]. This operation uses truncated division, which is often not desired as it does not work well with negative numbers. Consider using [method @GlobalScope.posmod] instead if you want to handle negative numbers. + [codeblock] + print(Vector2i(10, -20, 30) % 7) # Prints "(3, -6, 2)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector3i" /> <argument index="0" name="right" type="Vector3i" /> <description> + Multiplies each component of the [Vector3i] by the components of the given [Vector3i]. + [codeblock] + print(Vector3i(10, 20, 30) * Vector3i(3, 4, 5)) # Prints "(30, 80, 150)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector3i" /> <argument index="0" name="right" type="float" /> <description> + Multiplies each component of the [Vector3i] by the given [float] truncated to an integer. + [codeblock] + print(Vector3i(10, 20, 30) * 0.9) # Prints "(0, 0, 0)" + [/codeblock] </description> </operator> <operator name="operator *"> <return type="Vector3i" /> <argument index="0" name="right" type="int" /> <description> + Multiplies each component of the [Vector3i] by the given [int]. </description> </operator> <operator name="operator +"> <return type="Vector3i" /> <argument index="0" name="right" type="Vector3i" /> <description> + Adds each component of the [Vector3i] by the components of the given [Vector3i]. + [codeblock] + print(Vector3i(10, 20, 30) + Vector3i(3, 4, 5)) # Prints "(13, 24, 35)" + [/codeblock] </description> </operator> <operator name="operator -"> <return type="Vector3i" /> <argument index="0" name="right" type="Vector3i" /> <description> + Subtracts each component of the [Vector3i] by the components of the given [Vector3i]. + [codeblock] + print(Vector3i(10, 20, 30) - Vector3i(3, 4, 5)) # Prints "(7, 16, 25)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector3i" /> <argument index="0" name="right" type="Vector3i" /> <description> + Divides each component of the [Vector3i] by the components of the given [Vector3i]. + [codeblock] + print(Vector3i(10, 20, 30) / Vector3i(2, 5, 3)) # Prints "(5, 4, 10)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector3i" /> <argument index="0" name="right" type="float" /> <description> + Divides each component of the [Vector3i] by the given [float] truncated to an integer. + [codeblock] + print(Vector3i(10, 20, 30) / 2.9) # Prints "(5, 10, 15)" + [/codeblock] </description> </operator> <operator name="operator /"> <return type="Vector3i" /> <argument index="0" name="right" type="int" /> <description> + Divides each component of the [Vector3i] by the given [int]. </description> </operator> <operator name="operator <"> <return type="bool" /> <argument index="0" name="right" type="Vector3i" /> <description> + Compares two [Vector3i] vectors by first checking if the X value of the left vector is less than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, and then with the Z values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator <="> <return type="bool" /> <argument index="0" name="right" type="Vector3i" /> <description> + Compares two [Vector3i] vectors by first checking if the X value of the left vector is less than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, and then with the Z values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator =="> @@ -216,34 +253,40 @@ <return type="bool" /> <argument index="0" name="right" type="Vector3i" /> <description> + Returns [code]true[/code] if the vectors are equal. </description> </operator> <operator name="operator >"> <return type="bool" /> <argument index="0" name="right" type="Vector3i" /> <description> + Compares two [Vector3i] vectors by first checking if the X value of the left vector is greater than the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, and then with the Z values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator >="> <return type="bool" /> <argument index="0" name="right" type="Vector3i" /> <description> + Compares two [Vector3i] vectors by first checking if the X value of the left vector is greater than or equal to the X value of the [code]right[/code] vector. If the X values are exactly equal, then it repeats this check with the Y values of the two vectors, and then with the Z values. This operator is useful for sorting vectors. </description> </operator> <operator name="operator []"> <return type="int" /> <argument index="0" name="index" type="int" /> <description> + Access vector components using their index. [code]v[0][/code] is equivalent to [code]v.x[/code], [code]v[1][/code] is equivalent to [code]v.y[/code], and [code]v[2][/code] is equivalent to [code]v.z[/code]. </description> </operator> <operator name="operator unary+"> <return type="Vector3i" /> <description> + Returns the same value as if the [code]+[/code] was not there. Unary [code]+[/code] does nothing, but sometimes it can make your code more readable. </description> </operator> <operator name="operator unary-"> <return type="Vector3i" /> <description> + Returns the negative value of the [Vector3i]. This is the same as writing [code]Vector3i(-v.x, -v.y, -v.z)[/code]. This operation flips the direction of the vector while keeping the same magnitude. </description> </operator> </operators> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index e79cf0d233..8e75b474ed 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -12,8 +12,8 @@ Finally, viewports can also behave as render targets, in which case they will not be visible unless the associated texture is used to draw. </description> <tutorials> - <link title="Using Viewports">https://docs.godotengine.org/en/latest/tutorials/rendering/viewports.html</link> - <link title="Viewport and canvas transforms">https://docs.godotengine.org/en/latest/tutorials/2d/2d_transforms.html</link> + <link title="Using Viewports">$DOCS_URL/tutorials/rendering/viewports.html</link> + <link title="Viewport and canvas transforms">$DOCS_URL/tutorials/2d/2d_transforms.html</link> <link title="GUI in 3D Demo">https://godotengine.org/asset-library/asset/127</link> <link title="3D in 2D Demo">https://godotengine.org/asset-library/asset/128</link> <link title="2D in 3D Demo">https://godotengine.org/asset-library/asset/129</link> diff --git a/doc/classes/VisualShaderNode.xml b/doc/classes/VisualShaderNode.xml index b752e94490..cebe7f215f 100644 --- a/doc/classes/VisualShaderNode.xml +++ b/doc/classes/VisualShaderNode.xml @@ -7,7 +7,7 @@ Visual shader graphs consist of various nodes. Each node in the graph is a separate object and they are represented as a rectangular boxes with title and a set of properties. Each node has also connection ports that allow to connect it to another nodes and control the flow of the shader. </description> <tutorials> - <link title="VisualShaders">https://docs.godotengine.org/en/latest/tutorials/shaders/visual_shaders.html</link> + <link title="VisualShaders">$DOCS_URL/tutorials/shaders/visual_shaders.html</link> </tutorials> <methods> <method name="clear_default_input_values"> diff --git a/doc/classes/VisualShaderNodeCustom.xml b/doc/classes/VisualShaderNodeCustom.xml index b87b59c3e4..995f2796dd 100644 --- a/doc/classes/VisualShaderNodeCustom.xml +++ b/doc/classes/VisualShaderNodeCustom.xml @@ -13,7 +13,7 @@ [/codeblock] </description> <tutorials> - <link title="Visual Shader plugins">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/visual_shader_plugins.html</link> + <link title="Visual Shader plugins">$DOCS_URL/tutorials/plugins/editor/visual_shader_plugins.html</link> </tutorials> <methods> <method name="_get_category" qualifiers="virtual const"> @@ -27,8 +27,8 @@ <return type="String" /> <argument index="0" name="input_vars" type="PackedStringArray" /> <argument index="1" name="output_vars" type="String[]" /> - <argument index="2" name="mode" type="int" /> - <argument index="3" name="type" type="int" /> + <argument index="2" name="mode" type="int" enum="Shader.Mode" /> + <argument index="3" name="type" type="int" enum="VisualShader.Type" /> <description> Override this method to define the actual shader code of the associated custom node. The shader code should be returned as a string, which can have multiple lines (the [code]"""[/code] multiline string construct can be used for convenience). The [code]input_vars[/code] and [code]output_vars[/code] arrays contain the string names of the various input and output variables, as defined by [code]_get_input_*[/code] and [code]_get_output_*[/code] virtual methods in this class. @@ -46,7 +46,7 @@ </method> <method name="_get_global_code" qualifiers="virtual const"> <return type="String" /> - <argument index="0" name="mode" type="int" /> + <argument index="0" name="mode" type="int" enum="Shader.Mode" /> <description> Override this method to add shader code on top of the global shader, to define your own standard library of reusable methods, varyings, constants, uniforms, etc. The shader code should be returned as a string, which can have multiple lines (the [code]"""[/code] multiline string construct can be used for convenience). Be careful with this functionality as it can cause name conflicts with other custom nodes, so be sure to give the defined entities unique names. diff --git a/doc/classes/VisualShaderNodeInput.xml b/doc/classes/VisualShaderNodeInput.xml index 46d7dd6322..a7b501c6a0 100644 --- a/doc/classes/VisualShaderNodeInput.xml +++ b/doc/classes/VisualShaderNodeInput.xml @@ -7,7 +7,7 @@ Gives access to input variables (built-ins) available for the shader. See the shading reference for the list of available built-ins for each shader type (check [code]Tutorials[/code] section for link). </description> <tutorials> - <link title="Shading reference index">https://docs.godotengine.org/en/latest/tutorials/shaders/shader_reference/index.html</link> + <link title="Shading reference index">$DOCS_URL/tutorials/shaders/shader_reference/index.html</link> </tutorials> <methods> <method name="get_input_real_name" qualifiers="const"> diff --git a/doc/classes/VisualShaderNodeParticleMeshEmitter.xml b/doc/classes/VisualShaderNodeParticleMeshEmitter.xml new file mode 100644 index 0000000000..7abb330fd3 --- /dev/null +++ b/doc/classes/VisualShaderNodeParticleMeshEmitter.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeParticleMeshEmitter" inherits="VisualShaderNodeParticleEmitter" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <members> + <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh"> + </member> + <member name="surface_index" type="int" setter="set_surface_index" getter="get_surface_index" default="0"> + </member> + <member name="use_all_surfaces" type="bool" setter="set_use_all_surfaces" getter="is_use_all_surfaces" default="true"> + </member> + </members> +</class> diff --git a/doc/classes/VoxelGI.xml b/doc/classes/VoxelGI.xml index f6470782ee..2c3605aa1c 100644 --- a/doc/classes/VoxelGI.xml +++ b/doc/classes/VoxelGI.xml @@ -4,12 +4,13 @@ Real-time global illumination (GI) probe. </brief_description> <description> - [VoxelGI]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [VoxelGI]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked. - Having [VoxelGI]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/global_illumination/voxel_gi/quality]. - [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. + [VoxelGI]s are used to provide high-quality real-time indirect light and reflections to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [VoxelGI]s need to be baked before having a visible effect. However, once baked, dynamic objects will receive light from them. Furthermore, lights can be fully dynamic or baked. + [b]Procedural generation:[/b] [VoxelGI] can be baked in an exported project, which makes it suitable for procedurally generated or user-built levels as long as all the geometry is generated in advance. For games where geometry is generated at any time during gameplay, SDFGI is more suitable (see [member Environment.sdfgi_enabled]). + [b]Performance:[/b] [VoxelGI] is relatively demanding on the GPU and is not suited to low-end hardware such as integrated graphics (consider [LightmapGI] instead). To improve performance, adjust [member ProjectSettings.rendering/global_illumination/voxel_gi/quality] and enable [member ProjectSettings.rendering/global_illumination/gi/use_half_resolution] in the Project Settings. To provide a fallback for low-end hardware, consider adding an option to disable [VoxelGI] in your project's options menus. A [VoxelGI] node can be disabled by hiding it. + [b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. To further prevent light leaks, you can also strategically place temporary [MeshInstance3D] nodes with their [member GeometryInstance3D.gi_mode] set to [constant GeometryInstance3D.GI_MODE_BAKED]. These temporary nodes can then be hidden after baking the [VoxelGI] node. </description> <tutorials> - <link title="GI probes">https://docs.godotengine.org/en/latest/tutorials/3d/gi_probes.html</link> + <link title="GI probes">$DOCS_URL/tutorials/3d/gi_probes.html</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> </tutorials> <methods> @@ -19,6 +20,7 @@ <argument index="1" name="create_visual_debug" type="bool" default="false" /> <description> Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_BAKED] and [Light3D]s marked with either [constant Light3D.BAKE_DYNAMIC] or [constant Light3D.BAKE_STATIC]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [VoxelGI]'s data and debug any issues that may be occurring. + [b]Note:[/b] [method bake] works from the editor and in exported projects. This makes it suitable for procedurally generated or user-built levels. Baking a [VoxelGI] node generally takes from 5 to 20 seconds in most scenes. Reducing [member subdiv] can speed up baking. </description> </method> <method name="debug_bake"> @@ -50,7 +52,7 @@ Use 256 subdivisions. </constant> <constant name="SUBDIV_512" value="3" enum="Subdiv"> - Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware this could cause the GPU to stall. + Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware, this could cause the GPU to stall. </constant> <constant name="SUBDIV_MAX" value="4" enum="Subdiv"> Represents the size of the [enum Subdiv] enum. diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index 0653c8b453..f36b926bef 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -384,7 +384,7 @@ </constant> <constant name="MODE_FULLSCREEN" value="3" enum="Mode"> Fullscreen window mode. Note that this is not [i]exclusive[/i] fullscreen. On Windows and Linux, a borderless window is used to emulate fullscreen. On macOS, a new desktop is used to display the running project. - Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=https://docs.godotengine.org/en/latest/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode. + Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode. </constant> <constant name="FLAG_RESIZE_DISABLED" value="0" enum="Flags"> The window's ability to be resized. diff --git a/doc/classes/World2D.xml b/doc/classes/World2D.xml index a6a4701dd4..47ab4b3612 100644 --- a/doc/classes/World2D.xml +++ b/doc/classes/World2D.xml @@ -7,7 +7,7 @@ Class that has everything pertaining to a 2D world. A physics space, a visual scenario and a sound space. 2D nodes register their resources into the current 2D world. </description> <tutorials> - <link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link> + <link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link> </tutorials> <members> <member name="canvas" type="RID" setter="" getter="get_canvas"> diff --git a/doc/classes/World3D.xml b/doc/classes/World3D.xml index 136ca2c598..fd2f96985c 100644 --- a/doc/classes/World3D.xml +++ b/doc/classes/World3D.xml @@ -7,7 +7,7 @@ Class that has everything pertaining to a world. A physics space, a visual scenario and a sound space. Node3D nodes register their resources into the current world. </description> <tutorials> - <link title="Ray-casting">https://docs.godotengine.org/en/latest/tutorials/physics/ray-casting.html</link> + <link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link> </tutorials> <members> <member name="camera_effects" type="CameraEffects" setter="set_camera_effects" getter="get_camera_effects"> diff --git a/doc/classes/WorldEnvironment.xml b/doc/classes/WorldEnvironment.xml index bd25a74c5b..793479e074 100644 --- a/doc/classes/WorldEnvironment.xml +++ b/doc/classes/WorldEnvironment.xml @@ -9,7 +9,7 @@ The [WorldEnvironment] allows the user to specify default lighting parameters (e.g. ambient lighting), various post-processing effects (e.g. SSAO, DOF, Tonemapping), and how to draw the background (e.g. solid color, skybox). Usually, these are added in order to improve the realism/color balance of the scene. </description> <tutorials> - <link title="Environment and post-processing">https://docs.godotengine.org/en/latest/tutorials/3d/environment_and_post_processing.html</link> + <link title="Environment and post-processing">$DOCS_URL/tutorials/3d/environment_and_post_processing.html</link> <link title="3D Material Testers Demo">https://godotengine.org/asset-library/asset/123</link> <link title="2D HDR Demo">https://godotengine.org/asset-library/asset/110</link> <link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link> diff --git a/doc/classes/XRCamera3D.xml b/doc/classes/XRCamera3D.xml index 31f05ca06c..ca81f5b169 100644 --- a/doc/classes/XRCamera3D.xml +++ b/doc/classes/XRCamera3D.xml @@ -8,6 +8,6 @@ The position and orientation of this node is automatically updated by the XR Server to represent the location of the HMD if such tracking is available and can thus be used by game logic. Note that, in contrast to the XR Controller, the render thread has access to the most up-to-date tracking data of the HMD and the location of the XRCamera3D can lag a few milliseconds behind what is used for rendering as a result. </description> <tutorials> - <link title="VR documentation index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> + <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> </tutorials> </class> diff --git a/doc/classes/XRController3D.xml b/doc/classes/XRController3D.xml index eb91196e00..0e2785f246 100644 --- a/doc/classes/XRController3D.xml +++ b/doc/classes/XRController3D.xml @@ -10,7 +10,7 @@ As many XR runtimes now use a configurable action map all inputs are named. </description> <tutorials> - <link title="VR documentation index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> + <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> </tutorials> <methods> <method name="get_axis" qualifiers="const"> diff --git a/doc/classes/XRInterface.xml b/doc/classes/XRInterface.xml index 7ae70f97a2..3b03447ed1 100644 --- a/doc/classes/XRInterface.xml +++ b/doc/classes/XRInterface.xml @@ -8,7 +8,7 @@ Interfaces should be written in such a way that simply enabling them will give us a working setup. You can query the available interfaces through [XRServer]. </description> <tutorials> - <link title="VR documentation index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> + <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> </tutorials> <methods> <method name="get_camera_feed_id"> diff --git a/doc/classes/XROrigin3D.xml b/doc/classes/XROrigin3D.xml index 0d8acfeb1b..fc15102976 100644 --- a/doc/classes/XROrigin3D.xml +++ b/doc/classes/XROrigin3D.xml @@ -10,7 +10,7 @@ For example, if your character is driving a car, the XROrigin3D node should be a child node of this car. Or, if you're implementing a teleport system to move your character, you should change the position of this node. </description> <tutorials> - <link title="VR documentation index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> + <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> </tutorials> <members> <member name="world_scale" type="float" setter="set_world_scale" getter="get_world_scale" default="1.0"> diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml index bd6a518835..439bcfc382 100644 --- a/doc/classes/XRPositionalTracker.xml +++ b/doc/classes/XRPositionalTracker.xml @@ -9,7 +9,7 @@ The [XRController3D] and [XRAnchor3D] both consume objects of this type and should be used in your project. The positional trackers are just under-the-hood objects that make this all work. These are mostly exposed so that GDExtension-based interfaces can interact with them. </description> <tutorials> - <link title="VR documentation index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> + <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> </tutorials> <methods> <method name="get_input" qualifiers="const"> diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml index 87164ebb52..3a7fdea8d0 100644 --- a/doc/classes/XRServer.xml +++ b/doc/classes/XRServer.xml @@ -7,7 +7,7 @@ The AR/VR server is the heart of our Advanced and Virtual Reality solution and handles all the processing. </description> <tutorials> - <link title="VR documentation index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> + <link title="VR documentation index">$DOCS_URL/tutorials/vr/index.html</link> </tutorials> <methods> <method name="add_interface"> diff --git a/doc/classes/float.xml b/doc/classes/float.xml index 8231173bac..c96360e6ba 100644 --- a/doc/classes/float.xml +++ b/doc/classes/float.xml @@ -72,7 +72,7 @@ <return type="Quaternion" /> <argument index="0" name="right" type="Quaternion" /> <description> - Multiplies each component of the [Quaternion] by the given [float]. + Multiplies each component of the [Quaternion] by the given [float]. This operation is not meaningful on its own, but it can be used as a part of a larger expression. </description> </operator> <operator name="operator *"> @@ -81,7 +81,7 @@ <description> Multiplies each component of the [Vector2] by the given [float]. [codeblock] - print(2.5 * Vector2(1, 1)) # Vector2(2.5, 2.5) + print(2.5 * Vector2(1, 3)) # Prints "(2.5, 7.5)" [/codeblock] </description> </operator> @@ -89,9 +89,9 @@ <return type="Vector2i" /> <argument index="0" name="right" type="Vector2i" /> <description> - Multiplies each component of the [Vector2i] by the given [float]. + Multiplies each component of the [Vector2i] by the given [float] truncated to an integer. [codeblock] - print(2.0 * Vector2i(1, 1)) # Vector2i(2.0, 2.0) + print(0.9 * Vector2i(10, 20)) # Prints "(0, 0)" [/codeblock] </description> </operator> @@ -106,7 +106,10 @@ <return type="Vector3i" /> <argument index="0" name="right" type="Vector3i" /> <description> - Multiplies each component of the [Vector3i] by the given [float]. + Multiplies each component of the [Vector3i] by the given [float] truncated to an integer. + [codeblock] + print(0.9 * Vector3i(10, 20, 30)) # Prints "(0, 0, 0)" + [/codeblock] </description> </operator> <operator name="operator *"> diff --git a/doc/classes/int.xml b/doc/classes/int.xml index 94c2601e4a..bb36d83741 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -91,11 +91,11 @@ <return type="int" /> <argument index="0" name="right" type="int" /> <description> - Returns the result of the modulo operator for two integers, i.e. the remainder after dividing both numbers. + Returns the remainder after dividing two integers. This operation uses truncated division, which is often not desired as it does not work well with negative numbers. Consider using [method @GlobalScope.posmod] instead if you want to handle negative numbers. [codeblock] print(5 % 2) # 1 print(12 % 4) # 0 - print(12 % 2) # 2 + print(-5 % 3) # -2 [/codeblock] </description> </operator> @@ -121,12 +121,14 @@ <return type="Color" /> <argument index="0" name="right" type="Color" /> <description> + Multiplies each component of the [Color] by the given [int]. </description> </operator> <operator name="operator *"> <return type="Quaternion" /> <argument index="0" name="right" type="Quaternion" /> <description> + Multiplies each component of the [Quaternion] by the given [int]. This operation is not meaningful on its own, but it can be used as a part of a larger expression. </description> </operator> <operator name="operator *"> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index fe8083f218..5d3167a773 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -11,10 +11,8 @@ from collections import OrderedDict # Uncomment to do type checks. I have it commented out so it works below Python 3.5 # from typing import List, Dict, TextIO, Tuple, Iterable, Optional, DefaultDict, Any, Union -# http(s)://docs.godotengine.org/<langcode>/<tag>/path/to/page.html(#fragment-tag) -GODOT_DOCS_PATTERN = re.compile( - r"^http(?:s)?://docs\.godotengine\.org/(?:[a-zA-Z0-9.\-_]*)/(?:[a-zA-Z0-9.\-_]*)/(.*)\.html(#.*)?$" -) +# $DOCS_URL/path/to/page.html(#fragment-tag) +GODOT_DOCS_PATTERN = re.compile(r"^\$DOCS_URL/(.*)\.html(#.*)?$") def print_error(error, state): # type: (str, State) -> None @@ -857,16 +855,11 @@ def rstize_text(text, state): # type: (str, State) -> str # Handle [tags] inside_code = False - inside_url = False - url_has_name = False - url_link = "" pos = 0 tag_depth = 0 previous_pos = 0 while True: pos = text.find("[", pos) - if inside_url and (pos > previous_pos): - url_has_name = True if pos == -1: break @@ -995,17 +988,23 @@ def rstize_text(text, state): # type: (str, State) -> str elif cmd.find("image=") == 0: tag_text = "" # '![](' + cmd[6:] + ')' elif cmd.find("url=") == 0: - url_link = cmd[4:] - tag_text = "`" - tag_depth += 1 - inside_url = True - url_has_name = False - elif cmd == "/url": - tag_text = ("" if url_has_name else url_link) + " <" + url_link + ">`__" - tag_depth -= 1 - escape_post = True - inside_url = False - url_has_name = False + # URLs are handled in full here as we need to extract the optional link + # title to use `make_link`. + link_url = cmd[4:] + endurl_pos = text.find("[/url]", endq_pos + 1) + if endurl_pos == -1: + print_error( + "Tag depth mismatch for [url]: no closing [/url], file: {}".format(state.current_class), state + ) + break + link_title = text[endq_pos + 1 : endurl_pos] + tag_text = make_link(link_url, link_title) + + pre_text = text[:pos] + text = pre_text + tag_text + text[endurl_pos + 6 :] + pos = len(pre_text) + len(tag_text) + previous_pos = pos + continue elif cmd == "center": tag_depth += 1 tag_text = "" @@ -1252,21 +1251,22 @@ def make_link(url, title): # type: (str, str) -> str if match.lastindex == 2: # Doc reference with fragment identifier: emit direct link to section with reference to page, for example: # `#calling-javascript-from-script in Exporting For Web` - return "`" + groups[1] + " <../" + groups[0] + ".html" + groups[1] + ">`_ in :doc:`../" + groups[0] + "`" - # Commented out alternative: Instead just emit: - # `Subsection in Exporting For Web` - # return "`Subsection <../" + groups[0] + ".html" + groups[1] + ">`__ in :doc:`../" + groups[0] + "`" + # Or use the title if provided. + if title != "": + return "`" + title + " <../" + groups[0] + ".html" + groups[1] + ">`__" + return "`" + groups[1] + " <../" + groups[0] + ".html" + groups[1] + ">`__ in :doc:`../" + groups[0] + "`" elif match.lastindex == 1: # Doc reference, for example: # `Math` + if title != "": + return ":doc:`" + title + " <../" + groups[0] + ">`" return ":doc:`../" + groups[0] + "`" else: # External link, for example: # `http://enet.bespin.org/usergroup0.html` if title != "": return "`" + title + " <" + url + ">`__" - else: - return "`" + url + " <" + url + ">`__" + return "`" + url + " <" + url + ">`__" def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 8a070313f8..4759a2b0d0 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1871,31 +1871,38 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn } } -void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { +void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); - if (p_texture.is_valid()) { - shader->default_textures[p_name] = p_texture; + if (!p_texture.is_valid()) { + if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) { + shader->default_textures[p_name].erase(p_index); + + if (shader->default_textures[p_name].is_empty()) { + shader->default_textures.erase(p_name); + } + } } else { - shader->default_textures.erase(p_name); + if (!shader->default_textures.has(p_name)) { + shader->default_textures[p_name] = Map<int, RID>(); + } + shader->default_textures[p_name][p_index] = p_texture; } _shader_make_dirty(shader); } -RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { +RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { const Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, RID()); - const Map<StringName, RID>::Element *E = shader->default_textures.find(p_name); - - if (!E) { - return RID(); + if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) { + return shader->default_textures[p_name][p_index]; } - return E->get(); + return RID(); } void RasterizerStorageGLES3::shader_add_custom_define(RID p_shader, const String &p_define) { @@ -2195,10 +2202,11 @@ void RasterizerStorageGLES3::_update_material(Material *p_material) { } if (!texture.is_valid()) { - Map<StringName, RID>::Element *W = p_material->shader->default_textures.find(E->key()); + Map<StringName, Map<int, RID>>::Element *W = p_material->shader->default_textures.find(E->key()); - if (W) { - texture = W->get(); + // TODO: make texture uniform array properly works with GLES3 + if (W && W->get().has(0)) { + texture = W->get()[0]; } } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index eb5614f70f..3f9f208964 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -580,7 +580,7 @@ public: SelfList<Shader> dirty_list; - Map<StringName, RID> default_textures; + Map<StringName, Map<int, RID>> default_textures; Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints; @@ -706,8 +706,8 @@ public: String shader_get_code(RID p_shader) const override; void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override; - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override; + void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override; + RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override; RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index 3b2f078120..403feb149e 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -121,6 +121,12 @@ const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient); static bool default_render_device_changed = false; static bool default_capture_device_changed = false; +// Silence warning due to a COM API weirdness (GH-35194). +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + class CMMNotificationClient : public IMMNotificationClient { LONG _cRef = 1; IMMDeviceEnumerator *_pEnumerator = nullptr; @@ -162,7 +168,7 @@ public: HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) { return S_OK; - }; + } HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) { return S_OK; @@ -189,6 +195,10 @@ public: } }; +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + static CMMNotificationClient notif_client; Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool reinit) { @@ -373,18 +383,21 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, nullptr); ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + "."); UINT32 max_frames; - HRESULT hr = p_device->audio_client->GetBufferSize(&max_frames); + hr = p_device->audio_client->GetBufferSize(&max_frames); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Due to WASAPI Shared Mode we have no control of the buffer size - buffer_frames = max_frames; - - int64_t latency = 0; - audio_output.audio_client->GetStreamLatency(&latency); - // WASAPI REFERENCE_TIME units are 100 nanoseconds per unit - // https://docs.microsoft.com/en-us/windows/win32/directshow/reference-time - // Convert REFTIME to seconds as godot uses for latency - real_latency = (float)latency / (float)REFTIMES_PER_SEC; + if (!p_capture) { + buffer_frames = max_frames; + + int64_t latency = 0; + audio_output.audio_client->GetStreamLatency(&latency); + // WASAPI REFERENCE_TIME units are 100 nanoseconds per unit + // https://docs.microsoft.com/en-us/windows/win32/directshow/reference-time + // Convert REFTIME to seconds as godot uses for latency + real_latency = (float)latency / (float)REFTIMES_PER_SEC; + } + } else { IAudioClient3 *device_audio_client_3 = (IAudioClient3 *)p_device->audio_client; diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 519dd654ef..3ca3576de6 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -36,8 +36,8 @@ ///////////////////////////////////////// -// Maps to 2*axis if value is neg, or + 1 if value is pos. -static const char *_joy_axis_descriptions[JOY_AXIS_MAX * 2] = { +// Maps to 2*axis if value is neg, or 2*axis+1 if value is pos. +static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = { TTRC("Left Stick Left, Joystick 0 Left"), TTRC("Left Stick Right, Joystick 0 Right"), TTRC("Left Stick Up, Joystick 0 Up"), @@ -67,11 +67,11 @@ String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_ev Ref<InputEventJoypadMotion> jpmotion = p_event; if (jpmotion.is_valid()) { String desc = TTR("Unknown Joypad Axis"); - if (jpmotion->get_axis() < JOY_AXIS_MAX) { - desc = RTR(_joy_axis_descriptions[2 * jpmotion->get_axis() + (jpmotion->get_axis_value() < 0 ? 0 : 1)]); + if (jpmotion->get_axis() < JoyAxis::MAX) { + desc = RTR(_joy_axis_descriptions[2 * (size_t)jpmotion->get_axis() + (jpmotion->get_axis_value() < 0 ? 0 : 1)]); } - return vformat("Joypad Axis %s %s (%s)", itos(jpmotion->get_axis()), jpmotion->get_axis_value() < 0 ? "-" : "+", desc); + return vformat("Joypad Axis %s %s (%s)", itos((int64_t)jpmotion->get_axis()), jpmotion->get_axis_value() < 0 ? "-" : "+", desc); } else { return p_event->as_text(); } @@ -108,7 +108,7 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) { if (k.is_valid()) { show_phys_key = true; - physical_key_checkbox->set_pressed(k->get_physical_keycode() != 0 && k->get_keycode() == 0); + physical_key_checkbox->set_pressed(k->get_physical_keycode() != Key::NONE && k->get_keycode() == Key::NONE); } else if (joyb.is_valid() || joym.is_valid() || mb.is_valid()) { show_device = true; @@ -260,7 +260,7 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> & return; } else { // Always make the value 1 or -1 for display consistency - joym->set_axis_value(SGN(axis_value)); + joym->set_axis_value(SIGN(axis_value)); } } @@ -268,9 +268,9 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> & k->set_pressed(false); // to avoid serialisation of 'pressed' property - doesn't matter for actions anyway. // Maintain physical keycode option state if (physical_key_checkbox->is_pressed()) { - k->set_keycode(KEY_NONE); + k->set_keycode(Key::NONE); } else { - k->set_physical_keycode(KEY_NONE); + k->set_physical_keycode(Key::NONE); } } @@ -325,7 +325,7 @@ void InputEventConfigurationDialog::_update_input_list() { mouse_root->set_collapsed(collapse); mouse_root->set_meta("__type", INPUT_MOUSE_BUTTON); - MouseButton mouse_buttons[9] = { MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_WHEEL_UP, MOUSE_BUTTON_WHEEL_DOWN, MOUSE_BUTTON_WHEEL_LEFT, MOUSE_BUTTON_WHEEL_RIGHT, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_XBUTTON2 }; + MouseButton mouse_buttons[9] = { MouseButton::LEFT, MouseButton::RIGHT, MouseButton::MIDDLE, MouseButton::WHEEL_UP, MouseButton::WHEEL_DOWN, MouseButton::WHEEL_LEFT, MouseButton::WHEEL_RIGHT, MouseButton::MB_XBUTTON1, MouseButton::MB_XBUTTON2 }; for (int i = 0; i < 9; i++) { Ref<InputEventMouseButton> mb; mb.instantiate(); @@ -349,7 +349,7 @@ void InputEventConfigurationDialog::_update_input_list() { joyb_root->set_collapsed(collapse); joyb_root->set_meta("__type", INPUT_JOY_BUTTON); - for (int i = 0; i < JOY_BUTTON_MAX; i++) { + for (int i = 0; i < (int)JoyButton::MAX; i++) { Ref<InputEventJoypadButton> joyb; joyb.instantiate(); joyb->set_button_index((JoyButton)i); @@ -372,7 +372,7 @@ void InputEventConfigurationDialog::_update_input_list() { joya_root->set_collapsed(collapse); joya_root->set_meta("__type", INPUT_JOY_MOTION); - for (int i = 0; i < JOY_AXIS_MAX * 2; i++) { + for (int i = 0; i < (int)JoyAxis::MAX * 2; i++) { int axis = i / 2; int direction = (i & 1) ? 1 : -1; Ref<InputEventJoypadMotion> joym; @@ -453,10 +453,10 @@ void InputEventConfigurationDialog::_physical_keycode_toggled(bool p_checked) { if (p_checked) { k->set_physical_keycode(k->get_keycode()); - k->set_keycode(KEY_NONE); + k->set_keycode(Key::NONE); } else { k->set_keycode((Key)k->get_physical_keycode()); - k->set_physical_keycode(KEY_NONE); + k->set_physical_keycode(Key::NONE); } _set_event(k); @@ -480,9 +480,9 @@ void InputEventConfigurationDialog::_input_list_item_selected() { if (physical_key_checkbox->is_pressed()) { k->set_physical_keycode(keycode); - k->set_keycode(KEY_NONE); + k->set_keycode(Key::NONE); } else { - k->set_physical_keycode(KEY_NONE); + k->set_physical_keycode(Key::NONE); k->set_keycode(keycode); } diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 02b4a12b92..f7f88ad0d5 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -187,7 +187,7 @@ void AnimationBezierTrackEdit::_draw_line_clipped(const Vector2 &p_from, const V Vector2 from = p_from; Vector2 to = p_to; - if (from.x == to.x) { + if (from.x == to.x && from.y == to.y) { return; } if (to.x < from.x) { @@ -222,11 +222,6 @@ void AnimationBezierTrackEdit::_notification(int p_what) { bezier_icon = get_theme_icon(SNAME("KeyBezierPoint"), SNAME("EditorIcons")); bezier_handle_icon = get_theme_icon(SNAME("KeyBezierHandle"), SNAME("EditorIcons")); selected_icon = get_theme_icon(SNAME("KeyBezierSelected"), SNAME("EditorIcons")); - if (handle_mode_option->get_item_count() == 0) { - handle_mode_option->add_icon_item(get_theme_icon(SNAME("BezierHandlesFree"), SNAME("EditorIcons")), TTR("Free"), HANDLE_MODE_FREE); - handle_mode_option->add_icon_item(get_theme_icon(SNAME("BezierHandlesBalanced"), SNAME("EditorIcons")), TTR("Balanced"), HANDLE_MODE_BALANCED); - handle_mode_option->add_icon_item(get_theme_icon(SNAME("BezierHandlesMirror"), SNAME("EditorIcons")), TTR("Mirror"), HANDLE_MODE_MIRROR); - } } if (p_what == NOTIFICATION_RESIZED) { int right_limit = get_size().width - timeline->get_buttons_width(); @@ -420,9 +415,9 @@ void AnimationBezierTrackEdit::_notification(int p_what) { //draw editor handles { - float scale = timeline->get_zoom_scale(); edit_points.clear(); + float scale = timeline->get_zoom_scale(); for (int i = 0; i < animation->track_get_key_count(track); i++) { float offset = animation->track_get_key_time(track, i); float value = animation->bezier_track_get_key_value(track, i); @@ -438,7 +433,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { if (moving_handle != 0 && moving_handle_key == i) { in_vec = moving_handle_left; } - Vector2 pos_in = Vector2(((offset + in_vec.x) - timeline->get_value()) * scale + limit, _bezier_h_to_pixel(value + in_vec.y)); + Vector2 pos_in(((offset + in_vec.x) - timeline->get_value()) * scale + limit, _bezier_h_to_pixel(value + in_vec.y)); Vector2 out_vec = animation->bezier_track_get_key_out_handle(track, i); @@ -446,7 +441,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { out_vec = moving_handle_right; } - Vector2 pos_out = Vector2(((offset + out_vec.x) - timeline->get_value()) * scale + limit, _bezier_h_to_pixel(value + out_vec.y)); + Vector2 pos_out(((offset + out_vec.x) - timeline->get_value()) * scale + limit, _bezier_h_to_pixel(value + out_vec.y)); _draw_line_clipped(pos, pos_in, accent, limit, right_limit); _draw_line_clipped(pos, pos_out, accent, limit, right_limit); @@ -581,11 +576,21 @@ void AnimationBezierTrackEdit::_clear_selection() { update(); } +void AnimationBezierTrackEdit::_change_selected_keys_handle_mode(Animation::HandleMode p_mode) { + undo_redo->create_action(TTR("Update Selected Key Handles")); + double ratio = timeline->get_zoom_scale() * v_zoom; + for (Set<int>::Element *E = selection.back(); E; E = E->prev()) { + const int key_index = E->get(); + undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_handle_mode", track, key_index, animation->bezier_track_get_key_handle_mode(track, key_index), ratio); + undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_handle_mode", track, key_index, p_mode, ratio); + } + undo_redo->commit_action(); +} + void AnimationBezierTrackEdit::_clear_selection_for_anim(const Ref<Animation> &p_anim) { if (!(animation == p_anim)) { return; } - //selection.clear(); _clear_selection(); } @@ -618,7 +623,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { const float v_zoom_orig = v_zoom; if (mb->is_command_pressed()) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); @@ -631,7 +636,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { update(); } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { const float v_zoom_orig = v_zoom; if (mb->is_command_pressed()) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); @@ -644,7 +649,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { update(); } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::MIDDLE) { if (mb->is_pressed()) { int x = mb->get_position().x - timeline->get_name_limit(); panning_timeline_from = x / timeline->get_zoom_scale(); @@ -655,7 +660,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { menu_insert_key = mb->get_position(); if (menu_insert_key.x >= timeline->get_name_limit() && menu_insert_key.x <= get_size().width - timeline->get_buttons_width()) { Vector2 popup_pos = get_global_transform().xform(mb->get_position()); @@ -667,6 +672,9 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { menu->add_icon_item(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE); menu->add_separator(); menu->add_icon_item(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Delete Selected Key(s)"), MENU_KEY_DELETE); + menu->add_separator(); + menu->add_icon_item(get_theme_icon(SNAME("BezierHandlesFree"), SNAME("EditorIcons")), TTR("Make Handles Free"), MENU_KEY_SET_HANDLE_FREE); + menu->add_icon_item(get_theme_icon(SNAME("BezierHandlesBalanced"), SNAME("EditorIcons")), TTR("Make Handles Balanced"), MENU_KEY_SET_HANDLE_BALANCED); } menu->set_as_minsize(); @@ -675,11 +683,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { - if (close_icon_rect.has_point(mb->get_position())) { - emit_signal(SNAME("close_request")); - return; - } + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { for (const KeyValue<int, Rect2> &E : subtracks) { if (E.value.has_point(mb->get_position())) { set_animation_and_track(animation, E.key); @@ -746,7 +750,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { //insert new point if (mb->is_command_pressed() && mb->get_position().x >= timeline->get_name_limit() && mb->get_position().x < get_size().width - timeline->get_buttons_width()) { Array new_point; - new_point.resize(5); + new_point.resize(6); float h = (get_size().height / 2 - mb->get_position().y) * v_zoom + v_scroll; @@ -755,6 +759,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { new_point[2] = 0; new_point[3] = 0.25; new_point[4] = 0; + new_point[5] = 0; float time = ((mb->get_position().x - timeline->get_name_limit()) / timeline->get_zoom_scale()) + timeline->get_value(); while (animation->track_find_key(track, time, true) != -1) { @@ -792,7 +797,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } } - if (box_selecting_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (box_selecting_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (box_selecting) { //do actual select if (!box_selecting_add) { @@ -822,7 +827,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { update(); } - if (moving_handle != 0 && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (moving_handle != 0 && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { undo_redo->create_action(TTR("Move Bezier Points")); undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_in_handle", track, moving_handle_key, moving_handle_left); undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, moving_handle_key, moving_handle_right); @@ -834,7 +839,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { update(); } - if (moving_selection_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (moving_selection_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (moving_selection) { //combit it @@ -929,7 +934,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { v_scroll += mm->get_relative().y * v_zoom; if (v_scroll > 100000) { v_scroll = 100000; @@ -986,33 +991,49 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) { if (moving_handle == -1) { moving_handle_left = moving_handle_value; - if (moving_handle_left.x > 0) { - moving_handle_left.x = 0; - } - if (handle_mode_option->get_selected() == HANDLE_MODE_BALANCED) { - Vector2 scale = Vector2(timeline->get_zoom_scale(), v_zoom); - moving_handle_right = (-(moving_handle_left * scale).normalized() * (moving_handle_right * scale).length()) / scale; + if (animation->bezier_track_get_key_handle_mode(track, moving_handle_key) == Animation::HANDLE_MODE_BALANCED) { + double ratio = timeline->get_zoom_scale() * v_zoom; + Transform2D xform; + xform.set_scale(Vector2(1.0, 1.0 / ratio)); - } else if (handle_mode_option->get_selected() == HANDLE_MODE_MIRROR) { - moving_handle_right = -moving_handle_left; - } - } + Vector2 vec_out = xform.xform(moving_handle_right); + Vector2 vec_in = xform.xform(moving_handle_left); - if (moving_handle == 1) { - moving_handle_right = moving_handle_value; - if (moving_handle_right.x < 0) { - moving_handle_right.x = 0; + moving_handle_right = xform.affine_inverse().xform(-vec_in.normalized() * vec_out.length()); } + } else if (moving_handle == 1) { + moving_handle_right = moving_handle_value; + + if (animation->bezier_track_get_key_handle_mode(track, moving_handle_key) == Animation::HANDLE_MODE_BALANCED) { + double ratio = timeline->get_zoom_scale() * v_zoom; + Transform2D xform; + xform.set_scale(Vector2(1.0, 1.0 / ratio)); - if (handle_mode_option->get_selected() == HANDLE_MODE_BALANCED) { - Vector2 scale = Vector2(timeline->get_zoom_scale(), v_zoom); - moving_handle_left = (-(moving_handle_right * scale).normalized() * (moving_handle_left * scale).length()) / scale; - } else if (handle_mode_option->get_selected() == HANDLE_MODE_MIRROR) { - moving_handle_left = -moving_handle_right; + Vector2 vec_in = xform.xform(moving_handle_left); + Vector2 vec_out = xform.xform(moving_handle_right); + + moving_handle_left = xform.affine_inverse().xform(-vec_out.normalized() * vec_in.length()); } } + update(); + } + + bool is_finishing_key_handle_drag = moving_handle != 0 && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT; + if (is_finishing_key_handle_drag) { + undo_redo->create_action(TTR("Move Bezier Points")); + if (moving_handle == -1) { + double ratio = timeline->get_zoom_scale() * v_zoom; + undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_in_handle", track, moving_handle_key, moving_handle_left, ratio); + undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_in_handle", track, moving_handle_key, animation->bezier_track_get_key_in_handle(track, moving_handle_key), ratio); + } else if (moving_handle == 1) { + double ratio = timeline->get_zoom_scale() * v_zoom; + undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, moving_handle_key, moving_handle_right, ratio); + undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_out_handle", track, moving_handle_key, animation->bezier_track_get_key_out_handle(track, moving_handle_key), ratio); + } + undo_redo->commit_action(); + moving_handle = 0; update(); } } @@ -1021,7 +1042,7 @@ void AnimationBezierTrackEdit::_menu_selected(int p_index) { switch (p_index) { case MENU_KEY_INSERT: { Array new_point; - new_point.resize(5); + new_point.resize(6); float h = (get_size().height / 2 - menu_insert_key.y) * v_zoom + v_scroll; @@ -1030,6 +1051,7 @@ void AnimationBezierTrackEdit::_menu_selected(int p_index) { new_point[2] = 0; new_point[3] = 0.25; new_point[4] = 0; + new_point[5] = Animation::HANDLE_MODE_BALANCED; float time = ((menu_insert_key.x - timeline->get_name_limit()) / timeline->get_zoom_scale()) + timeline->get_value(); while (animation->track_find_key(track, time, true) != -1) { @@ -1048,6 +1070,12 @@ void AnimationBezierTrackEdit::_menu_selected(int p_index) { case MENU_KEY_DELETE: { delete_selection(); } break; + case MENU_KEY_SET_HANDLE_FREE: { + _change_selected_keys_handle_mode(Animation::HANDLE_MODE_FREE); + } break; + case MENU_KEY_SET_HANDLE_BALANCED: { + _change_selected_keys_handle_mode(Animation::HANDLE_MODE_BALANCED); + } break; } } @@ -1118,6 +1146,7 @@ void AnimationBezierTrackEdit::delete_selection() { undo_redo->add_do_method(this, "_clear_selection_for_anim", animation); undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation); undo_redo->commit_action(); + //selection.clear(); } } @@ -1150,8 +1179,6 @@ AnimationBezierTrackEdit::AnimationBezierTrackEdit() { set_focus_mode(FOCUS_CLICK); set_clip_contents(true); - handle_mode = HANDLE_MODE_FREE; - handle_mode_option = memnew(OptionButton); close_button = memnew(Button); close_button->connect("pressed", Callable(this, SNAME("emit_signal")), varray(SNAME("close_request"))); @@ -1160,7 +1187,6 @@ AnimationBezierTrackEdit::AnimationBezierTrackEdit() { right_column = memnew(VBoxContainer); right_column->add_child(close_button); right_column->add_spacer(); - right_column->add_child(handle_mode_option); add_child(right_column); menu = memnew(PopupMenu); diff --git a/editor/animation_bezier_editor.h b/editor/animation_bezier_editor.h index 578c6f9337..4b46777cfe 100644 --- a/editor/animation_bezier_editor.h +++ b/editor/animation_bezier_editor.h @@ -36,21 +36,14 @@ class AnimationBezierTrackEdit : public Control { GDCLASS(AnimationBezierTrackEdit, Control); - enum HandleMode { - HANDLE_MODE_FREE, - HANDLE_MODE_BALANCED, - HANDLE_MODE_MIRROR - }; - enum { MENU_KEY_INSERT, MENU_KEY_DUPLICATE, - MENU_KEY_DELETE + MENU_KEY_DELETE, + MENU_KEY_SET_HANDLE_FREE, + MENU_KEY_SET_HANDLE_BALANCED, }; - HandleMode handle_mode; - OptionButton *handle_mode_option; - VBoxContainer *right_column; Button *close_button; @@ -69,8 +62,6 @@ class AnimationBezierTrackEdit : public Control { Ref<Texture2D> bezier_handle_icon; Ref<Texture2D> selected_icon; - Rect2 close_icon_rect; - Map<int, Rect2> subtracks; float v_scroll = 0; @@ -104,10 +95,12 @@ class AnimationBezierTrackEdit : public Control { int moving_handle_key = 0; Vector2 moving_handle_left; Vector2 moving_handle_right; + int moving_handle_mode; // value from Animation::HandleMode void _clear_selection(); void _clear_selection_for_anim(const Ref<Animation> &p_anim); void _select_at_anim(const Ref<Animation> &p_anim, int p_track, float p_pos); + void _change_selected_keys_handle_mode(Animation::HandleMode p_mode); Vector2 menu_insert_key; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index a85a4450a6..6fce55f8e3 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -334,6 +334,22 @@ public: setting = false; return true; } + + if (name == "handle_mode") { + const Variant &value = p_value; + + setting = true; + undo_redo->create_action(TTR("Anim Change Keyframe Value"), UndoRedo::MERGE_ENDS); + int prev = animation->bezier_track_get_key_handle_mode(track, key); + undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_handle_mode", track, key, value); + undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_handle_mode", track, key, prev); + undo_redo->add_do_method(this, "_update_obj", animation); + undo_redo->add_undo_method(this, "_update_obj", animation); + undo_redo->commit_action(); + + setting = false; + return true; + } } break; case Animation::TYPE_AUDIO: { if (name == "stream") { @@ -498,6 +514,11 @@ public: return true; } + if (name == "handle_mode") { + r_ret = animation->bezier_track_get_key_handle_mode(track, key); + return true; + } + } break; case Animation::TYPE_AUDIO: { if (name == "stream") { @@ -610,6 +631,7 @@ public: p_list->push_back(PropertyInfo(Variant::FLOAT, "value")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "in_handle")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "out_handle")); + p_list->push_back(PropertyInfo(Variant::INT, "handle_mode", PROPERTY_HINT_ENUM, "Free,Balanced")); } break; case Animation::TYPE_AUDIO: { @@ -949,6 +971,17 @@ public: undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_out_handle", track, key, value); undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_out_handle", track, key, prev); update_obj = true; + } else if (name == "handle_mode") { + const Variant &value = p_value; + + if (!setting) { + setting = true; + undo_redo->create_action(TTR("Anim Multi Change Keyframe Value"), UndoRedo::MERGE_ENDS); + } + int prev = animation->bezier_track_get_key_handle_mode(track, key); + undo_redo->add_do_method(animation.ptr(), "bezier_track_set_key_handle_mode", track, key, value); + undo_redo->add_undo_method(animation.ptr(), "bezier_track_set_key_handle_mode", track, key, prev); + update_obj = true; } } break; case Animation::TYPE_AUDIO: { @@ -1120,6 +1153,11 @@ public: return true; } + if (name == "handle_mode") { + r_ret = animation->bezier_track_get_key_handle_mode(track, key); + return true; + } + } break; case Animation::TYPE_AUDIO: { if (name == "stream") { @@ -1273,6 +1311,7 @@ public: p_list->push_back(PropertyInfo(Variant::FLOAT, "value")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "in_handle")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "out_handle")); + p_list->push_back(PropertyInfo(Variant::INT, "handle_mode", PROPERTY_HINT_ENUM, "Free,Balanced")); } break; case Animation::TYPE_AUDIO: { p_list->push_back(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream")); @@ -1377,8 +1416,20 @@ void AnimationTimelineEdit::_anim_length_changed(double p_new_len) { void AnimationTimelineEdit::_anim_loop_pressed() { undo_redo->create_action(TTR("Change Animation Loop")); - undo_redo->add_do_method(animation.ptr(), "set_loop", loop->is_pressed()); - undo_redo->add_undo_method(animation.ptr(), "set_loop", animation->has_loop()); + switch (animation->get_loop_mode()) { + case Animation::LoopMode::LOOP_NONE: { + undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LoopMode::LOOP_LINEAR); + } break; + case Animation::LoopMode::LOOP_LINEAR: { + undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LoopMode::LOOP_PINGPONG); + } break; + case Animation::LoopMode::LOOP_PINGPONG: { + undo_redo->add_do_method(animation.ptr(), "set_loop_mode", Animation::LoopMode::LOOP_NONE); + } break; + default: + break; + } + undo_redo->add_undo_method(animation.ptr(), "set_loop_mode", animation->get_loop_mode()); undo_redo->commit_action(); } @@ -1664,7 +1715,24 @@ void AnimationTimelineEdit::update_values() { length->set_tooltip(TTR("Animation length (seconds)")); time_icon->set_tooltip(TTR("Animation length (seconds)")); } - loop->set_pressed(animation->has_loop()); + + switch (animation->get_loop_mode()) { + case Animation::LoopMode::LOOP_NONE: { + loop->set_icon(get_theme_icon("Loop", "EditorIcons")); + loop->set_pressed(false); + } break; + case Animation::LoopMode::LOOP_LINEAR: { + loop->set_icon(get_theme_icon("Loop", "EditorIcons")); + loop->set_pressed(true); + } break; + case Animation::LoopMode::LOOP_PINGPONG: { + loop->set_icon(get_theme_icon("PingPongLoop", "EditorIcons")); + loop->set_pressed(true); + } break; + default: + break; + } + editing = false; } @@ -1693,48 +1761,48 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) { const Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { get_zoom()->set_value(get_zoom()->get_value() * 1.05); accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { get_zoom()->set_value(get_zoom()->get_value() / 1.05); accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { if (track_edit) { track_edit->get_editor()->goto_prev_step(true); } accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { if (track_edit) { track_edit->get_editor()->goto_next_step(true); } accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && hsize_rect.has_point(mb->get_position())) { dragging_hsize = true; dragging_hsize_from = mb->get_position().x; dragging_hsize_at = name_limit; } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && dragging_hsize) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && dragging_hsize) { dragging_hsize = false; } if (mb.is_valid() && mb->get_position().x > get_name_limit() && mb->get_position().x < (get_size().width - get_buttons_width())) { - if (!panning_timeline && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (!panning_timeline && mb->get_button_index() == MouseButton::LEFT) { int x = mb->get_position().x - get_name_limit(); float ofs = x / get_zoom_scale() + get_value(); - emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT)); + emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(Key::ALT)); dragging_timeline = true; } - if (!dragging_timeline && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) { + if (!dragging_timeline && mb->get_button_index() == MouseButton::MIDDLE) { int x = mb->get_position().x - get_name_limit(); panning_timeline_from = x / get_zoom_scale(); panning_timeline = true; @@ -1742,11 +1810,11 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) { } } - if (dragging_timeline && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { + if (dragging_timeline && mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { dragging_timeline = false; } - if (panning_timeline && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE && !mb->is_pressed()) { + if (panning_timeline && mb.is_valid() && mb->get_button_index() == MouseButton::MIDDLE && !mb->is_pressed()) { panning_timeline = false; } @@ -1770,7 +1838,7 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) { if (dragging_timeline) { int x = mm->get_position().x - get_name_limit(); float ofs = x / get_zoom_scale() + get_value(); - emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT)); + emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(Key::ALT)); } if (panning_timeline) { int x = mm->get_position().x - get_name_limit(); @@ -2110,25 +2178,25 @@ void AnimationTrackEdit::_notification(int p_what) { Ref<Texture2D> icon = wrap_icon[loop_wrap ? 1 : 0]; - loop_mode_rect.position.x = ofs; - loop_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2; - loop_mode_rect.size = icon->get_size(); + loop_wrap_rect.position.x = ofs; + loop_wrap_rect.position.y = int(get_size().height - icon->get_height()) / 2; + loop_wrap_rect.size = icon->get_size(); if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) { - draw_texture(icon, loop_mode_rect.position); + draw_texture(icon, loop_wrap_rect.position); } - loop_mode_rect.position.y = 0; - loop_mode_rect.size.y = get_size().height; + loop_wrap_rect.position.y = 0; + loop_wrap_rect.size.y = get_size().height; ofs += icon->get_width() + hsep; - loop_mode_rect.size.x += hsep; + loop_wrap_rect.size.x += hsep; if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) { draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2)); - loop_mode_rect.size.x += down_icon->get_width(); + loop_wrap_rect.size.x += down_icon->get_width(); } else { - loop_mode_rect = Rect2(); + loop_wrap_rect = Rect2(); } ofs += down_icon->get_width(); @@ -2228,6 +2296,11 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool Ref<Texture2D> icon_to_draw = p_selected ? selected_icon : type_icon; + if (animation->track_get_type(track) == Animation::TYPE_VALUE && !Math::is_equal_approx(animation->track_get_key_transition(track, p_index), real_t(1.0))) { + // Use a different icon for keys with non-linear easing. + icon_to_draw = get_theme_icon(p_selected ? SNAME("KeyEasedSelected") : SNAME("KeyValueEased"), SNAME("EditorIcons")); + } + // Override type icon for invalid value keys, unless selected. if (!p_selected && animation->track_get_type(track) == Animation::TYPE_VALUE) { const Variant &v = animation->track_get_key_value(track, p_index); @@ -2478,7 +2551,7 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const { return TTR("Interpolation Mode"); } - if (loop_mode_rect.has_point(p_pos)) { + if (loop_wrap_rect.has_point(p_pos)) { return TTR("Loop Wrap Mode (Interpolate end with beginning on loop)"); } @@ -2573,6 +2646,17 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const { text += "In-Handle: " + ih + "\n"; Vector2 oh = animation->bezier_track_get_key_out_handle(track, key_idx); text += "Out-Handle: " + oh + "\n"; + int hm = animation->bezier_track_get_key_handle_mode(track, key_idx); + text += "Handle mode: "; + switch (hm) { + case Animation::HANDLE_MODE_FREE: { + text += "Free"; + } break; + case Animation::HANDLE_MODE_BALANCED: { + text += "Balanced"; + } break; + } + text += "\n"; } break; case Animation::TYPE_AUDIO: { String stream_name = "null"; @@ -2626,7 +2710,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Point2 pos = mb->get_position(); if (check_rect.has_point(pos)) { @@ -2681,7 +2765,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { accept_event(); } - if (loop_mode_rect.has_point(pos)) { + if (loop_wrap_rect.has_point(pos)) { if (!menu) { menu = memnew(PopupMenu); add_child(menu); @@ -2692,7 +2776,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { menu->add_icon_item(get_theme_icon(SNAME("InterpWrapLoop"), SNAME("EditorIcons")), TTR("Wrap Loop Interp"), MENU_LOOP_WRAP); menu->set_as_minsize(); - Vector2 popup_pos = get_screen_position() + loop_mode_rect.position + Vector2(0, loop_mode_rect.size.height); + Vector2 popup_pos = get_screen_position() + loop_wrap_rect.position + Vector2(0, loop_wrap_rect.size.height); menu->set_position(popup_pos); menu->popup(); accept_event(); @@ -2772,7 +2856,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) { Point2 pos = mb->get_position(); if (pos.x >= timeline->get_name_limit() && pos.x <= get_size().width - timeline->get_buttons_width()) { // Can do something with menu too! show insert key. @@ -2802,7 +2886,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && clicking_on_name) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && clicking_on_name) { if (!path) { path_popup = memnew(Popup); path_popup->set_wrap_controls(true); @@ -2824,7 +2908,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } if (mb.is_valid() && moving_selection_attempt) { - if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (!mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { moving_selection_attempt = false; if (moving_selection) { emit_signal(SNAME("move_selection_commit")); @@ -2835,7 +2919,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { select_single_attempt = -1; } - if (moving_selection && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (moving_selection && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) { moving_selection_attempt = false; moving_selection = false; emit_signal(SNAME("move_selection_cancel")); @@ -2843,7 +2927,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && moving_selection_attempt) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE && moving_selection_attempt) { if (!moving_selection) { moving_selection = true; emit_signal(SNAME("move_selection_begin")); @@ -4137,7 +4221,7 @@ bool AnimationTrackEditor::is_selection_active() const { } bool AnimationTrackEditor::is_snap_enabled() const { - return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CTRL); + return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(Key::CTRL); } void AnimationTrackEditor::_update_tracks() { @@ -4762,12 +4846,13 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) { Variant value; _find_hint_for_track(p_track, bp, &value); Array arr; - arr.resize(5); + arr.resize(6); arr[0] = value; arr[1] = -0.25; arr[2] = 0; arr[3] = 0.25; arr[4] = 0; + arr[5] = 0; undo_redo->create_action(TTR("Add Track Key")); undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, arr); @@ -5118,27 +5203,27 @@ void AnimationTrackEditor::_box_selection_draw() { void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); scroll->accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); scroll->accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { goto_prev_step(true); scroll->accept_event(); } - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { goto_next_step(true); scroll->accept_event(); } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { box_selecting = true; box_selecting_from = scroll->get_global_transform().xform(mb->get_position()); @@ -5166,12 +5251,12 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { timeline->set_value(timeline->get_value() - mm->get_relative().x / timeline->get_zoom_scale()); } if (mm.is_valid() && box_selecting) { - if (!(mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) { + if ((mm->get_button_mask() & MouseButton::MASK_LEFT) == MouseButton::NONE) { // No longer. box_selection->hide(); box_selecting = false; @@ -5320,7 +5405,7 @@ void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) { if (step == 0) { step = 1; } - if (p_from_mouse_event && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (p_from_mouse_event && Input::get_singleton()->is_key_pressed(Key::SHIFT)) { // Use more precise snapping when holding Shift. // This is used when scrobbling the timeline using Alt + Mouse wheel. step *= 0.25; @@ -5343,7 +5428,7 @@ void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) { if (step == 0) { step = 1; } - if (p_from_mouse_event && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (p_from_mouse_event && Input::get_singleton()->is_key_pressed(Key::SHIFT)) { // Use more precise snapping when holding Shift. // This is used when scrobbling the timeline using Alt + Mouse wheel. // Do not use precise snapping when using the menu action or keyboard shortcut, @@ -5779,7 +5864,7 @@ float AnimationTrackEditor::snap_time(float p_value, bool p_relative) { snap_increment = step->get_value(); } - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { // Use more precise snapping when holding Shift. snap_increment *= 0.25; } @@ -5893,10 +5978,10 @@ void AnimationTrackEditor::_pick_track_filter_input(const Ref<InputEvent> &p_ie) if (k.is_valid()) { switch (k->get_keycode()) { - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: { + case Key::UP: + case Key::DOWN: + case Key::PAGEUP: + case Key::PAGEDOWN: { pick_track->get_scene_tree()->get_scene_tree()->gui_input(k); pick_track->get_filter_line_edit()->accept_event(); } break; @@ -6057,14 +6142,14 @@ AnimationTrackEditor::AnimationTrackEditor() { edit->get_popup()->add_item(TTR("Scale Selection"), EDIT_SCALE_SELECTION); edit->get_popup()->add_item(TTR("Scale From Cursor"), EDIT_SCALE_FROM_CURSOR); edit->get_popup()->add_separator(); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_CMD | KEY_D), EDIT_DUPLICATE_SELECTION); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection_transposed", TTR("Duplicate Transposed"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D), EDIT_DUPLICATE_TRANSPOSED); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::CMD | Key::D), EDIT_DUPLICATE_SELECTION); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection_transposed", TTR("Duplicate Transposed"), KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::D), EDIT_DUPLICATE_TRANSPOSED); edit->get_popup()->add_separator(); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/delete_selection", TTR("Delete Selection"), KEY_DELETE), EDIT_DELETE_SELECTION); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/delete_selection", TTR("Delete Selection"), Key::KEY_DELETE), EDIT_DELETE_SELECTION); edit->get_popup()->add_separator(); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KEY_MASK_CMD | KEY_RIGHT), EDIT_GOTO_NEXT_STEP); - edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KEY_MASK_CMD | KEY_LEFT), EDIT_GOTO_PREV_STEP); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KeyModifierMask::CMD | Key::RIGHT), EDIT_GOTO_NEXT_STEP); + edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KeyModifierMask::CMD | Key::LEFT), EDIT_GOTO_PREV_STEP); edit->get_popup()->add_separator(); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/apply_reset", TTR("Apply Reset")), EDIT_APPLY_RESET); edit->get_popup()->add_separator(); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 05cf91de1d..2bdc1d4107 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -159,7 +159,7 @@ class AnimationTrackEdit : public Control { Rect2 update_mode_rect; Rect2 interp_mode_rect; - Rect2 loop_mode_rect; + Rect2 loop_wrap_rect; Rect2 remove_rect; Rect2 bezier_edit_rect; @@ -466,6 +466,7 @@ class AnimationTrackEditor : public VBoxContainer { Animation::TrackType track_type = Animation::TrackType::TYPE_ANIMATION; Animation::InterpolationType interp_type = Animation::InterpolationType::INTERPOLATION_CUBIC; Animation::UpdateMode update_mode = Animation::UpdateMode::UPDATE_CAPTURE; + Animation::LoopMode loop_mode = Animation::LoopMode::LOOP_LINEAR; bool loop_wrap = false; bool enabled = false; diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index 70ba806c37..dd3e08b299 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -1098,7 +1098,7 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && get_default_cursor_shape() == CURSOR_HSIZE) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && get_default_cursor_shape() == CURSOR_HSIZE) { len_resizing = true; len_resizing_start = mb->is_shift_pressed(); len_resizing_from_px = mb->get_position().x; @@ -1108,7 +1108,7 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) { return; } - if (len_resizing && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (len_resizing && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { float ofs_local = -len_resizing_rel / get_timeline()->get_zoom_scale(); if (len_resizing_start) { float prev_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), len_resizing_index); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 1902ae66fb..bfcd2dd4ca 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -127,7 +127,7 @@ void FindReplaceBar::unhandled_input(const Ref<InputEvent> &p_event) { bool accepted = true; switch (k->get_keycode()) { - case KEY_ESCAPE: { + case Key::ESCAPE: { _hide_bar(); } break; default: { @@ -542,7 +542,7 @@ void FindReplaceBar::_search_text_changed(const String &p_text) { } void FindReplaceBar::_search_text_submitted(const String &p_text) { - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { search_prev(); } else { search_next(); @@ -553,7 +553,7 @@ void FindReplaceBar::_replace_text_submitted(const String &p_text) { if (selection_only->is_pressed() && text_editor->has_selection()) { _replace_all(); _hide_bar(); - } else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + } else if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { _replace(); search_prev(); } else { @@ -766,9 +766,9 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid()) { if (mb->is_pressed() && mb->is_command_pressed()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb->get_button_index() == MouseButton::WHEEL_UP) { _zoom_in(); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN) { _zoom_out(); } } @@ -1654,7 +1654,7 @@ void CodeTextEditor::_toggle_scripts_pressed() { void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { goto_error(); } } @@ -1788,9 +1788,9 @@ void CodeTextEditor::update_toggle_scripts_button() { CodeTextEditor::CodeTextEditor() { code_complete_func = nullptr; - ED_SHORTCUT("script_editor/zoom_in", TTR("Zoom In"), KEY_MASK_CMD | KEY_EQUAL); - ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS); - ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KEY_MASK_CMD | KEY_0); + ED_SHORTCUT("script_editor/zoom_in", TTR("Zoom In"), KeyModifierMask::CMD | Key::EQUAL); + ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KeyModifierMask::CMD | Key::MINUS); + ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KeyModifierMask::CMD | Key::KEY_0); text_editor = memnew(CodeEdit); add_child(text_editor); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index f0b27702e7..72aea9b630 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -352,10 +352,10 @@ void CreateDialog::_sbox_input(const Ref<InputEvent> &p_ie) { Ref<InputEventKey> k = p_ie; if (k.is_valid()) { switch (k->get_keycode()) { - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: { + case Key::UP: + case Key::DOWN: + case Key::PAGEUP: + case Key::PAGEDOWN: { search_options->gui_input(k); search_box->accept_event(); } break; diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp index 08ed675d16..952f46e9a5 100644 --- a/editor/debugger/editor_performance_profiler.cpp +++ b/editor/debugger/editor_performance_profiler.cpp @@ -249,7 +249,7 @@ TreeItem *EditorPerformanceProfiler::_create_monitor_item(const StringName &p_mo void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Vector<StringName> active; for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { if (i.value().item->is_checked(0)) { diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index 2fe7cd7886..d08ae1de8a 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -438,7 +438,7 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseMotion> mm = p_ev; if ( - (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) || + (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) || (mm.is_valid())) { int x = me->get_position().x - 1; x = x * frame_metrics.size() / graph->get_size().width; @@ -453,7 +453,7 @@ void EditorProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { x = frame_metrics.size() - 1; } - if (mb.is_valid() || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mb.is_valid() || (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { updating_frame = true; if (x < total_metrics) diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index f25f18b7e4..4739458f8e 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -517,7 +517,7 @@ void EditorVisualProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseMotion> mm = p_ev; if ( - (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) || + (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) || (mm.is_valid())) { int half_w = graph->get_size().width / 2; int x = me->get_position().x; @@ -549,7 +549,7 @@ void EditorVisualProfiler::_graph_tex_input(const Ref<InputEvent> &p_ev) { hover_metric = -1; } - if (mb.is_valid() || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mb.is_valid() || (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { //cursor_metric=x; updating_frame = true; diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index a312c161a8..e0d32756ca 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -578,6 +578,12 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da error->set_tooltip(0, tooltip); error->set_tooltip(1, tooltip); + if (warning_count == 0 && error_count == 0) { + expand_all_button->set_disabled(false); + collapse_all_button->set_disabled(false); + clear_button->set_disabled(false); + } + if (oe.warning) { warning_count++; } else { @@ -1404,6 +1410,11 @@ void ScriptEditorDebugger::_clear_errors_list() { error_tree->clear(); error_count = 0; warning_count = 0; + update_tabs(); + + expand_all_button->set_disabled(true); + collapse_all_button->set_disabled(true); + clear_button->set_disabled(true); } // Right click on specific file(s) or folder(s). @@ -1662,28 +1673,31 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { errors_tab = memnew(VBoxContainer); errors_tab->set_name(TTR("Errors")); - HBoxContainer *errhb = memnew(HBoxContainer); - errors_tab->add_child(errhb); + HBoxContainer *error_hbox = memnew(HBoxContainer); + errors_tab->add_child(error_hbox); - Button *expand_all = memnew(Button); - expand_all->set_text(TTR("Expand All")); - expand_all->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_expand_errors_list)); - errhb->add_child(expand_all); + expand_all_button = memnew(Button); + expand_all_button->set_text(TTR("Expand All")); + expand_all_button->set_disabled(true); + expand_all_button->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_expand_errors_list)); + error_hbox->add_child(expand_all_button); - Button *collapse_all = memnew(Button); - collapse_all->set_text(TTR("Collapse All")); - collapse_all->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_collapse_errors_list)); - errhb->add_child(collapse_all); + collapse_all_button = memnew(Button); + collapse_all_button->set_text(TTR("Collapse All")); + collapse_all_button->set_disabled(true); + collapse_all_button->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_collapse_errors_list)); + error_hbox->add_child(collapse_all_button); Control *space = memnew(Control); space->set_h_size_flags(SIZE_EXPAND_FILL); - errhb->add_child(space); - - clearbutton = memnew(Button); - clearbutton->set_text(TTR("Clear")); - clearbutton->set_h_size_flags(0); - clearbutton->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_clear_errors_list)); - errhb->add_child(clearbutton); + error_hbox->add_child(space); + + clear_button = memnew(Button); + clear_button->set_text(TTR("Clear")); + clear_button->set_h_size_flags(0); + clear_button->set_disabled(true); + clear_button->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_clear_errors_list)); + error_hbox->add_child(clear_button); error_tree = memnew(Tree); error_tree->set_columns(2); diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index 1c1c0fd3e5..76209aef46 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -94,7 +94,9 @@ private: VBoxContainer *errors_tab; Tree *error_tree; - Button *clearbutton; + Button *expand_all_button; + Button *collapse_all_button; + Button *clear_button; PopupMenu *item_menu; EditorFileDialog *file_dialog; diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index 61cc6dbd4a..5ce57e936a 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -41,7 +41,7 @@ #include "scene/resources/theme.h" // Used for a hack preserving Mono properties on non-Mono builds. -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For mono. void DocTools::merge_from(const DocTools &p_data) { for (KeyValue<String, DocData::ClassDoc> &E : class_list) { diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index b9f1c1af54..dd9f10a23b 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -303,7 +303,7 @@ void EditorAudioBus::_volume_changed(float p_normalized) { const float p_db = this->_normalized_volume_to_scaled_db(p_normalized); - if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { // Snap the value when holding Ctrl for easier editing. // To do so, it needs to be converted back to normalized volume (as the slider uses that unit). slider->set_value(_scaled_db_to_normalized_volume(Math::round(p_db))); @@ -363,7 +363,7 @@ float EditorAudioBus::_scaled_db_to_normalized_volume(float db) { void EditorAudioBus::_show_value(float slider_value) { float db; - if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { // Display the correct (snapped) value when holding Ctrl db = Math::round(_normalized_volume_to_scaled_db(slider_value)); } else { @@ -534,7 +534,7 @@ void EditorAudioBus::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { Vector2 pos = mb->get_position(); bus_popup->set_position(get_global_position() + pos); bus_popup->popup(); @@ -543,7 +543,7 @@ void EditorAudioBus::gui_input(const Ref<InputEvent> &p_event) { void EditorAudioBus::_effects_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> k = p_event; - if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_DELETE) { + if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::KEY_DELETE) { TreeItem *current_effect = effects->get_selected(); if (current_effect && current_effect->get_metadata(0).get_type() == Variant::INT) { _delete_effect_pressed(0); @@ -925,8 +925,8 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { hbc->add_child(bus_options); bus_popup = bus_options->get_popup(); - bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/duplicate_selected_bus", TTR("Duplicate Bus"), KEY_MASK_CMD | KEY_D)); - bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/delete_selected_bus", TTR("Delete Bus"), KEY_DELETE)); + bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/duplicate_selected_bus", TTR("Duplicate Bus"), KeyModifierMask::CMD | Key::D)); + bus_popup->add_shortcut(ED_SHORTCUT("audio_bus_editor/delete_selected_bus", TTR("Delete Bus"), Key::KEY_DELETE)); bus_popup->set_item_disabled(1, is_master); bus_popup->add_item(TTR("Reset Volume")); bus_popup->connect("index_pressed", callable_mp(this, &EditorAudioBus::_bus_popup_pressed)); diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index 71e9fac219..52e55de84c 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -149,10 +149,10 @@ void EditorCommandPalette::_sbox_input(const Ref<InputEvent> &p_ie) { Ref<InputEventKey> k = p_ie; if (k.is_valid()) { switch (k->get_keycode()) { - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: { + case Key::UP: + case Key::DOWN: + case Key::PAGEUP: + case Key::PAGEDOWN: { search_options->gui_input(k); } break; default: diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h index 39821a1169..8836c7b0fb 100644 --- a/editor/editor_command_palette.h +++ b/editor/editor_command_palette.h @@ -99,6 +99,6 @@ public: static EditorCommandPalette *get_singleton(); }; -Ref<Shortcut> ED_SHORTCUT_AND_COMMAND(const String &p_path, const String &p_name, Key p_keycode = KEY_NONE, String p_command = ""); +Ref<Shortcut> ED_SHORTCUT_AND_COMMAND(const String &p_path, const String &p_name, Key p_keycode = Key::NONE, String p_command = ""); #endif //EDITOR_COMMAND_PALETTE_H diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index d1dfc61c19..e78ca7cd64 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -82,7 +82,7 @@ bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const { void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const { for (const PropertyInfo &E : properties) { - if (platform->get_option_visibility(E.name, values)) { + if (platform->get_export_option_visibility(E.name, values)) { p_list->push_back(E); } } diff --git a/editor/editor_export.h b/editor/editor_export.h index b681f52330..1a5b8e6026 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -240,7 +240,7 @@ public: virtual void get_export_options(List<ExportOption> *r_options) = 0; virtual bool should_update_export_options() { return false; } - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } + virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } virtual String get_os_name() const = 0; virtual String get_name() const = 0; diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 675234959a..021ab8b93b 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -598,7 +598,7 @@ void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p item_menu->add_icon_item(item_list->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), TTR("Copy Path"), ITEM_MENU_COPY_PATH); } if (allow_delete) { - item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Delete"), ITEM_MENU_DELETE, KEY_DELETE); + item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Delete"), ITEM_MENU_DELETE, Key::KEY_DELETE); } if (single_item_selected) { item_menu->add_separator(); @@ -623,9 +623,9 @@ void EditorFileDialog::_item_list_rmb_clicked(const Vector2 &p_pos) { item_menu->set_size(Size2(1, 1)); if (can_create_dir) { - item_menu->add_icon_item(item_list->get_theme_icon(SNAME("folder"), SNAME("FileDialog")), TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KEY_MASK_CMD | KEY_N); + item_menu->add_icon_item(item_list->get_theme_icon(SNAME("folder"), SNAME("FileDialog")), TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KeyModifierMask::CMD | Key::N); } - item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5); + item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), TTR("Refresh"), ITEM_MENU_REFRESH, Key::F5); item_menu->add_separator(); item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); @@ -1476,18 +1476,18 @@ EditorFileDialog::EditorFileDialog() { mode = FILE_MODE_SAVE_FILE; set_title(TTR("Save a File")); - ED_SHORTCUT("file_dialog/go_back", TTR("Go Back"), KEY_MASK_ALT | KEY_LEFT); - ED_SHORTCUT("file_dialog/go_forward", TTR("Go Forward"), KEY_MASK_ALT | KEY_RIGHT); - ED_SHORTCUT("file_dialog/go_up", TTR("Go Up"), KEY_MASK_ALT | KEY_UP); - ED_SHORTCUT("file_dialog/refresh", TTR("Refresh"), KEY_F5); - ED_SHORTCUT("file_dialog/toggle_hidden_files", TTR("Toggle Hidden Files"), KEY_MASK_CMD | KEY_H); - ED_SHORTCUT("file_dialog/toggle_favorite", TTR("Toggle Favorite"), KEY_MASK_ALT | KEY_F); - ED_SHORTCUT("file_dialog/toggle_mode", TTR("Toggle Mode"), KEY_MASK_ALT | KEY_V); - ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KEY_MASK_CMD | KEY_N); - ED_SHORTCUT("file_dialog/delete", TTR("Delete"), KEY_DELETE); - ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KEY_MASK_CMD | KEY_D); - ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KEY_MASK_CMD | KEY_UP); - ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KEY_MASK_CMD | KEY_DOWN); + ED_SHORTCUT("file_dialog/go_back", TTR("Go Back"), KeyModifierMask::ALT | Key::LEFT); + ED_SHORTCUT("file_dialog/go_forward", TTR("Go Forward"), KeyModifierMask::ALT | Key::RIGHT); + ED_SHORTCUT("file_dialog/go_up", TTR("Go Up"), KeyModifierMask::ALT | Key::UP); + ED_SHORTCUT("file_dialog/refresh", TTR("Refresh"), Key::F5); + ED_SHORTCUT("file_dialog/toggle_hidden_files", TTR("Toggle Hidden Files"), KeyModifierMask::CMD | Key::H); + ED_SHORTCUT("file_dialog/toggle_favorite", TTR("Toggle Favorite"), KeyModifierMask::ALT | Key::F); + ED_SHORTCUT("file_dialog/toggle_mode", TTR("Toggle Mode"), KeyModifierMask::ALT | Key::V); + ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KeyModifierMask::CMD | Key::N); + ED_SHORTCUT("file_dialog/delete", TTR("Delete"), Key::KEY_DELETE); + ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KeyModifierMask::CMD | Key::D); + ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KeyModifierMask::CMD | Key::UP); + ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KeyModifierMask::CMD | Key::DOWN); HBoxContainer *pathhb = memnew(HBoxContainer); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 3d6b523733..d141447044 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1633,7 +1633,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name); ERR_FAIL_COND_V(!importer.is_valid(), ERR_FILE_CORRUPT); List<ResourceImporter::ImportOption> options; - importer->get_import_options(&options); + importer->get_import_options(p_files[i], &options); //set default values for (const ResourceImporter::ImportOption &E : options) { source_file_options[p_files[i]][E.option.name] = E.default_value; @@ -1714,7 +1714,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector //store options in provided order, to avoid file changing. Order is also important because first match is accepted first. List<ResourceImporter::ImportOption> options; - importer->get_import_options(&options); + importer->get_import_options(file, &options); //set default values for (const ResourceImporter::ImportOption &F : options) { String base = F.option.name; @@ -1851,7 +1851,7 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName //mix with default params, in case a parameter is missing List<ResourceImporter::ImportOption> opts; - importer->get_import_options(&opts); + importer->get_import_options(p_file, &opts); for (const ResourceImporter::ImportOption &E : opts) { if (!params.has(E.option.name)) { //this one is not present params[E.option.name] = E.default_value; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 8c3569df07..05f4e385c6 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -33,13 +33,14 @@ #include "core/core_constants.h" #include "core/input/input.h" #include "core/os/keyboard.h" +#include "core/version_generated.gen.h" #include "doc_data_compressed.gen.h" #include "editor/plugins/script_editor_plugin.h" #include "editor_node.h" #include "editor_scale.h" #include "editor_settings.h" -#define CONTRIBUTE_URL "https://docs.godotengine.org/en/latest/community/contributing/updating_the_class_reference.html" +#define CONTRIBUTE_URL vformat("%s/community/contributing/updating_the_class_reference.html", VERSION_DOCS_URL) DocTools *EditorHelp::doc = nullptr; @@ -1429,14 +1430,15 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { bbcode = bbcode.replace("[/gdscript]", "[/codeblock]"); for (int pos = bbcode.find("[csharp]"); pos != -1; pos = bbcode.find("[csharp]")) { - if (bbcode.find("[/csharp]") == -1) { + int end_pos = bbcode.find("[/csharp]"); + if (end_pos == -1) { WARN_PRINT("Unclosed [csharp] block or parse fail in code (search for tag errors)"); break; } - bbcode.erase(pos, bbcode.find("[/csharp]") + 9 - pos); + bbcode = bbcode.left(pos) + bbcode.substr(end_pos + 9); // 9 is length of "[/csharp]". while (bbcode[pos] == '\n') { - bbcode.erase(pos, 1); + bbcode = bbcode.left(pos) + bbcode.substr(pos + 1); } } break; @@ -1445,14 +1447,15 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { bbcode = bbcode.replace("[/csharp]", "[/codeblock]"); for (int pos = bbcode.find("[gdscript]"); pos != -1; pos = bbcode.find("[gdscript]")) { - if (bbcode.find("[/gdscript]") == -1) { + int end_pos = bbcode.find("[/gdscript]"); + if (end_pos == -1) { WARN_PRINT("Unclosed [gdscript] block or parse fail in code (search for tag errors)"); break; } - bbcode.erase(pos, bbcode.find("[/gdscript]") + 11 - pos); + bbcode = bbcode.left(pos) + bbcode.substr(end_pos + 11); // 11 is length of "[/gdscript]". while (bbcode[pos] == '\n') { - bbcode.erase(pos, 1); + bbcode = bbcode.left(pos) + bbcode.substr(pos + 1); } } break; @@ -2021,7 +2024,7 @@ void FindBar::unhandled_input(const Ref<InputEvent> &p_event) { bool accepted = true; switch (k->get_keycode()) { - case KEY_ESCAPE: { + case Key::ESCAPE: { _hide_bar(); } break; default: { @@ -2041,7 +2044,7 @@ void FindBar::_search_text_changed(const String &p_text) { } void FindBar::_search_text_submitted(const String &p_text) { - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { search_prev(); } else { search_next(); diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 8504745b03..578e21861e 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -67,10 +67,10 @@ void EditorHelpSearch::_search_box_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> key = p_event; if (key.is_valid()) { switch (key->get_keycode()) { - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: { + case Key::UP: + case Key::DOWN: + case Key::PAGEUP: + case Key::PAGEDOWN: { results_tree->gui_input(key); search_box->accept_event(); } break; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 4ffa90777c..07e505adb4 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -571,7 +571,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { if (is_layout_rtl()) { mpos.x = get_size().x - mpos.x; } - bool button_left = me->get_button_mask() & MOUSE_BUTTON_MASK_LEFT; + bool button_left = (me->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE; bool new_keying_hover = keying_rect.has_point(mpos) && !button_left; if (new_keying_hover != keying_hover) { @@ -600,7 +600,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Vector2 mpos = mb->get_position(); if (is_layout_rtl()) { mpos.x = get_size().x - mpos.x; @@ -647,7 +647,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { update(); emit_signal(SNAME("property_checked"), property, checked); } - } else if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + } else if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) { _update_popup(); menu->set_position(get_screen_position() + get_local_mouse_position()); menu->set_size(Vector2(1, 1)); @@ -1014,11 +1014,15 @@ bool EditorInspectorPlugin::can_handle(Object *p_object) { } void EditorInspectorPlugin::parse_begin(Object *p_object) { - GDVIRTUAL_CALL(_parse_begin); + GDVIRTUAL_CALL(_parse_begin, p_object); } -void EditorInspectorPlugin::parse_category(Object *p_object, const String &p_parse_category) { - GDVIRTUAL_CALL(_parse_category, p_object, p_parse_category); +void EditorInspectorPlugin::parse_category(Object *p_object, const String &p_category) { + GDVIRTUAL_CALL(_parse_category, p_object, p_category); +} + +void EditorInspectorPlugin::parse_group(Object *p_object, const String &p_group) { + GDVIRTUAL_CALL(_parse_group, p_object, p_group); } bool EditorInspectorPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { @@ -1029,8 +1033,8 @@ bool EditorInspectorPlugin::parse_property(Object *p_object, const Variant::Type return false; } -void EditorInspectorPlugin::parse_end() { - GDVIRTUAL_CALL(_parse_end); +void EditorInspectorPlugin::parse_end(Object *p_object) { + GDVIRTUAL_CALL(_parse_end, p_object); } void EditorInspectorPlugin::_bind_methods() { @@ -1039,10 +1043,11 @@ void EditorInspectorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("add_property_editor_for_multiple_properties", "label", "properties", "editor"), &EditorInspectorPlugin::add_property_editor_for_multiple_properties); GDVIRTUAL_BIND(_can_handle, "object") - GDVIRTUAL_BIND(_parse_begin) + GDVIRTUAL_BIND(_parse_begin, "object") GDVIRTUAL_BIND(_parse_category, "object", "category") + GDVIRTUAL_BIND(_parse_group, "object", "group") GDVIRTUAL_BIND(_parse_property, "object", "type", "name", "hint_type", "hint_string", "usage_flags", "wide"); - GDVIRTUAL_BIND(_parse_end) + GDVIRTUAL_BIND(_parse_end, "object") } //////////////////////////////////////////////// @@ -1217,7 +1222,7 @@ void EditorInspectorSection::_notification(int p_what) { Color c = bg_color; c.a *= 0.4; if (foldable && header_rect.has_point(get_local_mouse_position())) { - c = c.lightened(Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT) ? -0.05 : 0.2); + c = c.lightened(Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT) ? -0.05 : 0.2); } draw_rect(header_rect, c); @@ -1335,7 +1340,7 @@ void EditorInspectorSection::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Tree")); int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Tree")); if (mb->get_position().y > font->get_height(font_size)) { //clicked outside @@ -1538,7 +1543,7 @@ void EditorInspectorArray::_panel_gui_input(Ref<InputEvent> p_event, int p_index if (key_ref.is_valid()) { const InputEventKey &key = **key_ref; - if (array_elements[p_index].panel->has_focus() && key.is_pressed() && key.get_keycode() == KEY_DELETE) { + if (array_elements[p_index].panel->has_focus() && key.is_pressed() && key.get_keycode() == Key::KEY_DELETE) { _move_element(begin_array_index + p_index, -1); array_elements[p_index].panel->accept_event(); } @@ -1546,7 +1551,7 @@ void EditorInspectorArray::_panel_gui_input(Ref<InputEvent> p_event, int p_index Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->get_button_index() == MouseButton::RIGHT) { popup_array_index_pressed = begin_array_index + p_index; rmb_popup->set_item_disabled(OPTION_MOVE_UP, popup_array_index_pressed == 0); rmb_popup->set_item_disabled(OPTION_MOVE_DOWN, popup_array_index_pressed == count - 1); @@ -2628,6 +2633,12 @@ void EditorInspector::update_tree() { c.a /= level; section->setup(acc_path, component, object, c, use_folding); + // Add editors at the start of a group. + for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { + ped->parse_group(object, path); + _parse_added_editors(section->get_vbox(), ped); + } + vbox_per_path[root_vbox][acc_path] = section->get_vbox(); } @@ -2837,7 +2848,7 @@ void EditorInspector::update_tree() { // Get the lists of to add at the end. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { - ped->parse_end(); + ped->parse_end(object); _parse_added_editors(main_vbox, ped); } } @@ -3075,12 +3086,20 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo } else { undo_redo->create_action(vformat(TTR("Set %s"), p_name), UndoRedo::MERGE_ENDS); undo_redo->add_do_property(object, p_name, p_value); - undo_redo->add_undo_property(object, p_name, object->get(p_name)); + bool valid = false; + Variant value = object->get(p_name, &valid); + if (valid) { + undo_redo->add_undo_property(object, p_name, value); + } PropertyInfo prop_info; if (ClassDB::get_property_info(object->get_class_name(), p_name, &prop_info)) { for (const String &linked_prop : prop_info.linked_properties) { - undo_redo->add_undo_property(object, linked_prop, object->get(linked_prop)); + valid = false; + value = object->get(linked_prop, &valid); + if (valid) { + undo_redo->add_undo_property(object, linked_prop, value); + } } } @@ -3557,7 +3576,7 @@ EditorInspector::EditorInspector() { refresh_countdown = 0.33; } - ED_SHORTCUT("property_editor/copy_property", TTR("Copy Property"), KEY_MASK_CMD | KEY_C); - ED_SHORTCUT("property_editor/paste_property", TTR("Paste Property"), KEY_MASK_CMD | KEY_V); - ED_SHORTCUT("property_editor/copy_property_path", TTR("Copy Property Path"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_C); + ED_SHORTCUT("property_editor/copy_property", TTR("Copy Property"), KeyModifierMask::CMD | Key::C); + ED_SHORTCUT("property_editor/paste_property", TTR("Paste Property"), KeyModifierMask::CMD | Key::V); + ED_SHORTCUT("property_editor/copy_property_path", TTR("Copy Property Path"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::C); } diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index aabb66eeb4..f2dfe32f82 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -215,10 +215,11 @@ protected: static void _bind_methods(); GDVIRTUAL1RC(bool, _can_handle, Variant) - GDVIRTUAL0(_parse_begin) + GDVIRTUAL1(_parse_begin, Object *) GDVIRTUAL2(_parse_category, Object *, String) + GDVIRTUAL2(_parse_group, Object *, String) GDVIRTUAL7R(bool, _parse_property, Object *, int, String, int, String, int, bool) - GDVIRTUAL0(_parse_end) + GDVIRTUAL1(_parse_end, Object *) public: void add_custom_control(Control *control); @@ -227,9 +228,10 @@ public: virtual bool can_handle(Object *p_object); virtual void parse_begin(Object *p_object); - virtual void parse_category(Object *p_object, const String &p_parse_category); + virtual void parse_category(Object *p_object, const String &p_category); + virtual void parse_group(Object *p_object, const String &p_group); virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false); - virtual void parse_end(); + virtual void parse_end(Object *p_object); }; class EditorInspectorCategory : public Control { diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp index b1f8ba5d20..4cdeeb2396 100644 --- a/editor/editor_layouts_dialog.cpp +++ b/editor/editor_layouts_dialog.cpp @@ -46,15 +46,15 @@ void EditorLayoutsDialog::_line_gui_input(const Ref<InputEvent> &p_event) { } switch (k->get_keycode()) { - case KEY_KP_ENTER: - case KEY_ENTER: { + case Key::KP_ENTER: + case Key::ENTER: { if (get_hide_on_ok()) { hide(); } ok_pressed(); set_input_as_handled(); } break; - case KEY_ESCAPE: { + case Key::ESCAPE: { hide(); set_input_as_handled(); } break; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 5f2f8e91c9..5ace9ae03e 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -366,7 +366,7 @@ EditorLog::EditorLog() { clear_button = memnew(Button); clear_button->set_flat(true); clear_button->set_focus_mode(FOCUS_NONE); - clear_button->set_shortcut(ED_SHORTCUT("editor/clear_output", TTR("Clear Output"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_K)); + clear_button->set_shortcut(ED_SHORTCUT("editor/clear_output", TTR("Clear Output"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::K)); clear_button->set_shortcut_context(this); clear_button->connect("pressed", callable_mp(this, &EditorLog::_clear_request)); hb_tools->add_child(clear_button); @@ -375,7 +375,7 @@ EditorLog::EditorLog() { copy_button = memnew(Button); copy_button->set_flat(true); copy_button->set_focus_mode(FOCUS_NONE); - copy_button->set_shortcut(ED_SHORTCUT("editor/copy_output", TTR("Copy Selection"), KEY_MASK_CMD | KEY_C)); + copy_button->set_shortcut(ED_SHORTCUT("editor/copy_output", TTR("Copy Selection"), KeyModifierMask::CMD | Key::C)); copy_button->set_shortcut_context(this); copy_button->connect("pressed", callable_mp(this, &EditorLog::_copy_request)); hb_tools->add_child(copy_button); @@ -401,7 +401,7 @@ EditorLog::EditorLog() { show_search_button->set_focus_mode(FOCUS_NONE); show_search_button->set_toggle_mode(true); show_search_button->set_pressed(true); - show_search_button->set_shortcut(ED_SHORTCUT("editor/open_search", TTR("Focus Search/Filter Bar"), KEY_MASK_CMD | KEY_F)); + show_search_button->set_shortcut(ED_SHORTCUT("editor/open_search", TTR("Focus Search/Filter Bar"), KeyModifierMask::CMD | Key::F)); show_search_button->set_shortcut_context(this); show_search_button->connect("toggled", callable_mp(this, &EditorLog::_set_search_visible)); hb_tools2->add_child(show_search_button); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4af7763caa..368b7e6ab3 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -621,6 +621,19 @@ void EditorNode::_notification(int p_what) { } break; case NOTIFICATION_READY: { + { + _initializing_addons = true; + Vector<String> addons; + if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) { + addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled"); + } + + for (int i = 0; i < addons.size(); i++) { + set_addon_plugin_enabled(addons[i], true); + } + _initializing_addons = false; + } + RenderingServer::get_singleton()->viewport_set_disable_2d(get_scene_root()->get_viewport_rid(), true); RenderingServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true); @@ -994,18 +1007,6 @@ void EditorNode::_sources_changed(bool p_exist) { load_scene(defer_load_scene); defer_load_scene = ""; } - - // Only enable addons once resources have been imported - _initializing_addons = true; - Vector<String> addons; - if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) { - addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled"); - } - - for (int i = 0; i < addons.size(); i++) { - set_addon_plugin_enabled(addons[i], true); - } - _initializing_addons = false; } } @@ -1717,8 +1718,10 @@ void EditorNode::_save_scene(String p_file, int idx) { err = ResourceSaver::save(p_file, sdata, flg); - _save_external_resources(); + // This needs to be emitted before saving external resources. + emit_signal(SNAME("scene_saved"), p_file); + _save_external_resources(); editor_data.save_editor_external_data(); for (Ref<AnimatedValuesBackup> &E : anim_backups) { @@ -2644,7 +2647,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case EDIT_UNDO: { - if (Input::get_singleton()->get_mouse_button_mask() & 0x7) { + if ((int)Input::get_singleton()->get_mouse_button_mask() & 0x7) { log->add_message(TTR("Can't undo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR); } else { String action = editor_data.get_undo_redo().get_current_action_name(); @@ -2657,7 +2660,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } break; case EDIT_REDO: { - if (Input::get_singleton()->get_mouse_button_mask() & 0x7) { + if ((int)Input::get_singleton()->get_mouse_button_mask() & 0x7) { log->add_message(TTR("Can't redo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR); } else { if (!editor_data.get_undo_redo().redo()) { @@ -4323,7 +4326,7 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = me; - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && dock_popup_selected != nrect) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && dock_popup_selected != nrect) { Control *dock = dock_slot[dock_popup_selected]->get_current_tab_control(); if (dock) { dock_slot[dock_popup_selected]->remove_child(dock); @@ -5016,15 +5019,15 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { if (mb.is_valid()) { if (scene_tabs->get_hovered_tab() >= 0) { - if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::MIDDLE && mb->is_pressed()) { _scene_tab_closed(scene_tabs->get_hovered_tab()); } } else { - if ((mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_double_click()) || (mb->get_button_index() == MOUSE_BUTTON_MIDDLE && mb->is_pressed())) { + if ((mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) || (mb->get_button_index() == MouseButton::MIDDLE && mb->is_pressed())) { _menu_option_confirm(FILE_NEW_SCENE, true); } } - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { // context menu scene_tabs_context_menu->clear(); scene_tabs_context_menu->set_size(Size2(1, 1)); @@ -5057,12 +5060,12 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { scene_tabs_context_menu->set_position(mb->get_global_position()); scene_tabs_context_menu->popup(); } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) { int previous_tab = editor_data.get_edited_scene() - 1; previous_tab = previous_tab >= 0 ? previous_tab : editor_data.get_edited_scene_count() - 1; _scene_tab_changed(previous_tab); } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) { int next_tab = editor_data.get_edited_scene() + 1; next_tab %= editor_data.get_edited_scene_count(); _scene_tab_changed(next_tab); @@ -5712,6 +5715,7 @@ void EditorNode::_bind_methods() { ADD_SIGNAL(MethodInfo("request_help_search")); ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "args"))); ADD_SIGNAL(MethodInfo("resource_saved", PropertyInfo(Variant::OBJECT, "obj"))); + ADD_SIGNAL(MethodInfo("scene_saved", PropertyInfo(Variant::STRING, "path"))); ADD_SIGNAL(MethodInfo("project_settings_changed")); } @@ -6255,8 +6259,8 @@ EditorNode::EditorNode() { tabbar_container->add_child(scene_tabs); distraction_free = memnew(Button); distraction_free->set_flat(true); - ED_SHORTCUT_AND_COMMAND("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F11); - ED_SHORTCUT_OVERRIDE("editor/distraction_free_mode", "macos", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D); + ED_SHORTCUT_AND_COMMAND("editor/distraction_free_mode", TTR("Distraction Free Mode"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F11); + ED_SHORTCUT_OVERRIDE("editor/distraction_free_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::D); distraction_free->set_shortcut(ED_GET_SHORTCUT("editor/distraction_free_mode")); distraction_free->set_tooltip(TTR("Toggle distraction-free mode.")); distraction_free->connect("pressed", callable_mp(this, &EditorNode::_toggle_distraction_free_mode)); @@ -6354,9 +6358,9 @@ EditorNode::EditorNode() { gui_base->add_child(warning); warning->connect("custom_action", callable_mp(this, &EditorNode::_copy_warning)); - ED_SHORTCUT("editor/next_tab", TTR("Next Scene Tab"), KEY_MASK_CMD + KEY_TAB); - ED_SHORTCUT("editor/prev_tab", TTR("Previous Scene Tab"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_TAB); - ED_SHORTCUT("editor/filter_files", TTR("Focus FileSystem Filter"), KEY_MASK_CMD + KEY_MASK_ALT + KEY_P); + ED_SHORTCUT("editor/next_tab", TTR("Next Scene Tab"), KeyModifierMask::CMD + Key::TAB); + ED_SHORTCUT("editor/prev_tab", TTR("Previous Scene Tab"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::TAB); + ED_SHORTCUT("editor/filter_files", TTR("Focus FileSystem Filter"), KeyModifierMask::CMD + KeyModifierMask::ALT + Key::P); command_palette = EditorCommandPalette::get_singleton(); command_palette->set_title(TTR("Command Palette")); @@ -6368,22 +6372,22 @@ EditorNode::EditorNode() { p = file_menu->get_popup(); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTR("New Scene"), KEY_MASK_CMD + KEY_N), FILE_NEW_SCENE); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTR("New Inherited Scene..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_N), FILE_NEW_INHERITED_SCENE); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_T), FILE_OPEN_PREV); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTR("New Scene"), KeyModifierMask::CMD + Key::N), FILE_NEW_SCENE); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTR("New Inherited Scene..."), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::N), FILE_NEW_INHERITED_SCENE); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTR("Open Scene..."), KeyModifierMask::CMD + Key::O), FILE_OPEN_SCENE); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::T), FILE_OPEN_PREV); p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT); p->add_separator(); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTR("Save Scene"), KEY_MASK_CMD + KEY_S), FILE_SAVE_SCENE); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_S), FILE_SAVE_AS_SCENE); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTR("Save All Scenes"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_S), FILE_SAVE_ALL_SCENES); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTR("Save Scene"), KeyModifierMask::CMD + Key::S), FILE_SAVE_SCENE); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTR("Save Scene As..."), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::S), FILE_SAVE_AS_SCENE); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTR("Save All Scenes"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::S), FILE_SAVE_ALL_SCENES); p->add_separator(); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open", TTR("Quick Open..."), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_O), FILE_QUICK_OPEN_SCENE); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_CMD + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN_SCRIPT); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open", TTR("Quick Open..."), KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::O), FILE_QUICK_OPEN); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTR("Quick Open Scene..."), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::O), FILE_QUICK_OPEN_SCENE); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTR("Quick Open Script..."), KeyModifierMask::CMD + KeyModifierMask::ALT + Key::O), FILE_QUICK_OPEN_SCRIPT); p->add_separator(); PopupMenu *pm_export = memnew(PopupMenu); @@ -6399,7 +6403,7 @@ EditorNode::EditorNode() { p->add_separator(); p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reload_saved_scene", TTR("Reload Saved Scene")), EDIT_RELOAD_SAVED_SCENE); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTR("Close Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_W), FILE_CLOSE); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTR("Close Scene"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::W), FILE_CLOSE); recent_scenes = memnew(PopupMenu); recent_scenes->set_name("RecentScenes"); @@ -6407,7 +6411,7 @@ EditorNode::EditorNode() { recent_scenes->connect("id_pressed", callable_mp(this, &EditorNode::_open_recent_scene)); p->add_separator(); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTR("Quit"), KEY_MASK_CMD + KEY_Q), FILE_QUIT, true); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTR("Quit"), KeyModifierMask::CMD + Key::Q), FILE_QUIT, true); project_menu = memnew(MenuButton); project_menu->set_flat(false); @@ -6419,7 +6423,7 @@ EditorNode::EditorNode() { p = project_menu->get_popup(); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/project_settings", TTR("Project Settings..."), KEY_NONE, TTR("Project Settings")), RUN_SETTINGS); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/project_settings", TTR("Project Settings..."), Key::NONE, TTR("Project Settings")), RUN_SETTINGS); p->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel(); @@ -6432,7 +6436,7 @@ EditorNode::EditorNode() { vcs_actions_menu->add_item(TTR("Shut Down Version Control"), RUN_VCS_SHUT_DOWN); p->add_separator(); - p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/export", TTR("Export..."), KEY_NONE, TTR("Export")), FILE_EXPORT_PROJECT); + p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/export", TTR("Export..."), Key::NONE, TTR("Export")), FILE_EXPORT_PROJECT); p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE); p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER); @@ -6449,8 +6453,8 @@ EditorNode::EditorNode() { p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/reload_current_project", TTR("Reload Current Project")), RUN_RELOAD_CURRENT_PROJECT); - ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_Q); - ED_SHORTCUT_OVERRIDE("editor/quit_to_project_list", "macos", KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q); + ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTR("Quit to Project List"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::Q); + ED_SHORTCUT_OVERRIDE("editor/quit_to_project_list", "macos", KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::Q); p->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), RUN_PROJECT_MANAGER, true); menu_hb->add_spacer(); @@ -6478,9 +6482,9 @@ EditorNode::EditorNode() { p = settings_menu->get_popup(); ED_SHORTCUT_AND_COMMAND("editor/editor_settings", TTR("Editor Settings...")); - ED_SHORTCUT_OVERRIDE("editor/editor_settings", "macos", KEY_MASK_CMD + KEY_COMMA); + ED_SHORTCUT_OVERRIDE("editor/editor_settings", "macos", KeyModifierMask::CMD + Key::COMMA); p->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), SETTINGS_PREFERENCES); - p->add_shortcut(ED_SHORTCUT("editor/command_palette", TTR("Command Palette..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_P), HELP_COMMAND_PALETTE); + p->add_shortcut(ED_SHORTCUT("editor/command_palette", TTR("Command Palette..."), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::P), HELP_COMMAND_PALETTE); p->add_separator(); editor_layouts = memnew(PopupMenu); @@ -6490,14 +6494,14 @@ EditorNode::EditorNode() { p->add_submenu_item(TTR("Editor Layout"), "Layouts"); p->add_separator(); - ED_SHORTCUT_AND_COMMAND("editor/take_screenshot", TTR("Take Screenshot"), KEY_MASK_CTRL | KEY_F12); - ED_SHORTCUT_OVERRIDE("editor/take_screenshot", "macos", KEY_MASK_CMD | KEY_F12); + ED_SHORTCUT_AND_COMMAND("editor/take_screenshot", TTR("Take Screenshot"), KeyModifierMask::CTRL | Key::F12); + ED_SHORTCUT_OVERRIDE("editor/take_screenshot", "macos", KeyModifierMask::CMD | Key::F12); p->add_shortcut(ED_GET_SHORTCUT("editor/take_screenshot"), EDITOR_SCREENSHOT); p->set_item_tooltip(p->get_item_count() - 1, TTR("Screenshots are stored in the Editor Data/Settings Folder.")); - ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11); - ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F); + ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KeyModifierMask::SHIFT | Key::F11); + ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::F); p->add_shortcut(ED_GET_SHORTCUT("editor/fullscreen_mode"), SETTINGS_TOGGLE_FULLSCREEN); #if defined(WINDOWS_ENABLED) && defined(WINDOWS_SUBSYSTEM_CONSOLE) @@ -6531,8 +6535,8 @@ EditorNode::EditorNode() { p = help_menu->get_popup(); p->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); - ED_SHORTCUT_AND_COMMAND("editor/editor_help", TTR("Search Help"), KEY_F1); - ED_SHORTCUT_OVERRIDE("editor/editor_help", "macos", KEY_MASK_ALT | KEY_SPACE); + ED_SHORTCUT_AND_COMMAND("editor/editor_help", TTR("Search Help"), Key::F1); + ED_SHORTCUT_OVERRIDE("editor/editor_help", "macos", KeyModifierMask::ALT | Key::SPACE); p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")), ED_GET_SHORTCUT("editor/editor_help"), HELP_SEARCH); p->add_separator(); p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTR("Online Documentation")), HELP_DOCS); @@ -6557,8 +6561,8 @@ EditorNode::EditorNode() { play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY)); play_button->set_tooltip(TTR("Play the project.")); - ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), KEY_F5); - ED_SHORTCUT_OVERRIDE("editor/play", "macos", KEY_MASK_CMD | KEY_B); + ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), Key::F5); + ED_SHORTCUT_OVERRIDE("editor/play", "macos", KeyModifierMask::CMD | Key::B); play_button->set_shortcut(ED_GET_SHORTCUT("editor/play")); pause_button = memnew(Button); @@ -6570,8 +6574,8 @@ EditorNode::EditorNode() { pause_button->set_disabled(true); play_hb->add_child(pause_button); - ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), KEY_F7); - ED_SHORTCUT_OVERRIDE("editor/pause_scene", "macos", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_Y); + ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), Key::F7); + ED_SHORTCUT_OVERRIDE("editor/pause_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::Y); pause_button->set_shortcut(ED_GET_SHORTCUT("editor/pause_scene")); stop_button = memnew(Button); @@ -6583,8 +6587,8 @@ EditorNode::EditorNode() { stop_button->set_tooltip(TTR("Stop the scene.")); stop_button->set_disabled(true); - ED_SHORTCUT("editor/stop", TTR("Stop"), KEY_F8); - ED_SHORTCUT_OVERRIDE("editor/stop", "macos", KEY_MASK_CMD | KEY_PERIOD); + ED_SHORTCUT("editor/stop", TTR("Stop"), Key::F8); + ED_SHORTCUT_OVERRIDE("editor/stop", "macos", KeyModifierMask::CMD | Key::PERIOD); stop_button->set_shortcut(ED_GET_SHORTCUT("editor/stop")); run_native = memnew(EditorRunNative); @@ -6600,8 +6604,8 @@ EditorNode::EditorNode() { play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_SCENE)); play_scene_button->set_tooltip(TTR("Play the edited scene.")); - ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), KEY_F6); - ED_SHORTCUT_OVERRIDE("editor/play_scene", "macos", KEY_MASK_CMD | KEY_R); + ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), Key::F6); + ED_SHORTCUT_OVERRIDE("editor/play_scene", "macos", KeyModifierMask::CMD | Key::R); play_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/play_scene")); play_custom_scene_button = memnew(Button); @@ -6613,8 +6617,8 @@ EditorNode::EditorNode() { play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_CUSTOM_SCENE)); play_custom_scene_button->set_tooltip(TTR("Play custom scene")); - ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5); - ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R); + ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F5); + ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R); play_custom_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/play_custom_scene")); HBoxContainer *right_menu_hb = memnew(HBoxContainer); @@ -6801,7 +6805,7 @@ EditorNode::EditorNode() { bottom_panel_raise->set_flat(true); bottom_panel_raise->set_icon(gui_base->get_theme_icon(SNAME("ExpandBottomDock"), SNAME("EditorIcons"))); - bottom_panel_raise->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12)); + bottom_panel_raise->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KeyModifierMask::SHIFT | Key::F12)); bottom_panel_hb->add_child(bottom_panel_raise); bottom_panel_raise->hide(); @@ -7171,15 +7175,15 @@ EditorNode::EditorNode() { ResourceLoader::set_load_callback(_resource_loaded); // Use the Ctrl modifier so F2 can be used to rename nodes in the scene tree dock. - ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_CTRL | KEY_F1); - ED_SHORTCUT_AND_COMMAND("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_CTRL | KEY_F2); - ED_SHORTCUT_AND_COMMAND("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_CTRL | KEY_F3); - ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_CTRL | KEY_F4); - - ED_SHORTCUT_OVERRIDE("editor/editor_2d", "macos", KEY_MASK_ALT | KEY_1); - ED_SHORTCUT_OVERRIDE("editor/editor_3d", "macos", KEY_MASK_ALT | KEY_2); - ED_SHORTCUT_OVERRIDE("editor/editor_script", "macos", KEY_MASK_ALT | KEY_3); - ED_SHORTCUT_OVERRIDE("editor/editor_assetlib", "macos", KEY_MASK_ALT | KEY_4); + ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTR("Open 2D Editor"), KeyModifierMask::CTRL | Key::F1); + ED_SHORTCUT_AND_COMMAND("editor/editor_3d", TTR("Open 3D Editor"), KeyModifierMask::CTRL | Key::F2); + ED_SHORTCUT_AND_COMMAND("editor/editor_script", TTR("Open Script Editor"), KeyModifierMask::CTRL | Key::F3); + ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KeyModifierMask::CTRL | Key::F4); + + ED_SHORTCUT_OVERRIDE("editor/editor_2d", "macos", KeyModifierMask::ALT | Key::KEY_1); + ED_SHORTCUT_OVERRIDE("editor/editor_3d", "macos", KeyModifierMask::ALT | Key::KEY_2); + ED_SHORTCUT_OVERRIDE("editor/editor_script", "macos", KeyModifierMask::ALT | Key::KEY_3); + ED_SHORTCUT_OVERRIDE("editor/editor_assetlib", "macos", KeyModifierMask::ALT | Key::KEY_4); ED_SHORTCUT_AND_COMMAND("editor/editor_next", TTR("Open the next Editor")); ED_SHORTCUT_AND_COMMAND("editor/editor_prev", TTR("Open the previous Editor")); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 26f28ff5fb..e48679cad7 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -818,7 +818,7 @@ public: } const Ref<InputEventMouseButton> mb = p_ev; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { if (hovered_index >= 0) { // Toggle the flag. // We base our choice on the hovered flag, so that it always matches the hovered flag. @@ -1278,11 +1278,11 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { } const Ref<InputEventMouseButton> mb = p_ev; if (mb.is_valid()) { - if (mb->is_double_click() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->is_double_click() && mb->get_button_index() == MouseButton::LEFT) { _setup_spin(); } - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) { preset->set_position(easing_draw->get_screen_transform().xform(mb->get_position())); preset->popup(); @@ -1291,7 +1291,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { easing_draw->update(); } - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { dragging = mb->is_pressed(); // Update to display the correct dragging color easing_draw->update(); @@ -1300,7 +1300,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { const Ref<InputEventMouseMotion> mm = p_ev; - if (dragging && mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (dragging && mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { float rel = mm->get_relative().x; if (rel == 0) { return; @@ -3170,11 +3170,7 @@ EditorPropertyResource::EditorPropertyResource() { ////////////// DEFAULT PLUGIN ////////////////////// bool EditorInspectorDefaultPlugin::can_handle(Object *p_object) { - return true; //can handle everything -} - -void EditorInspectorDefaultPlugin::parse_begin(Object *p_object) { - //do none + return true; // Can handle everything. } bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { @@ -3185,10 +3181,6 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, const Varian return false; } -void EditorInspectorDefaultPlugin::parse_end() { - //do none -} - struct EditorPropertyRangeHint { bool angle_in_degrees = false; bool greater = true; diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 754d444309..42ef650adc 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -696,9 +696,7 @@ class EditorInspectorDefaultPlugin : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual void parse_begin(Object *p_object) override; virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; - virtual void parse_end() override; static EditorProperty *get_editor_for_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false); }; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 4775ca418b..0703677dc8 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -464,7 +464,7 @@ void EditorResourcePicker::_button_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) { _update_menu_items(); Vector2 pos = get_screen_position() + mb->get_position(); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 739fc0e4f5..613e0ba7a0 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1482,7 +1482,7 @@ void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_k ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE with invalid shortcut: " + p_path + "."); PackedInt32Array arr; - arr.push_back(p_keycode); + arr.push_back((int32_t)p_keycode); ED_SHORTCUT_OVERRIDE_ARRAY(p_path, p_feature, arr); } @@ -1503,13 +1503,12 @@ void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, c #ifdef OSX_ENABLED // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS - if (keycode == KEY_DELETE) { - keycode = KEY_MASK_CMD | KEY_BACKSPACE; + if (keycode == Key::KEY_DELETE) { + keycode = KeyModifierMask::CMD | Key::BACKSPACE; } #endif - Ref<InputEventKey> ie; - if (keycode) { + if (keycode != Key::NONE) { ie = InputEventKey::create_reference(keycode); events.push_back(ie); } @@ -1522,7 +1521,7 @@ void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, c Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, Key p_keycode) { PackedInt32Array arr; - arr.push_back(p_keycode); + arr.push_back((int32_t)p_keycode); return ED_SHORTCUT_ARRAY(p_path, p_name, arr); } @@ -1534,13 +1533,13 @@ Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, cons #ifdef OSX_ENABLED // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS - if (keycode == KEY_DELETE) { - keycode = KEY_MASK_CMD | KEY_BACKSPACE; + if (keycode == Key::KEY_DELETE) { + keycode = KeyModifierMask::CMD | Key::BACKSPACE; } #endif Ref<InputEventKey> ie; - if (keycode) { + if (keycode != Key::NONE) { ie = InputEventKey::create_reference(keycode); events.push_back(ie); } diff --git a/editor/editor_settings.h b/editor/editor_settings.h index 04e227bc5c..cb23ed3d19 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -200,9 +200,9 @@ Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_re Variant _EDITOR_GET(const String &p_setting); #define ED_IS_SHORTCUT(p_name, p_ev) (EditorSettings::get_singleton()->is_shortcut(p_name, p_ev)) -Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, Key p_keycode = KEY_NONE); +Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, Key p_keycode = Key::NONE); Ref<Shortcut> ED_SHORTCUT_ARRAY(const String &p_path, const String &p_name, const PackedInt32Array &p_keycodes); -void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_keycode = KEY_NONE); +void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_keycode = Key::NONE); void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes); Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 82b5ec5ca1..2942ece409 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -39,9 +39,9 @@ String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const { if (grabber->is_visible()) { #ifdef OSX_ENABLED - const int key = KEY_META; + Key key = Key::META; #else - const int key = KEY_CTRL; + Key key = Key::CTRL; #endif return TS->format_number(rtos(get_value())) + "\n\n" + vformat(TTR("Hold %s to round to integers. Hold Shift for more precise changes."), find_keycode_name(key)); } @@ -61,7 +61,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (updown_offset != -1 && mb->get_position().x > updown_offset) { //there is an updown, so use it. @@ -92,7 +92,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) { grabbing_spinner_attempt = false; } } - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP || mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + } else if (mb->get_button_index() == MouseButton::WHEEL_UP || mb->get_button_index() == MouseButton::WHEEL_DOWN) { if (grabber->is_visible()) { call_deferred(SNAME("update")); } @@ -154,17 +154,17 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) { if (grabbing_grabber) { if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb->get_button_index() == MouseButton::WHEEL_UP) { set_value(get_value() + get_step()); mousewheel_over_grabber = true; - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN) { set_value(get_value() - get_step()); mousewheel_over_grabber = true; } } } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { grabbing_grabber = true; if (!mousewheel_over_grabber) { @@ -212,9 +212,9 @@ void EditorSpinSlider::_value_input_gui_input(const Ref<InputEvent> &p_event) { step *= 0.1; } - uint32_t code = k->get_keycode(); + Key code = k->get_keycode(); switch (code) { - case KEY_UP: { + case Key::UP: { _evaluate_input_text(); double last_value = get_value(); @@ -228,7 +228,7 @@ void EditorSpinSlider::_value_input_gui_input(const Ref<InputEvent> &p_event) { value_input_dirty = true; set_process_internal(true); } break; - case KEY_DOWN: { + case Key::DOWN: { _evaluate_input_text(); double last_value = get_value(); @@ -242,6 +242,8 @@ void EditorSpinSlider::_value_input_gui_input(const Ref<InputEvent> &p_event) { value_input_dirty = true; set_process_internal(true); } break; + default: + break; } } } diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 8e8437f1b2..637394d136 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -36,7 +36,7 @@ #include "editor_scale.h" #include "editor_settings.h" -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For svg. #ifdef MODULE_SVG_ENABLED #include "modules/svg/image_loader_svg.h" #endif diff --git a/editor/editor_zoom_widget.cpp b/editor/editor_zoom_widget.cpp index 420aeb03fe..a998ec7e5b 100644 --- a/editor/editor_zoom_widget.cpp +++ b/editor/editor_zoom_widget.cpp @@ -51,7 +51,7 @@ void EditorZoomWidget::_update_zoom_label() { } void EditorZoomWidget::_button_zoom_minus() { - set_zoom_by_increments(-6, Input::get_singleton()->is_key_pressed(KEY_ALT)); + set_zoom_by_increments(-6, Input::get_singleton()->is_key_pressed(Key::ALT)); emit_signal(SNAME("zoom_changed"), zoom); } @@ -61,7 +61,7 @@ void EditorZoomWidget::_button_zoom_reset() { } void EditorZoomWidget::_button_zoom_plus() { - set_zoom_by_increments(6, Input::get_singleton()->is_key_pressed(KEY_ALT)); + set_zoom_by_increments(6, Input::get_singleton()->is_key_pressed(Key::ALT)); emit_signal(SNAME("zoom_changed"), zoom); } @@ -169,7 +169,7 @@ EditorZoomWidget::EditorZoomWidget() { zoom_minus->set_flat(true); add_child(zoom_minus); zoom_minus->connect("pressed", callable_mp(this, &EditorZoomWidget::_button_zoom_minus)); - zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS)); + zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KeyModifierMask::CMD | Key::MINUS)); zoom_minus->set_shortcut_context(this); zoom_minus->set_focus_mode(FOCUS_NONE); @@ -180,7 +180,7 @@ EditorZoomWidget::EditorZoomWidget() { zoom_reset->add_theme_color_override("font_outline_color", Color(0, 0, 0)); zoom_reset->add_theme_color_override("font_color", Color(1, 1, 1)); zoom_reset->connect("pressed", callable_mp(this, &EditorZoomWidget::_button_zoom_reset)); - zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0)); + zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KeyModifierMask::CMD | Key::KEY_0)); zoom_reset->set_shortcut_context(this); zoom_reset->set_focus_mode(FOCUS_NONE); zoom_reset->set_text_align(Button::TextAlign::ALIGN_CENTER); @@ -191,7 +191,7 @@ EditorZoomWidget::EditorZoomWidget() { zoom_plus->set_flat(true); add_child(zoom_plus); zoom_plus->connect("pressed", callable_mp(this, &EditorZoomWidget::_button_zoom_plus)); - zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom In"), KEY_MASK_CMD | KEY_EQUAL)); // Usually direct access key for PLUS + zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom In"), KeyModifierMask::CMD | Key::EQUAL)); // Usually direct access key for PLUS zoom_plus->set_shortcut_context(this); zoom_plus->set_focus_mode(FOCUS_NONE); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index f2a3aa3b44..1dde157527 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2273,7 +2273,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, } } if (!to_move.is_empty()) { - if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { for (int i = 0; i < to_move.size(); i++) { String new_path; String new_path_base; @@ -2794,11 +2794,12 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { editor = p_editor; path = "res://"; - // `KEY_MASK_CMD | KEY_C` conflicts with other editor shortcuts. - ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_C); - ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KEY_MASK_CMD | KEY_D); - ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), KEY_DELETE); - ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), KEY_F2); + // `KeyModifierMask::CMD | Key::C` conflicts with other editor shortcuts. + ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::C); + ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KeyModifierMask::CMD | Key::D); + ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), Key::KEY_DELETE); + ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), Key::F2); + ED_SHORTCUT_OVERRIDE("filesystem_dock/rename", "macos", Key::ENTER); VBoxContainer *top_vbc = memnew(VBoxContainer); add_child(top_vbc); diff --git a/editor/icons/KeyEasedSelected.svg b/editor/icons/KeyEasedSelected.svg new file mode 100644 index 0000000000..c06d94c553 --- /dev/null +++ b/editor/icons/KeyEasedSelected.svg @@ -0,0 +1 @@ +<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#5fb2ff" height="9.999999" rx=".948002" stroke-width="1.2427" width="9.999999" x=".000001" y=".000035"/><rect fill="#003e7a" height="5.628136" rx=".533549" stroke-width=".699406" transform="matrix(.99989481 .01450427 .01450427 .99989481 0 0)" width="5.628136" x="2.115027" y="2.114924"/></svg> diff --git a/editor/icons/KeyValueEased.svg b/editor/icons/KeyValueEased.svg new file mode 100644 index 0000000000..4e4a33c006 --- /dev/null +++ b/editor/icons/KeyValueEased.svg @@ -0,0 +1 @@ +<svg height="10" viewBox="0 0 10 10" width="10" xmlns="http://www.w3.org/2000/svg"><rect fill="#e0e0e0" height="8.000001" rx="1.000032" ry="1.00003" stroke-width="1.3109" transform="rotate(-90)" width="8.000016" x="-9.000016" y=".999999"/></svg> diff --git a/editor/icons/MirrorX.svg b/editor/icons/MirrorX.svg new file mode 100644 index 0000000000..fa668986ac --- /dev/null +++ b/editor/icons/MirrorX.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#e0e0e0" stroke-opacity=".99608" stroke-width="2" transform="translate(0 -1036.4)"><path d="m4 1042.4-2 2 2 2" stroke-linecap="round" stroke-linejoin="round"/><path d="m2 1044.4h11"/><path d="m12 1042.4 2 2-2 2" stroke-linecap="round" stroke-linejoin="round"/></g></svg> diff --git a/editor/icons/MirrorY.svg b/editor/icons/MirrorY.svg new file mode 100644 index 0000000000..bb4e4d3543 --- /dev/null +++ b/editor/icons/MirrorY.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11.012 1048.4a1.0001 1.0001 0 0 0 -1.7168-.6973l-.29297.293v-7.1719l.29297.293a1.0001 1.0001 0 0 0 1.7148-.7266 1.0001 1.0001 0 0 0 -.30078-.6875l-2-2a1.0001 1.0001 0 0 0 -1.4141 0l-2 2a1.0001 1.0001 0 1 0 1.4141 1.4141l.29297-.293v7.1719l-.29297-.293a1.0001 1.0001 0 1 0 -1.4141 1.4141l2 2a1.0001 1.0001 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 .30273-.7168z" fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/PingPongLoop.svg b/editor/icons/PingPongLoop.svg new file mode 100644 index 0000000000..c44f889b49 --- /dev/null +++ b/editor/icons/PingPongLoop.svg @@ -0,0 +1 @@ +<svg enable-background="new 0 0 16 16" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".9961"><path d="m10 7h-4v-2l-4 3 4 3v-2h4v2l4-3-4-3z"/><path d="m0 1v14h2v-7-7z"/><path d="m14 1v7 7h2v-14z"/></g></svg> diff --git a/editor/icons/RotateLeft.svg b/editor/icons/RotateLeft.svg new file mode 100644 index 0000000000..1200df1dde --- /dev/null +++ b/editor/icons/RotateLeft.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="translate(0 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg> diff --git a/editor/icons/RotateRight.svg b/editor/icons/RotateRight.svg new file mode 100644 index 0000000000..d69e6a7705 --- /dev/null +++ b/editor/icons/RotateRight.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".99608" transform="matrix(-1 0 0 1 16.026308 -1036.4)"><path d="m9 2a6 6 0 0 0 -6 6h2a4 4 0 0 1 4-4 4 4 0 0 1 4 4 4 4 0 0 1 -4 4v2a6 6 0 0 0 6-6 6 6 0 0 0 -6-6z" transform="translate(0 1036.4)"/><path d="m4.118 1048.3-1.6771-.9683-1.6771-.9682 1.6771-.9683 1.6771-.9682-.0000001 1.9365z" transform="matrix(0 -1.1926 1.5492 0 -1617 1049.3)"/></g></svg> diff --git a/editor/icons/ShapeCast2D.svg b/editor/icons/ShapeCast2D.svg new file mode 100644 index 0000000000..dcdba92f45 --- /dev/null +++ b/editor/icons/ShapeCast2D.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#a5b7f3"><path d="m7 1v9h-3l4 5 4-5h-3v-9z"/><circle cx="7.990566" cy="4.8202" r="4.009434"/></g></svg> diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp index d219f6e325..1a002569c5 100644 --- a/editor/import/editor_import_plugin.cpp +++ b/editor/import/editor_import_plugin.cpp @@ -57,6 +57,7 @@ void EditorImportPlugin::get_recognized_extensions(List<String> *p_extensions) c for (int i = 0; i < extensions.size(); i++) { p_extensions->push_back(extensions[i]); } + return; } ERR_FAIL_MSG("Unimplemented _get_recognized_extensions in add-on."); } @@ -109,12 +110,12 @@ int EditorImportPlugin::get_import_order() const { ERR_FAIL_V_MSG(-1, "Unimplemented _get_import_order in add-on."); } -void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption> *r_options, int p_preset) const { +void EditorImportPlugin::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options, int p_preset) const { Array needed; needed.push_back("name"); needed.push_back("default_value"); Array options; - if (GDVIRTUAL_CALL(_get_import_options, p_preset, options)) { + if (GDVIRTUAL_CALL(_get_import_options, p_path, p_preset, options)) { for (int i = 0; i < options.size(); i++) { Dictionary d = options[i]; ERR_FAIL_COND(!d.has_all(needed)); @@ -139,12 +140,13 @@ void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption> ImportOption option(PropertyInfo(default_value.get_type(), name, hint, hint_string, usage), default_value); r_options->push_back(option); } + return; } ERR_FAIL_MSG("Unimplemented _get_import_options in add-on."); } -bool EditorImportPlugin::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool EditorImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { Dictionary d; Map<StringName, Variant>::Element *E = p_options.front(); while (E) { @@ -152,7 +154,7 @@ bool EditorImportPlugin::get_option_visibility(const String &p_option, const Map E = E->next(); } bool visible; - if (GDVIRTUAL_CALL(_get_option_visibility, p_option, d, visible)) { + if (GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, d, visible)) { return visible; } @@ -190,11 +192,11 @@ void EditorImportPlugin::_bind_methods() { GDVIRTUAL_BIND(_get_preset_count) GDVIRTUAL_BIND(_get_preset_name, "preset_index") GDVIRTUAL_BIND(_get_recognized_extensions) - GDVIRTUAL_BIND(_get_import_options, "preset_index") + GDVIRTUAL_BIND(_get_import_options, "path", "preset_index") GDVIRTUAL_BIND(_get_save_extension) GDVIRTUAL_BIND(_get_resource_type) GDVIRTUAL_BIND(_get_priority) GDVIRTUAL_BIND(_get_import_order) - GDVIRTUAL_BIND(_get_option_visibility, "option_name", "options") + GDVIRTUAL_BIND(_get_option_visibility, "path", "option_name", "options") GDVIRTUAL_BIND(_import, "source_file", "save_path", "options", "platform_variants", "gen_files"); } diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index 49c959ab44..6c5f4f6005 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -44,12 +44,12 @@ protected: GDVIRTUAL0RC(int, _get_preset_count) GDVIRTUAL1RC(String, _get_preset_name, int) GDVIRTUAL0RC(Vector<String>, _get_recognized_extensions) - GDVIRTUAL1RC(Array, _get_import_options, int) + GDVIRTUAL2RC(Array, _get_import_options, String, int) GDVIRTUAL0RC(String, _get_save_extension) GDVIRTUAL0RC(String, _get_resource_type) GDVIRTUAL0RC(float, _get_priority) GDVIRTUAL0RC(int, _get_import_order) - GDVIRTUAL2RC(bool, _get_option_visibility, StringName, Dictionary) + GDVIRTUAL3RC(bool, _get_option_visibility, String, StringName, Dictionary) GDVIRTUAL5RC(int, _import, String, String, Dictionary, Array, Array) public: @@ -63,8 +63,8 @@ public: virtual String get_resource_type() const override; virtual float get_priority() const override; virtual int get_import_order() const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata = nullptr) override; }; diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp index 7fd9230284..c43052593d 100644 --- a/editor/import/resource_importer_bitmask.cpp +++ b/editor/import/resource_importer_bitmask.cpp @@ -57,7 +57,7 @@ String ResourceImporterBitMap::get_resource_type() const { return "BitMap"; } -bool ResourceImporterBitMap::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterBitMap::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -69,7 +69,7 @@ String ResourceImporterBitMap::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterBitMap::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterBitMap::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "create_from", PROPERTY_HINT_ENUM, "Black & White,Alpha"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.5)); } diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h index d68693c54a..f3da5f9a31 100644 --- a/editor/import/resource_importer_bitmask.h +++ b/editor/import/resource_importer_bitmask.h @@ -49,8 +49,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterBitMap(); diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp index a64be54f2d..f54065416e 100644 --- a/editor/import/resource_importer_bmfont.cpp +++ b/editor/import/resource_importer_bmfont.cpp @@ -56,11 +56,11 @@ String ResourceImporterBMFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterBMFont::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterBMFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } -void ResourceImporterBMFont::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterBMFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true)); } diff --git a/editor/import/resource_importer_bmfont.h b/editor/import/resource_importer_bmfont.h index 065703132a..64d536535c 100644 --- a/editor/import/resource_importer_bmfont.h +++ b/editor/import/resource_importer_bmfont.h @@ -45,8 +45,8 @@ public: virtual String get_save_extension() const override; virtual String get_resource_type() const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index 07647d8b6a..7948d9e577 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -55,7 +55,7 @@ String ResourceImporterCSVTranslation::get_resource_type() const { return "Translation"; } -bool ResourceImporterCSVTranslation::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterCSVTranslation::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -67,7 +67,7 @@ String ResourceImporterCSVTranslation::get_preset_name(int p_idx) const { return ""; } -void ResourceImporterCSVTranslation::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterCSVTranslation::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "delimiter", PROPERTY_HINT_ENUM, "Comma,Semicolon,Tab"), 0)); } diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h index d53e91e38b..de7ba3e3a0 100644 --- a/editor/import/resource_importer_csv_translation.h +++ b/editor/import/resource_importer_csv_translation.h @@ -46,8 +46,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_dynamicfont.cpp b/editor/import/resource_importer_dynamicfont.cpp index 8e01adbd56..f7363a565d 100644 --- a/editor/import/resource_importer_dynamicfont.cpp +++ b/editor/import/resource_importer_dynamicfont.cpp @@ -30,12 +30,12 @@ #include "resource_importer_dynamicfont.h" -#include "dynamicfont_import_settings.h" - #include "core/io/file_access.h" #include "core/io/resource_saver.h" +#include "dynamicfont_import_settings.h" #include "editor/editor_node.h" -#include "modules/modules_enabled.gen.h" + +#include "modules/modules_enabled.gen.h" // For freetype. String ResourceImporterDynamicFont::get_importer_name() const { return "font_data_dynamic"; @@ -66,7 +66,7 @@ String ResourceImporterDynamicFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterDynamicFont::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option == "msdf_pixel_range" && !bool(p_options["multichannel_signed_distance_field"])) { return false; } @@ -94,7 +94,7 @@ String ResourceImporterDynamicFont::get_preset_name(int p_idx) const { } } -void ResourceImporterDynamicFont::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { bool msdf = p_preset == PRESET_MSDF; r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); diff --git a/editor/import/resource_importer_dynamicfont.h b/editor/import/resource_importer_dynamicfont.h index 52f256ab96..cb5294b9dd 100644 --- a/editor/import/resource_importer_dynamicfont.h +++ b/editor/import/resource_importer_dynamicfont.h @@ -57,8 +57,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; bool has_advanced_options() const override; void show_advanced_options(const String &p_path) override; diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp index 2dea359188..45cb5e2f9d 100644 --- a/editor/import/resource_importer_image.cpp +++ b/editor/import/resource_importer_image.cpp @@ -55,7 +55,7 @@ String ResourceImporterImage::get_resource_type() const { return "Image"; } -bool ResourceImporterImage::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterImage::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -67,7 +67,7 @@ String ResourceImporterImage::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterImage::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterImage::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { } Error ResourceImporterImage::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { diff --git a/editor/import/resource_importer_image.h b/editor/import/resource_importer_image.h index 7c8d5e228e..b7131ec850 100644 --- a/editor/import/resource_importer_image.h +++ b/editor/import/resource_importer_image.h @@ -47,8 +47,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index 997280d1dd..04a68e4a53 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -55,11 +55,11 @@ String ResourceImporterImageFont::get_resource_type() const { return "FontData"; } -bool ResourceImporterImageFont::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterImageFont::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } -void ResourceImporterImageFont::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterImageFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "character_ranges"), Vector<String>())); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "columns"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rows"), 1)); diff --git a/editor/import/resource_importer_imagefont.h b/editor/import/resource_importer_imagefont.h index 9b2b38596f..d600c35e1c 100644 --- a/editor/import/resource_importer_imagefont.h +++ b/editor/import/resource_importer_imagefont.h @@ -47,8 +47,8 @@ public: virtual String get_save_extension() const override; virtual String get_resource_type() const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index d5bb21443c..89c62ab5cb 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -118,7 +118,7 @@ String ResourceImporterLayeredTexture::get_resource_type() const { ERR_FAIL_V(String()); } -bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option == "compress/lossy_quality" && p_options.has("compress/mode")) { return int(p_options["compress/mode"]) == COMPRESS_LOSSY; } @@ -133,7 +133,7 @@ String ResourceImporterLayeredTexture::get_preset_name(int p_idx) const { return ""; } -void ResourceImporterLayeredTexture::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterLayeredTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless (PNG),Lossy (WebP),Video RAM (S3TC/ETC/BPTC),Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_compression", PROPERTY_HINT_ENUM, "Disabled,Opaque Only,Always"), 1)); diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 7d8fb3cac5..29dfe7263a 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -84,8 +84,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; void _save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2); diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index 01af75c338..bb68de99b1 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -405,11 +405,11 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ current_material_library = l.replace("mtllib", "").strip_edges(); if (!material_map.has(current_material_library)) { Map<String, Ref<StandardMaterial3D>> lib; - Error err = _parse_material_library(current_material_library, lib, r_missing_deps); - if (err == ERR_CANT_OPEN) { - String dir = p_path.get_base_dir(); - err = _parse_material_library(dir.plus_file(current_material_library), lib, r_missing_deps); + String lib_path = current_material_library; + if (lib_path.is_relative_path()) { + lib_path = p_path.get_base_dir().plus_file(current_material_library); } + Error err = _parse_material_library(lib_path, lib, r_missing_deps); if (err == OK) { material_map[current_material_library] = lib; } @@ -504,14 +504,14 @@ String ResourceImporterOBJ::get_preset_name(int p_idx) const { return ""; } -void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterOBJ::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_tangents"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "scale_mesh"), Vector3(1, 1, 1))); r_options->push_back(ImportOption(PropertyInfo(Variant::VECTOR3, "offset_mesh"), Vector3(0, 0, 0))); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "optimize_mesh"), true)); } -bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterOBJ::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index d9f2f79903..c3e46b6eb5 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -59,8 +59,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 5efb08b95d..ab3479b7ce 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -91,6 +91,16 @@ Ref<Animation> EditorSceneFormatImporter::import_animation(const String &p_path, ERR_FAIL_V(nullptr); } +void EditorSceneFormatImporter::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) { + GDVIRTUAL_CALL(_get_import_options, p_path); +} + +Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) { + Variant ret; + GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret); + return ret; +} + //for documenters, these functions are useful when an importer calls an external conversion helper (like, fbx2gltf), //and you want to load the resulting file @@ -110,6 +120,8 @@ void EditorSceneFormatImporter::_bind_methods() { GDVIRTUAL_BIND(_get_extensions); GDVIRTUAL_BIND(_import_scene, "path", "flags", "bake_fps"); GDVIRTUAL_BIND(_import_animation, "path", "flags", "bake_fps"); + GDVIRTUAL_BIND(_get_import_options, "path"); + GDVIRTUAL_BIND(_get_option_visibility, "path", "option"); BIND_CONSTANT(IMPORT_SCENE); BIND_CONSTANT(IMPORT_ANIMATION); @@ -193,15 +205,15 @@ void EditorScenePostImportPlugin::internal_process(InternalImportCategory p_cate current_options_dict = nullptr; } -void EditorScenePostImportPlugin::get_import_options(List<ResourceImporter::ImportOption> *r_options) { +void EditorScenePostImportPlugin::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) { current_option_list = r_options; - GDVIRTUAL_CALL(_get_import_options); + GDVIRTUAL_CALL(_get_import_options, p_path); current_option_list = nullptr; } -Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { current_options = &p_options; Variant ret; - GDVIRTUAL_CALL(_get_option_visibility, p_option, ret); + GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret); current_options = nullptr; return ret; } @@ -227,8 +239,8 @@ void EditorScenePostImportPlugin::_bind_methods() { GDVIRTUAL_BIND(_get_internal_option_visibility, "category", "option"); GDVIRTUAL_BIND(_get_internal_option_update_view_required, "category", "option"); GDVIRTUAL_BIND(_internal_process, "category", "base_node", "node", "resource"); - GDVIRTUAL_BIND(_get_import_options); - GDVIRTUAL_BIND(_get_option_visibility, "option"); + GDVIRTUAL_BIND(_get_import_options, "path"); + GDVIRTUAL_BIND(_get_option_visibility, "path", "option"); GDVIRTUAL_BIND(_pre_process, "scene"); GDVIRTUAL_BIND(_post_process, "scene"); @@ -269,7 +281,7 @@ int ResourceImporterScene::get_format_version() const { return 1; } -bool ResourceImporterScene::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterScene::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option.begins_with("animation/")) { if (p_option != "animation/import" && !bool(p_options["animation/import"])) { return false; @@ -281,7 +293,14 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const } for (int i = 0; i < post_importer_plugins.size(); i++) { - Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_option, p_options); + Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_path, p_option, p_options); + if (ret.get_type() == Variant::BOOL) { + return ret; + } + } + + for (Ref<EditorSceneFormatImporter> importer : importers) { + Variant ret = importer->get_option_visibility(p_path, p_option, p_options); if (ret.get_type() == Variant::BOOL) { return ret; } @@ -424,10 +443,10 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I String animname = E; const int loop_string_count = 3; - static const char *loop_strings[loop_string_count] = { "loops", "loop", "cycle" }; + static const char *loop_strings[loop_string_count] = { "loop_mode", "loop", "cycle" }; for (int i = 0; i < loop_string_count; i++) { if (_teststr(animname, loop_strings[i])) { - anim->set_loop(true); + anim->set_loop_mode(Animation::LoopMode::LOOP_LINEAR); animname = _fixstr(animname, loop_strings[i]); ap->rename_animation(E, animname); } @@ -868,7 +887,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< String name = node_settings["clip_" + itos(i + 1) + "/name"]; int from_frame = node_settings["clip_" + itos(i + 1) + "/start_frame"]; int end_frame = node_settings["clip_" + itos(i + 1) + "/end_frame"]; - bool loop = node_settings["clip_" + itos(i + 1) + "/loops"]; + Animation::LoopMode loop_mode = static_cast<Animation::LoopMode>((int)node_settings["clip_" + itos(i + 1) + "/loop_mode"]); bool save_to_file = node_settings["clip_" + itos(i + 1) + "/save_to_file/enabled"]; bool save_to_path = node_settings["clip_" + itos(i + 1) + "/save_to_file/path"]; bool save_to_file_keep_custom = node_settings["clip_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"]; @@ -876,7 +895,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< animation_clips.push_back(name); animation_clips.push_back(from_frame / p_animation_fps); animation_clips.push_back(end_frame / p_animation_fps); - animation_clips.push_back(loop); + animation_clips.push_back(loop_mode); animation_clips.push_back(save_to_file); animation_clips.push_back(save_to_path); animation_clips.push_back(save_to_file_keep_custom); @@ -903,7 +922,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } } - anim->set_loop(anim_settings["settings/loops"]); + anim->set_loop_mode(static_cast<Animation::LoopMode>((int)anim_settings["settings/loop_mode"])); bool save = anim_settings["save_to_file/enabled"]; String path = anim_settings["save_to_file/path"]; bool keep_custom = anim_settings["save_to_file/keep_custom_tracks"]; @@ -977,7 +996,7 @@ Ref<Animation> ResourceImporterScene::_save_animation_to_file(Ref<Animation> ani old_anim->copy_track(i, anim); } } - anim->set_loop(old_anim->has_loop()); + anim->set_loop_mode(old_anim->get_loop_mode()); } } @@ -1005,7 +1024,7 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ String name = p_clips[i]; float from = p_clips[i + 1]; float to = p_clips[i + 2]; - bool loop = p_clips[i + 3]; + Animation::LoopMode loop_mode = static_cast<Animation::LoopMode>((int)p_clips[i + 3]); bool save_to_file = p_clips[i + 4]; String save_to_path = p_clips[i + 5]; bool keep_current = p_clips[i + 6]; @@ -1135,7 +1154,7 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ } } - new_anim->set_loop(loop); + new_anim->set_loop_mode(loop_mode); new_anim->set_length(to - from); anim->add_animation(name, new_anim); @@ -1218,7 +1237,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "use_external/path", PROPERTY_HINT_FILE, "*.material,*.res,*.tres"), "")); } break; case INTERNAL_IMPORT_CATEGORY_ANIMATION: { - r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "settings/loops"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "settings/loop_mode"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "save_to_file/path", PROPERTY_HINT_SAVE_FILE, "*.res,*.tres"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "save_to_file/keep_custom_tracks"), "")); @@ -1240,7 +1259,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "slice_" + itos(i + 1) + "/name"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/start_frame"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/end_frame"), 0)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/loops"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slice_" + itos(i + 1) + "/loop_mode"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "slice_" + itos(i + 1) + "/save_to_file/path", PROPERTY_HINT_SAVE_FILE, ".res,*.tres"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"), false)); @@ -1404,7 +1423,7 @@ bool ResourceImporterScene::get_internal_option_update_view_required(InternalImp return false; } -void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterScene::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_type", PROPERTY_HINT_TYPE_STRING, "Node"), "Node3D")); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_name"), "Scene Root")); @@ -1428,13 +1447,17 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 30)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "_subresources", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), Dictionary())); for (int i = 0; i < post_importer_plugins.size(); i++) { - post_importer_plugins.write[i]->get_import_options(r_options); + post_importer_plugins.write[i]->get_import_options(p_path, r_options); + } + + for (Ref<EditorSceneFormatImporter> importer : importers) { + importer->get_import_options(p_path, r_options); } } @@ -1462,7 +1485,7 @@ Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneFormatI for (const String &F : extensions) { if (F.to_lower() == ext) { - importer = E; + importer = E->get(); break; } } @@ -1492,7 +1515,7 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito for (const String &F : extensions) { if (F.to_lower() == ext) { - importer = E; + importer = E->get(); break; } } diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index a192921966..5437ecd159 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -55,6 +55,8 @@ protected: GDVIRTUAL0RC(Vector<String>, _get_extensions) GDVIRTUAL3R(Object *, _import_scene, String, uint32_t, uint32_t) GDVIRTUAL3R(Ref<Animation>, _import_animation, String, uint32_t, uint32_t) + GDVIRTUAL1(_get_import_options, String) + GDVIRTUAL2RC(Variant, _get_option_visibility, String, String) public: enum ImportFlags { @@ -69,6 +71,8 @@ public: virtual void get_extensions(List<String> *r_extensions) const; virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); + virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options); + virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options); EditorSceneFormatImporter() {} }; @@ -115,8 +119,8 @@ protected: GDVIRTUAL2RC(Variant, _get_internal_option_visibility, int, String) GDVIRTUAL2RC(Variant, _get_internal_option_update_view_required, int, String) GDVIRTUAL4(_internal_process, int, Node *, Node *, RES) - GDVIRTUAL0(_get_import_options) - GDVIRTUAL1RC(Variant, _get_option_visibility, String) + GDVIRTUAL1(_get_import_options, String) + GDVIRTUAL2RC(Variant, _get_option_visibility, String, String) GDVIRTUAL1(_pre_process, Node *) GDVIRTUAL1(_post_process, Node *) @@ -133,8 +137,8 @@ public: virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, RES p_resource, const Dictionary &p_options); - virtual void get_import_options(List<ResourceImporter::ImportOption> *r_options); - virtual Variant get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; + virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options); + virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const; virtual void pre_process(Node *p_scene, const Map<StringName, Variant> &p_options); virtual void post_process(Node *p_scene, const Map<StringName, Variant> &p_options); @@ -250,8 +254,8 @@ public: bool get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; bool get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; // Import scenes *after* everything else (such as textures). virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp index c01d8068da..797e11f5ea 100644 --- a/editor/import/resource_importer_shader_file.cpp +++ b/editor/import/resource_importer_shader_file.cpp @@ -65,10 +65,10 @@ String ResourceImporterShaderFile::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterShaderFile::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterShaderFile::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { } -bool ResourceImporterShaderFile::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterShaderFile::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } diff --git a/editor/import/resource_importer_shader_file.h b/editor/import/resource_importer_shader_file.h index c421132ec2..3ed489e9fb 100644 --- a/editor/import/resource_importer_shader_file.h +++ b/editor/import/resource_importer_shader_file.h @@ -46,8 +46,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index e4553c625b..b1fa2eda28 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -153,7 +153,7 @@ String ResourceImporterTexture::get_resource_type() const { return "StreamTexture2D"; } -bool ResourceImporterTexture::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterTexture::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option == "compress/lossy_quality") { int compress_mode = int(p_options["compress/mode"]); if (compress_mode != COMPRESS_LOSSY && compress_mode != COMPRESS_VRAM_COMPRESSED) { @@ -194,7 +194,7 @@ String ResourceImporterTexture::get_preset_name(int p_idx) const { return preset_names[p_idx]; } -void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,VRAM Compressed,VRAM Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), p_preset == PRESET_3D ? 2 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/hdr_compression", PROPERTY_HINT_ENUM, "Disabled,Opaque Only,Always"), 1)); diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index 41220009cd..cb9d1b08cd 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -95,8 +95,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index cf699599ae..1d59c3627d 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -59,7 +59,7 @@ String ResourceImporterTextureAtlas::get_resource_type() const { return "Texture2D"; } -bool ResourceImporterTextureAtlas::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterTextureAtlas::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -71,7 +71,7 @@ String ResourceImporterTextureAtlas::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterTextureAtlas::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterTextureAtlas::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "atlas_file", PROPERTY_HINT_SAVE_FILE, "*.png"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_mode", PROPERTY_HINT_ENUM, "Region,Mesh2D"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "crop_to_region"), false)); diff --git a/editor/import/resource_importer_texture_atlas.h b/editor/import/resource_importer_texture_atlas.h index d518a120bf..177ef949ac 100644 --- a/editor/import/resource_importer_texture_atlas.h +++ b/editor/import/resource_importer_texture_atlas.h @@ -60,8 +60,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual String get_option_group_file() const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index 89383d3dde..820eba951f 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -58,7 +58,7 @@ String ResourceImporterWAV::get_resource_type() const { return "AudioStreamSample"; } -bool ResourceImporterWAV::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterWAV::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { if (p_option == "force/max_rate_hz" && !bool(p_options["force/max_rate"])) { return false; } @@ -74,7 +74,7 @@ String ResourceImporterWAV::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterWAV::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterWAV::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/8_bit"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/mono"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/max_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); @@ -272,7 +272,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s if (loop_type == 0x00) { loop = AudioStreamSample::LOOP_FORWARD; } else if (loop_type == 0x01) { - loop = AudioStreamSample::LOOP_PING_PONG; + loop = AudioStreamSample::LOOP_PINGPONG; } else if (loop_type == 0x02) { loop = AudioStreamSample::LOOP_BACKWARD; } diff --git a/editor/import/resource_importer_wav.h b/editor/import/resource_importer_wav.h index 7413dbd11c..e3e605aeb2 100644 --- a/editor/import/resource_importer_wav.h +++ b/editor/import/resource_importer_wav.h @@ -46,8 +46,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; static void _compress_ima_adpcm(const Vector<float> &p_data, Vector<uint8_t> &dst_data) { /*p_sample_data->data = (void*)malloc(len); diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 9b9320ad6d..5690d49a55 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -664,7 +664,7 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { List<ResourceImporter::ImportOption> options; if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) { - ResourceImporterScene::get_singleton()->get_import_options(&options); + ResourceImporterScene::get_singleton()->get_import_options(base_path, &options); } else { ResourceImporterScene::get_singleton()->get_internal_import_options(scene_import_settings_data->category, &options); } @@ -737,21 +737,21 @@ void SceneImportSettings::_viewport_input(const Ref<InputEvent> &p_input) { zoom = &md.cam_zoom; } Ref<InputEventMouseMotion> mm = p_input; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { (*rot_x) -= mm->get_relative().y * 0.01 * EDSCALE; (*rot_y) -= mm->get_relative().x * 0.01 * EDSCALE; (*rot_x) = CLAMP((*rot_x), -Math_PI / 2, Math_PI / 2); _update_camera(); } Ref<InputEventMouseButton> mb = p_input; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { (*zoom) *= 1.1; if ((*zoom) > 10.0) { (*zoom) = 10.0; } _update_camera(); } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::WHEEL_UP) { (*zoom) /= 1.1; if ((*zoom) < 0.1) { (*zoom) = 0.1; diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp index 8300dcf555..4b69810861 100644 --- a/editor/import_defaults_editor.cpp +++ b/editor/import_defaults_editor.cpp @@ -62,7 +62,7 @@ protected: return; } for (const PropertyInfo &E : properties) { - if (importer->get_option_visibility(E.name, values)) { + if (importer->get_option_visibility("", E.name, values)) { p_list->push_back(E); } } @@ -119,7 +119,7 @@ void ImportDefaultsEditor::_update_importer() { if (importer.is_valid()) { List<ResourceImporter::ImportOption> options; - importer->get_import_options(&options); + importer->get_import_options("", &options); Dictionary d; if (ProjectSettings::get_singleton()->has_setting("importer_defaults/" + importer->get_importer_name())) { d = ProjectSettings::get_singleton()->get("importer_defaults/" + importer->get_importer_name()); diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index a6e1e1d094..cc6b4e66e4 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -42,6 +42,7 @@ public: Vector<String> paths; Set<StringName> checked; bool checking; + String base_options_path; bool _set(const StringName &p_name, const Variant &p_value) { if (values.has(p_name)) { @@ -66,7 +67,7 @@ public: } void _get_property_list(List<PropertyInfo> *p_list) const { for (const PropertyInfo &E : properties) { - if (!importer->get_option_visibility(E.name, values)) { + if (!importer->get_option_visibility(base_options_path, E.name, values)) { continue; } PropertyInfo pi = E; @@ -104,8 +105,9 @@ void ImportDock::set_edit_path(const String &p_path) { params->paths.clear(); params->paths.push_back(p_path); + params->base_options_path = p_path; - _update_options(config); + _update_options(p_path, config); List<Ref<ResourceImporter>> importers; ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_path.get_extension(), &importers); @@ -146,17 +148,18 @@ void ImportDock::_add_keep_import_option(const String &p_importer_name) { } } -void ImportDock::_update_options(const Ref<ConfigFile> &p_config) { +void ImportDock::_update_options(const String &p_path, const Ref<ConfigFile> &p_config) { List<ResourceImporter::ImportOption> options; if (params->importer.is_valid()) { - params->importer->get_import_options(&options); + params->importer->get_import_options(p_path, &options); } params->properties.clear(); params->values.clear(); params->checking = params->paths.size() > 1; params->checked.clear(); + params->base_options_path = p_path; for (const ResourceImporter::ImportOption &E : options) { params->properties.push_back(E.option); @@ -184,10 +187,12 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { // Use the value that is repeated the most. Map<String, Dictionary> value_frequency; + Set<String> extensions; for (int i = 0; i < p_paths.size(); i++) { Ref<ConfigFile> config; config.instantiate(); + extensions.insert(p_paths[i].get_extension()); Error err = config->load(p_paths[i] + ".import"); ERR_CONTINUE(err != OK); @@ -223,13 +228,18 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { ERR_FAIL_COND(params->importer.is_null()); + String base_path; + if (extensions.size() == 1 && p_paths.size() > 0) { + base_path = p_paths[0]; + } List<ResourceImporter::ImportOption> options; - params->importer->get_import_options(&options); + params->importer->get_import_options(base_path, &options); params->properties.clear(); params->values.clear(); params->checking = true; params->checked.clear(); + params->base_options_path = base_path; for (const ResourceImporter::ImportOption &E : options) { params->properties.push_back(E.option); @@ -327,22 +337,22 @@ void ImportDock::_importer_selected(int i_idx) { String name = import_as->get_selected_metadata(); if (name == "keep") { params->importer.unref(); - _update_options(Ref<ConfigFile>()); + _update_options(params->base_options_path, Ref<ConfigFile>()); } else { Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(name); ERR_FAIL_COND(importer.is_null()); params->importer = importer; - Ref<ConfigFile> config; if (params->paths.size()) { + String path = params->paths[0]; config.instantiate(); - Error err = config->load(params->paths[0] + ".import"); + Error err = config->load(path + ".import"); if (err != OK) { config.unref(); } } - _update_options(config); + _update_options(params->base_options_path, config); } } @@ -387,7 +397,7 @@ void ImportDock::_preset_selected(int p_idx) { default: { List<ResourceImporter::ImportOption> options; - params->importer->get_import_options(&options, p_idx); + params->importer->get_import_options(params->base_options_path, &options, p_idx); if (params->checking) { params->checked.clear(); diff --git a/editor/import_dock.h b/editor/import_dock.h index 150c44576d..ac73f3e3c0 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -64,7 +64,7 @@ class ImportDock : public VBoxContainer { void _preset_selected(int p_idx); void _importer_selected(int i_idx); - void _update_options(const Ref<ConfigFile> &p_config = Ref<ConfigFile>()); + void _update_options(const String &p_path, const Ref<ConfigFile> &p_config = Ref<ConfigFile>()); void _update_preset_menu(); void _add_keep_import_option(const String &p_importer_name); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 91ca1465df..c99b34e0c2 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -38,7 +38,7 @@ #include "editor/project_settings_editor.h" #include "scene/gui/grid_container.h" -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For gdscript. #ifdef MODULE_GDSCRIPT_ENABLED #include "modules/gdscript/gdscript.h" #endif diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 36a814c30a..7cafbbc1c4 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -245,11 +245,11 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Ref<InputEventMouseButton> mb = p_event; if (!_has_resource()) { - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { create_resource->set_text(String("No polygon resource on this node.\nCreate and assign one?")); create_resource->popup_centered(); } - return (mb.is_valid() && mb->get_button_index() == 1); + return (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT); } CanvasItemEditor::Tool tool = CanvasItemEditor::get_singleton()->get_current_tool(); @@ -264,7 +264,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Vector2 cpoint = _get_node()->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (mb->is_ctrl_pressed() || mb->is_shift_pressed() || mb->is_alt_pressed()) { return false; @@ -326,7 +326,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return true; } } - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && !edited_point.valid()) { + } else if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed() && !edited_point.valid()) { const PosVertex closest = closest_point(gpoint); if (closest.valid()) { @@ -335,7 +335,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } } } else if (mode == MODE_DELETE) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { const PosVertex closest = closest_point(gpoint); if (closest.valid()) { @@ -346,7 +346,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } if (mode == MODE_CREATE) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { if (_is_line()) { // for lines, we don't have a wip mode, and we can undo each single add point. Vector<Vector2> vertices = _get_polygon(0); @@ -384,7 +384,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return true; } } - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && wip_active) { + } else if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed() && wip_active) { _wip_cancel(); } } @@ -395,7 +395,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) if (mm.is_valid()) { Vector2 gpoint = mm->get_position(); - if (edited_point.valid() && (wip_active || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT))) { + if (edited_point.valid() && (wip_active || (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE)) { Vector2 cpoint = _get_node()->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint))); //Move the point in a single axis. Should only work when editing a polygon and while holding shift. @@ -443,7 +443,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Ref<InputEventKey> k = p_event; if (k.is_valid() && k->is_pressed()) { - if (k->get_keycode() == KEY_DELETE || k->get_keycode() == KEY_BACKSPACE) { + if (k->get_keycode() == Key::KEY_DELETE || k->get_keycode() == Key::BACKSPACE) { if (wip_active && selected_point.polygon == -1) { if (wip.size() > selected_point.vertex) { wip.remove(selected_point.vertex); @@ -460,9 +460,9 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) return true; } } - } else if (wip_active && k->get_keycode() == KEY_ENTER) { + } else if (wip_active && k->get_keycode() == Key::ENTER) { _wip_close(); - } else if (wip_active && k->get_keycode() == KEY_ESCAPE) { + } else if (wip_active && k->get_keycode() == Key::ESCAPE) { _wip_cancel(); } } diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index ad2d9866fa..cfb7217baa 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -42,7 +42,7 @@ StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const { void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && !k->is_echo()) { + if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) { if (selected_point != -1) { _erase_selected(); accept_event(); @@ -51,7 +51,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && tool_create->is_pressed()))) { + if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (mb->get_button_index() == MouseButton::LEFT && tool_create->is_pressed()))) { menu->clear(); animations_menu->clear(); animations_to_add.clear(); @@ -110,7 +110,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { blend_space_draw->update(); // why not // try to see if a point can be selected @@ -132,7 +132,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MouseButton::LEFT) { if (dragging_selected) { // move float point = blend_space->get_blend_point_position(selected_point); @@ -161,7 +161,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven } // *set* the blend - if (mb.is_valid() && !mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { float blend_pos = mb->get_position().x / blend_space_draw->get_size().x; blend_pos *= blend_space->get_max_space() - blend_space->get_min_space(); blend_pos += blend_space->get_min_space(); @@ -184,7 +184,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven _update_edited_point_pos(); } - if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && tool_blend->is_pressed() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { float blend_pos = mm->get_position().x / blend_space_draw->get_size().x; blend_pos *= blend_space->get_max_space() - blend_space->get_min_space(); blend_pos += blend_space->get_min_space(); diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 686a35e442..9af060ed84 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -70,7 +70,7 @@ StringName AnimationNodeBlendSpace2DEditor::get_blend_position_path() const { void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && !k->is_echo()) { + if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) { if (selected_point != -1 || selected_triangle != -1) { _erase_selected(); accept_event(); @@ -79,7 +79,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && tool_create->is_pressed()))) { + if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (mb->get_button_index() == MouseButton::LEFT && tool_create->is_pressed()))) { menu->clear(); animations_menu->clear(); animations_to_add.clear(); @@ -133,7 +133,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { blend_space_draw->update(); //update anyway //try to see if a point can be selected selected_point = -1; @@ -173,7 +173,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && mb->is_pressed() && tool_triangle->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && tool_triangle->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { blend_space_draw->update(); //update anyway //try to see if a point can be selected selected_point = -1; @@ -208,7 +208,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven } } - if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MouseButton::LEFT) { if (dragging_selected) { //move Vector2 point = blend_space->get_blend_point_position(selected_point); @@ -234,7 +234,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven blend_space_draw->update(); } - if (mb.is_valid() && mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && tool_blend->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Vector2 blend_pos = (mb->get_position() / blend_space_draw->get_size()); blend_pos.y = 1.0 - blend_pos.y; blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space()); @@ -268,7 +268,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven blend_space_draw->update(); } - if (mm.is_valid() && tool_blend->is_pressed() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && tool_blend->is_pressed() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { Vector2 blend_pos = (mm->get_position() / blend_space_draw->get_size()); blend_pos.y = 1.0 - blend_pos.y; blend_pos *= (blend_space->get_max_space() - blend_space->get_min_space()); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index ea025dad3e..226046f250 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -41,6 +41,7 @@ #include "editor/plugins/canvas_item_editor_plugin.h" // For onion skinning. #include "editor/plugins/node_3d_editor_plugin.h" // For onion skinning. #include "scene/main/window.h" +#include "scene/resources/animation.h" #include "servers/rendering_server.h" void AnimationPlayerEditor::_node_removed(Node *p_node) { @@ -72,7 +73,7 @@ void AnimationPlayerEditor::_notification(int p_what) { if (player->has_animation(animname)) { Ref<Animation> anim = player->get_animation(animname); if (!anim.is_null()) { - frame->set_max(anim->get_length()); + frame->set_max((double)anim->get_length()); } } } @@ -289,7 +290,7 @@ void AnimationPlayerEditor::_animation_selected(int p_which) { track_editor->set_root(root); } } - frame->set_max(anim->get_length()); + frame->set_max((double)anim->get_length()); } else { track_editor->set_animation(Ref<Animation>()); @@ -474,7 +475,7 @@ double AnimationPlayerEditor::_get_editor_step() const { ERR_FAIL_COND_V(!anim.is_valid(), 0.0); // Use more precise snapping when holding Shift - return Input::get_singleton()->is_key_pressed(KEY_SHIFT) ? anim->get_step() * 0.25 : anim->get_step(); + return Input::get_singleton()->is_key_pressed(Key::SHIFT) ? anim->get_step() * 0.25 : anim->get_step(); } return 0.0; @@ -1014,7 +1015,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set, bool Ref<Animation> anim; anim = player->get_animation(current); - float pos = CLAMP(anim->get_length() * (p_value / frame->get_max()), 0, anim->get_length()); + float pos = CLAMP((double)anim->get_length() * (p_value / frame->get_max()), 0, (double)anim->get_length()); if (track_editor->is_snap_enabled()) { pos = Math::snapped(pos, _get_editor_step()); } @@ -1228,7 +1229,7 @@ void AnimationPlayerEditor::unhandled_key_input(const Ref<InputEvent> &p_ev) { Ref<InputEventKey> k = p_ev; if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->is_alt_pressed() && !k->is_ctrl_pressed() && !k->is_meta_pressed()) { switch (k->get_keycode()) { - case KEY_A: { + case Key::A: { if (!k->is_shift_pressed()) { _play_bw_from_pressed(); } else { @@ -1236,11 +1237,11 @@ void AnimationPlayerEditor::unhandled_key_input(const Ref<InputEvent> &p_ev) { } accept_event(); } break; - case KEY_S: { + case Key::S: { _stop_pressed(); accept_event(); } break; - case KEY_D: { + case Key::D: { if (!k->is_shift_pressed()) { _play_from_pressed(); } else { @@ -1424,7 +1425,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { float pos = cpos + step_off * anim->get_step(); - bool valid = anim->has_loop() || (pos >= 0 && pos <= anim->get_length()); + bool valid = anim->get_loop_mode() != Animation::LoopMode::LOOP_NONE || (pos >= 0 && pos <= anim->get_length()); onion.captures_valid.write[cidx] = valid; if (valid) { player->seek(pos, true); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index a1f96f21bf..191f5d9071 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -66,7 +66,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } Ref<InputEventKey> k = p_event; - if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && !k->is_echo()) { + if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) { if (selected_node != StringName() || selected_transition_to != StringName() || selected_transition_from != StringName()) { _erase_selected(); accept_event(); @@ -76,7 +76,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv Ref<InputEventMouseButton> mb = p_event; //Add new node - if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT))) { + if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == MouseButton::LEFT))) { menu->clear(); animations_menu->clear(); animations_to_add.clear(); @@ -124,7 +124,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } // select node or push a field inside - if (mb.is_valid() && !mb->is_shift_pressed() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_shift_pressed() && mb->is_pressed() && tool_select->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { selected_transition_from = StringName(); selected_transition_to = StringName(); selected_node = StringName(); @@ -216,7 +216,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } //end moving node - if (mb.is_valid() && dragging_selected_attempt && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { + if (mb.is_valid() && dragging_selected_attempt && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { if (dragging_selected) { Ref<AnimationNode> an = state_machine->get_node(selected_node); updating = true; @@ -237,7 +237,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } //connect nodes - if (mb.is_valid() && ((tool_select->is_pressed() && mb->is_shift_pressed()) || tool_connect->is_pressed()) && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { + if (mb.is_valid() && ((tool_select->is_pressed() && mb->is_shift_pressed()) || tool_connect->is_pressed()) && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order if (node_rects[i].node.has_point(mb->get_position())) { //select node since nothing else was selected connecting = true; @@ -250,7 +250,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } //end connecting nodes - if (mb.is_valid() && connecting && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { + if (mb.is_valid() && connecting && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { if (connecting_to_node != StringName()) { if (state_machine->has_transition(connecting_from, connecting_to_node)) { EditorNode::get_singleton()->show_warning(TTR("Transition exists!")); @@ -284,7 +284,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv Ref<InputEventMouseMotion> mm = p_event; //pan window - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x); v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y); } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index aacfc3e305..1a216b3862 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -620,7 +620,7 @@ void EditorAssetLibrary::unhandled_key_input(const Ref<InputEvent> &p_event) { const Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed()) { - if (key->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_F) && is_visible_in_tree()) { + if (key->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F) && is_visible_in_tree()) { filter->grab_focus(); filter->select_all(); accept_event(); diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index 482c08f50a..c76713f534 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -157,7 +157,7 @@ void AudioStreamEditor::_draw_indicator() { void AudioStreamEditor::_on_input_indicator(Ref<InputEvent> p_event) { const Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { _seek_to(mb->get_position().x); } @@ -232,7 +232,7 @@ AudioStreamEditor::AudioStreamEditor() { hbox->add_child(_play_button); _play_button->set_focus_mode(Control::FOCUS_NONE); _play_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_play)); - _play_button->set_shortcut(ED_SHORTCUT("inspector/audio_preview_play_pause", TTR("Audio Preview Play/Pause"), KEY_SPACE)); + _play_button->set_shortcut(ED_SHORTCUT("inspector/audio_preview_play_pause", TTR("Audio Preview Play/Pause"), Key::SPACE)); _stop_button = memnew(Button); _stop_button->set_flat(true); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 061483decf..02756916a5 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -333,7 +333,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(Key::CTRL); // Smart snap using the canvas position Vector2 output = p_target; @@ -461,7 +461,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig } real_t CanvasItemEditor::snap_angle(real_t p_target, real_t p_start) const { - if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CTRL)) && snap_rotation_step != 0) { + if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(Key::CTRL)) && snap_rotation_step != 0) { if (snap_relative) { return Math::snapped(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset + (p_start - (int)(p_start / snap_rotation_step) * snap_rotation_step); } else { @@ -482,7 +482,7 @@ void CanvasItemEditor::unhandled_key_input(const Ref<InputEvent> &p_ev) { } if (k.is_valid()) { - if (k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) { + if (k->get_keycode() == Key::CTRL || k->get_keycode() == Key::ALT || k->get_keycode() == Key::SHIFT) { viewport->update(); } @@ -950,7 +950,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve } // Start dragging a guide - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed()) { // Press button if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) { // Drag a new double guide @@ -1009,7 +1009,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve } // Release confirms the guide move - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { if (show_guides && EditorNode::get_singleton()->get_edited_scene()) { Transform2D xform = viewport_scrollable->get_transform() * transform; @@ -1123,7 +1123,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo if (pan_on_scroll) { // Perform horizontal scrolling first so we can check for Shift being held. if (b->is_pressed() && - (b->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || (b->is_shift_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP))) { + (b->get_button_index() == MouseButton::WHEEL_LEFT || (b->is_shift_pressed() && b->get_button_index() == MouseButton::WHEEL_UP))) { // Pan left view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); @@ -1131,7 +1131,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo } if (b->is_pressed() && - (b->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT || (b->is_shift_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN))) { + (b->get_button_index() == MouseButton::WHEEL_RIGHT || (b->is_shift_pressed() && b->get_button_index() == MouseButton::WHEEL_DOWN))) { // Pan right view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); @@ -1139,13 +1139,13 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo } } - if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (b->is_pressed() && b->get_button_index() == MouseButton::WHEEL_DOWN) { // Scroll or pan down if (pan_on_scroll) { view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); } else { - zoom_widget->set_zoom_by_increments(-1, Input::get_singleton()->is_key_pressed(KEY_ALT)); + zoom_widget->set_zoom_by_increments(-1, Input::get_singleton()->is_key_pressed(Key::ALT)); if (!Math::is_equal_approx(b->get_factor(), 1.0f)) { // Handle high-precision (analog) scrolling. zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f)); @@ -1155,13 +1155,13 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo return true; } - if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (b->is_pressed() && b->get_button_index() == MouseButton::WHEEL_UP) { // Scroll or pan up if (pan_on_scroll) { view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); update_viewport(); } else { - zoom_widget->set_zoom_by_increments(1, Input::get_singleton()->is_key_pressed(KEY_ALT)); + zoom_widget->set_zoom_by_increments(1, Input::get_singleton()->is_key_pressed(Key::ALT)); if (!Math::is_equal_approx(b->get_factor(), 1.0f)) { // Handle high-precision (analog) scrolling. zoom_widget->set_zoom(zoom * ((zoom_widget->get_zoom() / zoom - 1.f) * b->get_factor() + 1.f)); @@ -1173,16 +1173,16 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo if (!panning) { if (b->is_pressed() && - (b->get_button_index() == MOUSE_BUTTON_MIDDLE || - (b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_PAN) || - (b->get_button_index() == MOUSE_BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) { + (b->get_button_index() == MouseButton::MIDDLE || + (b->get_button_index() == MouseButton::LEFT && tool == TOOL_PAN) || + (b->get_button_index() == MouseButton::LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) { // Pan the viewport panning = true; } } if (panning) { - if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != MOUSE_BUTTON_WHEEL_DOWN && b->get_button_index() != MOUSE_BUTTON_WHEEL_UP))) { + if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != MouseButton::WHEEL_DOWN && b->get_button_index() != MouseButton::WHEEL_UP))) { // Stop panning the viewport (for any mouse button press except zooming) panning = false; } @@ -1294,8 +1294,8 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { // Drag the pivot (in pivot mode / with V key) if (drag_type == DRAG_NONE) { - if ((b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || - (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_V && tool == TOOL_SELECT && k->get_modifiers_mask() == 0)) { + if ((b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::LEFT && tool == TOOL_EDIT_PIVOT) || + (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::V && tool == TOOL_SELECT && k->get_modifiers_mask() == Key::NONE)) { List<CanvasItem *> selection = _get_edited_canvas_items(); // Filters the selection with nodes that allow setting the pivot @@ -1345,8 +1345,8 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { // Confirm the pivot move if (drag_selection.size() >= 1 && - ((b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) || - (k.is_valid() && !k->is_pressed() && k->get_keycode() == KEY_V))) { + ((b.is_valid() && !b->is_pressed() && b->get_button_index() == MouseButton::LEFT && tool == TOOL_EDIT_PIVOT) || + (k.is_valid() && !k->is_pressed() && k->get_keycode() == Key::V))) { _commit_canvas_item_state( drag_selection, vformat( @@ -1359,7 +1359,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); drag_type = DRAG_NONE; viewport->update(); @@ -1375,7 +1375,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { // Start rotation if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed()) { if ((b->is_command_pressed() && !b->is_alt_pressed() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { List<CanvasItem *> selection = _get_edited_canvas_items(); @@ -1418,7 +1418,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { } // Confirms the node rotation - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { if (drag_selection.size() != 1) { _commit_canvas_item_state( drag_selection, @@ -1442,7 +1442,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); drag_type = DRAG_NONE; viewport->update(); @@ -1456,7 +1456,7 @@ bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEven Ref<InputEventMouseButton> b = p_event; // Open a sub-scene on double-click - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && b->is_double_click() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && b->is_double_click() && tool == TOOL_SELECT) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; @@ -1475,7 +1475,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { // Starts anchor dragging if needed if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && tool == TOOL_SELECT) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { Control *control = Object::cast_to<Control>(selection[0]); @@ -1595,7 +1595,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { } // Confirms new anchor position - if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { + if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { _commit_canvas_item_state( drag_selection, vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection[0]->get_name())); @@ -1604,7 +1604,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); drag_type = DRAG_NONE; viewport->update(); @@ -1620,7 +1620,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { // Drag resize handles if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && tool == TOOL_SELECT) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; @@ -1774,7 +1774,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { } // Confirm resize - if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { + if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { const Node2D *node2d = Object::cast_to<Node2D>(drag_selection[0]); if (node2d) { // Extends from Node2D. @@ -1811,7 +1811,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; @@ -1829,7 +1829,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { // Drag resize handles if (drag_type == DRAG_NONE) { - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && ((b->is_alt_pressed() && b->is_ctrl_pressed()) || tool == TOOL_SCALE)) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && ((b->is_alt_pressed() && b->is_ctrl_pressed()) || tool == TOOL_SCALE)) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; @@ -1876,7 +1876,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform; bool uniform = m->is_shift_pressed(); - bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); Point2 drag_from_local = simple_xform.xform(drag_from); Point2 drag_to_local = simple_xform.xform(drag_to); @@ -1925,7 +1925,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { } // Confirm resize - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { if (drag_selection.size() != 1) { _commit_canvas_item_state( drag_selection, @@ -1950,7 +1950,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection); drag_type = DRAG_NONE; viewport->update(); @@ -1967,7 +1967,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_NONE) { //Start moving the nodes - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed()) { if ((b->is_alt_pressed() && !b->is_ctrl_pressed()) || tool == TOOL_MOVE) { List<CanvasItem *> selection = _get_edited_canvas_items(); @@ -2050,7 +2050,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } // Confirm the move (only if it was moved) - if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT) { + if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MouseButton::LEFT) { if (transform.affine_inverse().xform(b->get_position()) != drag_from) { if (drag_selection.size() != 1) { _commit_canvas_item_state( @@ -2083,7 +2083,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } // Cancel a drag - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { + if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { _restore_canvas_item_state(drag_selection, true); snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; @@ -2095,7 +2095,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { // Move the canvas items with the arrow keys if (k.is_valid() && k->is_pressed() && (tool == TOOL_SELECT || tool == TOOL_MOVE) && - (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)) { + (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::LEFT || k->get_keycode() == Key::RIGHT)) { if (!k->is_echo()) { // Start moving the canvas items with the keyboard drag_selection = _get_edited_canvas_items(); @@ -2112,13 +2112,13 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { bool move_local_base_rotated = k->is_ctrl_pressed() || k->is_meta_pressed(); Vector2 dir; - if (k->get_keycode() == KEY_UP) { + if (k->get_keycode() == Key::UP) { dir += Vector2(0, -1); - } else if (k->get_keycode() == KEY_DOWN) { + } else if (k->get_keycode() == Key::DOWN) { dir += Vector2(0, 1); - } else if (k->get_keycode() == KEY_LEFT) { + } else if (k->get_keycode() == Key::LEFT) { dir += Vector2(-1, 0); - } else if (k->get_keycode() == KEY_RIGHT) { + } else if (k->get_keycode() == Key::RIGHT) { dir += Vector2(1, 0); } if (k->is_shift_pressed()) { @@ -2166,12 +2166,12 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && (tool == TOOL_SELECT || tool == TOOL_MOVE) && - (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)) { + (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::LEFT || k->get_keycode() == Key::RIGHT)) { // Confirm canvas items move by arrow keys - if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) && - (!Input::get_singleton()->is_key_pressed(KEY_DOWN)) && - (!Input::get_singleton()->is_key_pressed(KEY_LEFT)) && - (!Input::get_singleton()->is_key_pressed(KEY_RIGHT))) { + if ((!Input::get_singleton()->is_key_pressed(Key::UP)) && + (!Input::get_singleton()->is_key_pressed(Key::DOWN)) && + (!Input::get_singleton()->is_key_pressed(Key::LEFT)) && + (!Input::get_singleton()->is_key_pressed(Key::RIGHT))) { if (drag_selection.size() > 1) { _commit_canvas_item_state( drag_selection, @@ -2192,7 +2192,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { return true; } - return (k.is_valid() && (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)); // Accept the key event in any case + return (k.is_valid() && (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::LEFT || k->get_keycode() == Key::RIGHT)); // Accept the key event in any case } bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { @@ -2202,8 +2202,8 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { if (drag_type == DRAG_NONE) { if (b.is_valid() && - ((b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_alt_pressed() && tool == TOOL_SELECT) || - (b->get_button_index() == MOUSE_BUTTON_LEFT && tool == TOOL_LIST_SELECT))) { + ((b->get_button_index() == MouseButton::RIGHT && b->is_alt_pressed() && tool == TOOL_SELECT) || + (b->get_button_index() == MouseButton::LEFT && tool == TOOL_LIST_SELECT))) { // Popup the selection menu list Point2 click = transform.affine_inverse().xform(b->get_position()); @@ -2264,7 +2264,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } } - if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::RIGHT) { add_node_menu->set_size(Vector2(1, 1)); add_node_menu->set_position(get_screen_position() + b->get_position()); add_node_menu->popup(); @@ -2272,7 +2272,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return true; } - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed() && tool == TOOL_SELECT) { // Single item selection Point2 click = transform.affine_inverse().xform(b->get_position()); @@ -2348,7 +2348,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } if (drag_type == DRAG_BOX_SELECTION) { - if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_LEFT) { + if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MouseButton::LEFT) { // Confirms box selection Node *scene = editor->get_edited_scene(); if (scene) { @@ -2377,7 +2377,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return true; } - if (b.is_valid() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::RIGHT) { // Cancel box selection drag_type = DRAG_NONE; viewport->update(); @@ -2392,7 +2392,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } } - if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) { + if (k.is_valid() && k->is_pressed() && k->get_keycode() == Key::ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) { // Unselect everything editor_selection->clear(); viewport->update(); @@ -2414,7 +2414,7 @@ bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) { ruler_tool_origin = snap_point(viewport->get_local_mouse_position() / zoom + view_offset); } - if (b.is_valid() && b->get_button_index() == MOUSE_BUTTON_LEFT) { + if (b.is_valid() && b->get_button_index() == MouseButton::LEFT) { if (b->is_pressed()) { ruler_tool_active = true; } else { @@ -3354,8 +3354,8 @@ void CanvasItemEditor::_draw_selection() { } // Draw the move handles - bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); - bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT); + bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); + bool is_alt = Input::get_singleton()->is_key_pressed(Key::ALT); if (tool == TOOL_MOVE && show_transformation_gizmos) { if (_is_node_movable(canvas_item)) { Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized(); @@ -3391,7 +3391,7 @@ void CanvasItemEditor::_draw_selection() { Transform2D simple_xform = viewport->get_transform() * unscaled_transform; Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); - bool uniform = Input::get_singleton()->is_key_pressed(KEY_SHIFT); + bool uniform = Input::get_singleton()->is_key_pressed(Key::SHIFT); Point2 offset = (simple_xform.affine_inverse().xform(drag_to) - simple_xform.affine_inverse().xform(drag_from)) * zoom; if (drag_type == DRAG_SCALE_X) { @@ -5330,9 +5330,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { select_button->set_toggle_mode(true); select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SELECT)); select_button->set_pressed(true); - select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q)); + select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), Key::Q)); select_button->set_shortcut_context(this); - select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("RMB: Add node at position clicked.")); + select_button->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("RMB: Add node at position clicked.")); hb->add_child(memnew(VSeparator)); @@ -5341,7 +5341,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(move_button); move_button->set_toggle_mode(true); move_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_MOVE)); - move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W)); + move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), Key::W)); move_button->set_shortcut_context(this); move_button->set_tooltip(TTR("Move Mode")); @@ -5350,7 +5350,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(rotate_button); rotate_button->set_toggle_mode(true); rotate_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_ROTATE)); - rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E)); + rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), Key::E)); rotate_button->set_shortcut_context(this); rotate_button->set_tooltip(TTR("Rotate Mode")); @@ -5359,7 +5359,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(scale_button); scale_button->set_toggle_mode(true); scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SCALE)); - scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), KEY_S)); + scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), Key::S)); scale_button->set_shortcut_context(this); scale_button->set_tooltip(TTR("Scale Mode")); @@ -5384,7 +5384,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(pan_button); pan_button->set_toggle_mode(true); pan_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_PAN)); - pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), KEY_G)); + pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), Key::G)); pan_button->set_shortcut_context(this); pan_button->set_tooltip(TTR("You can also use Pan View shortcut (Space by default) to pan in any mode.")); @@ -5393,7 +5393,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(ruler_button); ruler_button->set_toggle_mode(true); ruler_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_RULER)); - ruler_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/ruler_mode", TTR("Ruler Mode"), KEY_R)); + ruler_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/ruler_mode", TTR("Ruler Mode"), Key::R)); ruler_button->set_shortcut_context(this); ruler_button->set_tooltip(TTR("Ruler Mode")); @@ -5405,7 +5405,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { smart_snap_button->set_toggle_mode(true); smart_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_smart_snap)); smart_snap_button->set_tooltip(TTR("Toggle smart snapping.")); - smart_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_smart_snap", TTR("Use Smart Snap"), KEY_MASK_SHIFT | KEY_S)); + smart_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_smart_snap", TTR("Use Smart Snap"), KeyModifierMask::SHIFT | Key::S)); smart_snap_button->set_shortcut_context(this); grid_snap_button = memnew(Button); @@ -5414,7 +5414,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { grid_snap_button->set_toggle_mode(true); grid_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_grid_snap)); grid_snap_button->set_tooltip(TTR("Toggle grid snapping.")); - grid_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_grid_snap", TTR("Use Grid Snap"), KEY_MASK_SHIFT | KEY_G)); + grid_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_grid_snap", TTR("Use Grid Snap"), KeyModifierMask::SHIFT | Key::G)); grid_snap_button->set_shortcut_context(this); snap_config_menu = memnew(MenuButton); @@ -5457,7 +5457,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(LOCK_SELECTED)); lock_button->set_tooltip(TTR("Lock selected node, preventing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KEY_MASK_CMD | KEY_L)); + lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L)); unlock_button = memnew(Button); unlock_button->set_flat(true); @@ -5465,7 +5465,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNLOCK_SELECTED)); unlock_button->set_tooltip(TTR("Unlock selected node, allowing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_L)); + unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L)); group_button = memnew(Button); group_button->set_flat(true); @@ -5473,7 +5473,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(GROUP_SELECTED)); group_button->set_tooltip(TTR("Makes sure the object's children are not selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KEY_MASK_CMD | KEY_G)); + group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G)); ungroup_button = memnew(Button); ungroup_button->set_flat(true); @@ -5481,7 +5481,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNGROUP_SELECTED)); ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G)); + ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); hb->add_child(memnew(VSeparator)); @@ -5495,7 +5495,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->set_hide_on_checkable_item_selection(false); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES); p->add_separator(); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bone2D Node(s) from Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bone2D Node(s) from Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::B), SKELETON_MAKE_BONES); p->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback)); hb->add_child(memnew(VSeparator)); @@ -5519,21 +5519,21 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p = view_menu->get_popup(); p->set_hide_on_checkable_item_selection(false); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_NUMBERSIGN), SHOW_GRID); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), Key::NUMBERSIGN), SHOW_GRID); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), Key::H), SHOW_HELPERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), Key::Y), SHOW_GUIDES); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_edit_locks", TTR("Show Group And Lock Icons")), SHOW_EDIT_LOCKS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_transformation_gizmos", TTR("Show Transformation Gizmos")), SHOW_TRANSFORMATION_GIZMOS); p->add_separator(); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), Key::F), VIEW_CENTER_TO_SELECTION); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KeyModifierMask::SHIFT | Key::F), VIEW_FRAME_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/clear_guides", TTR("Clear Guides")), CLEAR_GUIDES); p->add_separator(); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_P), PREVIEW_CANVAS_SCALE); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::P), PREVIEW_CANVAS_SCALE); hb->add_child(memnew(VSeparator)); @@ -5604,7 +5604,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { key_insert_button->set_focus_mode(FOCUS_NONE); key_insert_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(ANIM_INSERT_KEY)); key_insert_button->set_tooltip(TTR("Insert keys (based on mask).")); - key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), KEY_INSERT)); + key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), Key::INSERT)); key_insert_button->set_shortcut_context(this); animation_hb->add_child(key_insert_button); @@ -5627,11 +5627,11 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p = animation_menu->get_popup(); p->add_shortcut(ED_GET_SHORTCUT("canvas_item_editor/anim_insert_key"), ANIM_INSERT_KEY); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key_existing_tracks", TTR("Insert Key (Existing Tracks)"), KEY_MASK_CMD + KEY_INSERT), ANIM_INSERT_KEY_EXISTING); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key_existing_tracks", TTR("Insert Key (Existing Tracks)"), KeyModifierMask::CMD + Key::INSERT), ANIM_INSERT_KEY_EXISTING); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_copy_pose", TTR("Copy Pose")), ANIM_COPY_POSE); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_paste_pose", TTR("Paste Pose")), ANIM_PASTE_POSE); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_clear_pose", TTR("Clear Pose"), KEY_MASK_SHIFT | KEY_K), ANIM_CLEAR_POSE); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_clear_pose", TTR("Clear Pose"), KeyModifierMask::SHIFT | Key::K), ANIM_CLEAR_POSE); snap_dialog = memnew(SnapDialog); snap_dialog->connect("confirmed", callable_mp(this, &CanvasItemEditor::_snap_changed)); @@ -5651,9 +5651,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { add_node_menu->add_icon_item(editor->get_scene_tree_dock()->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Instance Scene Here")); add_node_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_add_node_pressed)); - multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY); - divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE); - pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), KEY_SPACE); + multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), Key::KP_MULTIPLY); + divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), Key::KP_DIVIDE); + pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), Key::SPACE); skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); singleton = this; @@ -5662,16 +5662,16 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { // those shortcuts one by one. // Resetting zoom to 100% is a duplicate shortcut of `canvas_item_editor/reset_zoom`, // but it ensures both 1 and Ctrl + 0 can be used to reset zoom. - ED_SHORTCUT("canvas_item_editor/zoom_3.125_percent", TTR("Zoom to 3.125%"), KEY_MASK_SHIFT | KEY_5); - ED_SHORTCUT("canvas_item_editor/zoom_6.25_percent", TTR("Zoom to 6.25%"), KEY_MASK_SHIFT | KEY_4); - ED_SHORTCUT("canvas_item_editor/zoom_12.5_percent", TTR("Zoom to 12.5%"), KEY_MASK_SHIFT | KEY_3); - ED_SHORTCUT("canvas_item_editor/zoom_25_percent", TTR("Zoom to 25%"), KEY_MASK_SHIFT | KEY_2); - ED_SHORTCUT("canvas_item_editor/zoom_50_percent", TTR("Zoom to 50%"), KEY_MASK_SHIFT | KEY_1); - ED_SHORTCUT("canvas_item_editor/zoom_100_percent", TTR("Zoom to 100%"), KEY_1); - ED_SHORTCUT("canvas_item_editor/zoom_200_percent", TTR("Zoom to 200%"), KEY_2); - ED_SHORTCUT("canvas_item_editor/zoom_400_percent", TTR("Zoom to 400%"), KEY_3); - ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom to 800%"), KEY_4); - ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom to 1600%"), KEY_5); + ED_SHORTCUT("canvas_item_editor/zoom_3.125_percent", TTR("Zoom to 3.125%"), KeyModifierMask::SHIFT | Key::KEY_5); + ED_SHORTCUT("canvas_item_editor/zoom_6.25_percent", TTR("Zoom to 6.25%"), KeyModifierMask::SHIFT | Key::KEY_4); + ED_SHORTCUT("canvas_item_editor/zoom_12.5_percent", TTR("Zoom to 12.5%"), KeyModifierMask::SHIFT | Key::KEY_3); + ED_SHORTCUT("canvas_item_editor/zoom_25_percent", TTR("Zoom to 25%"), KeyModifierMask::SHIFT | Key::KEY_2); + ED_SHORTCUT("canvas_item_editor/zoom_50_percent", TTR("Zoom to 50%"), KeyModifierMask::SHIFT | Key::KEY_1); + ED_SHORTCUT("canvas_item_editor/zoom_100_percent", TTR("Zoom to 100%"), Key::KEY_1); + ED_SHORTCUT("canvas_item_editor/zoom_200_percent", TTR("Zoom to 200%"), Key::KEY_2); + ED_SHORTCUT("canvas_item_editor/zoom_400_percent", TTR("Zoom to 400%"), Key::KEY_3); + ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom to 800%"), Key::KEY_4); + ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom to 1600%"), Key::KEY_5); set_process_unhandled_key_input(true); @@ -6059,9 +6059,9 @@ bool CanvasItemEditorViewport::_only_packed_scenes_selected() const { } void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) { - bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT); - bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); - bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT); + bool is_shift = Input::get_singleton()->is_key_pressed(Key::SHIFT); + bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); + bool is_alt = Input::get_singleton()->is_key_pressed(Key::ALT); selected_files.clear(); Dictionary d = p_data; diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp index 53314db1e9..7a8680c4dd 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp @@ -142,7 +142,7 @@ EditorPlugin::AfterGUIInput CollisionPolygon3DEditor::forward_spatial_gui_input( switch (mode) { case MODE_CREATE: { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { if (!wip_active) { wip.clear(); wip.push_back(cpoint); @@ -166,14 +166,14 @@ EditorPlugin::AfterGUIInput CollisionPolygon3DEditor::forward_spatial_gui_input( return EditorPlugin::AFTER_GUI_INPUT_STOP; } } - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && wip_active) { + } else if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed() && wip_active) { _wip_close(); } } break; case MODE_EDIT: { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (mb->is_ctrl_pressed()) { if (poly.size() < 3) { @@ -267,7 +267,7 @@ EditorPlugin::AfterGUIInput CollisionPolygon3DEditor::forward_spatial_gui_input( } } } - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { + if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed() && edited_point == -1) { int closest_idx = -1; Vector2 closest_pos; real_t closest_dist = 1e10; @@ -301,7 +301,7 @@ EditorPlugin::AfterGUIInput CollisionPolygon3DEditor::forward_spatial_gui_input( Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { - if (edited_point != -1 && (wip_active || mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) { + if (edited_point != -1 && (wip_active || (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE)) { Vector2 gpoint = mm->get_position(); Vector3 ray_from = p_camera->project_ray_origin(gpoint); @@ -317,7 +317,7 @@ EditorPlugin::AfterGUIInput CollisionPolygon3DEditor::forward_spatial_gui_input( Vector2 cpoint(spoint.x, spoint.y); - if (snap_ignore && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (snap_ignore && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { snap_ignore = false; } diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index fb32d7b1fd..94fd9a5a08 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -183,7 +183,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { size.y = p_point.y * RECT_HANDLES[idx].y * 2; } - if (Input::get_singleton()->is_key_pressed(KEY_ALT)) { + if (Input::get_singleton()->is_key_pressed(Key::ALT)) { rect->set_size(size.abs()); node->set_global_position(original_transform.get_origin()); } else { @@ -333,7 +333,7 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e if (mb.is_valid()) { Vector2 gpoint = mb->get_position(); - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { for (int i = 0; i < handles.size(); i++) { if (xform.xform(handles[i]).distance_to(gpoint) < 8) { @@ -394,7 +394,7 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e return false; } - if (shape_type == RECTANGLE_SHAPE && k->get_keycode() == KEY_ALT) { + if (shape_type == RECTANGLE_SHAPE && k->get_keycode() == Key::ALT) { set_handle(edit_handle, last_point); // Update handle when Alt key is toggled. } } diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 43eb6a7ce9..005cf27e8a 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -115,16 +115,16 @@ void CurveEditor::gui_input(const Ref<InputEvent> &p_event) { } switch (mb.get_button_index()) { - case MOUSE_BUTTON_RIGHT: + case MouseButton::RIGHT: _context_click_pos = mpos; open_context_menu(get_global_transform().xform(mpos)); break; - case MOUSE_BUTTON_MIDDLE: + case MouseButton::MIDDLE: remove_point(_hover_point); break; - case MOUSE_BUTTON_LEFT: + case MouseButton::LEFT: _dragging = true; break; default: @@ -132,7 +132,7 @@ void CurveEditor::gui_input(const Ref<InputEvent> &p_event) { } } - if (!mb.is_pressed() && _dragging && mb.get_button_index() == MOUSE_BUTTON_LEFT) { + if (!mb.is_pressed() && _dragging && mb.get_button_index() == MouseButton::LEFT) { _dragging = false; if (_has_undo_data) { UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); @@ -210,7 +210,7 @@ void CurveEditor::gui_input(const Ref<InputEvent> &p_event) { tangent = 9999 * (dir.y >= 0 ? 1 : -1); } - bool link = !Input::get_singleton()->is_key_pressed(KEY_SHIFT); + bool link = !Input::get_singleton()->is_key_pressed(Key::SHIFT); if (_selected_tangent == TANGENT_LEFT) { curve.set_point_left_tangent(_selected_point, tangent); @@ -240,7 +240,7 @@ void CurveEditor::gui_input(const Ref<InputEvent> &p_event) { const InputEventKey &key = **key_ref; if (key.is_pressed() && _selected_point != -1) { - if (key.get_keycode() == KEY_DELETE) { + if (key.get_keycode() == Key::KEY_DELETE) { remove_point(_selected_point); } } diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp index cc916aad8b..51e1b639a4 100644 --- a/editor/plugins/debugger_editor_plugin.cpp +++ b/editor/plugins/debugger_editor_plugin.cpp @@ -41,10 +41,10 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(EditorNode *p_editor, MenuButton *p_debug_menu) { EditorDebuggerServer::initialize(); - ED_SHORTCUT("debugger/step_into", TTR("Step Into"), KEY_F11); - ED_SHORTCUT("debugger/step_over", TTR("Step Over"), KEY_F10); + ED_SHORTCUT("debugger/step_into", TTR("Step Into"), Key::F11); + ED_SHORTCUT("debugger/step_over", TTR("Step Over"), Key::F10); ED_SHORTCUT("debugger/break", TTR("Break")); - ED_SHORTCUT("debugger/continue", TTR("Continue"), KEY_F12); + ED_SHORTCUT("debugger/continue", TTR("Continue"), Key::F12); ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open")); ED_SHORTCUT("debugger/debug_with_external_editor", TTR("Debug with External Editor")); diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index dc16a7a325..4b18ac6e9f 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -36,7 +36,7 @@ void MeshEditor::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { rot_x -= mm->get_relative().y * 0.01; rot_y -= mm->get_relative().x * 0.01; if (rot_x < -Math_PI / 2) { diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index e4bc9ef690..b74d229d3e 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -185,7 +185,7 @@ void ViewportRotationControl::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); const Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { Vector2 pos = mb->get_position(); if (mb->is_pressed()) { if (pos.distance_to(get_size() / 2.0) < get_size().x / 2.0) { @@ -901,36 +901,36 @@ void Node3DEditorViewport::_compute_edit(const Point2 &p_point) { } } -static int _get_key_modifier_setting(const String &p_property) { +static Key _get_key_modifier_setting(const String &p_property) { switch (EditorSettings::get_singleton()->get(p_property).operator int()) { case 0: - return 0; + return Key::NONE; case 1: - return KEY_SHIFT; + return Key::SHIFT; case 2: - return KEY_ALT; + return Key::ALT; case 3: - return KEY_META; + return Key::META; case 4: - return KEY_CTRL; + return Key::CTRL; } - return 0; + return Key::NONE; } -static int _get_key_modifier(Ref<InputEventWithModifiers> e) { +static Key _get_key_modifier(Ref<InputEventWithModifiers> e) { if (e->is_shift_pressed()) { - return KEY_SHIFT; + return Key::SHIFT; } if (e->is_alt_pressed()) { - return KEY_ALT; + return Key::ALT; } if (e->is_ctrl_pressed()) { - return KEY_CTRL; + return Key::CTRL; } if (e->is_meta_pressed()) { - return KEY_META; + return Key::META; } - return 0; + return Key::NONE; } bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) { @@ -1336,7 +1336,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { const real_t zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor(); switch (b->get_button_index()) { - case MOUSE_BUTTON_WHEEL_UP: { + case MouseButton::WHEEL_UP: { if (b->is_alt_pressed()) { scale_fov(-0.05); } else { @@ -1347,7 +1347,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } } break; - case MOUSE_BUTTON_WHEEL_DOWN: { + case MouseButton::WHEEL_DOWN: { if (b->is_alt_pressed()) { scale_fov(0.05); } else { @@ -1358,7 +1358,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } } break; - case MOUSE_BUTTON_RIGHT: { + case MouseButton::RIGHT: { NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); if (b->is_pressed() && _edit.gizmo.is_valid()) { @@ -1415,7 +1415,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } if (b->is_pressed()) { - const int mod = _get_key_modifier(b); + const Key mod = _get_key_modifier(b); if (!orthogonal) { if (mod == _get_key_modifier_setting("editors/3d/freelook/freelook_activation_modifier")) { set_freelook_active(true); @@ -1432,7 +1432,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } break; - case MOUSE_BUTTON_MIDDLE: { + case MouseButton::MIDDLE: { if (b->is_pressed() && _edit.mode != TRANSFORM_NONE) { switch (_edit.plane) { case TRANSFORM_VIEW: { @@ -1463,7 +1463,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } } break; - case MOUSE_BUTTON_LEFT: { + case MouseButton::LEFT: { if (b->is_pressed()) { NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->is_alt_pressed()) { @@ -1724,7 +1724,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } - if (spatial_editor->get_current_hover_gizmo().is_null() && !(m->get_button_mask() & 1) && !_edit.gizmo.is_valid()) { + if (spatial_editor->get_current_hover_gizmo().is_null() && (m->get_button_mask() & MouseButton::MASK_LEFT) == MouseButton::NONE && !_edit.gizmo.is_valid()) { _transform_gizmo_select(_edit.mouse_pos, true); } @@ -1737,7 +1737,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { String n = _edit.gizmo->get_handle_name(_edit.gizmo_handle); set_message(n + ": " + String(v)); - } else if (m->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + } else if ((m->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) { nav_mode = NAVIGATION_ORBIT; } else if (nav_scheme == NAVIGATION_MODO && m->is_alt_pressed() && m->is_shift_pressed()) { @@ -1827,7 +1827,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } else { // Alternative planar scaling mode - if (_get_key_modifier(m) != KEY_SHIFT) { + if (_get_key_modifier(m) != Key::SHIFT) { motion = motion_mask.dot(motion) * motion_mask; } } @@ -2082,7 +2082,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } } - } else if ((m->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) || freelook_active) { + } else if ((m->get_button_mask() & MouseButton::MASK_RIGHT) != MouseButton::NONE || freelook_active) { if (nav_scheme == NAVIGATION_MAYA && m->is_alt_pressed()) { nav_mode = NAVIGATION_ZOOM; } else if (freelook_active) { @@ -2091,14 +2091,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { nav_mode = NAVIGATION_PAN; } - } else if (m->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) { - const int mod = _get_key_modifier(m); + } else if ((m->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { + const Key mod = _get_key_modifier(m); if (nav_scheme == NAVIGATION_GODOT) { if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) { nav_mode = NAVIGATION_PAN; } else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) { nav_mode = NAVIGATION_ZOOM; - } else if (mod == KEY_ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) { + } else if (mod == Key::ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) { // Always allow Alt as a modifier to better support graphic tablets. nav_mode = NAVIGATION_ORBIT; } @@ -2109,14 +2109,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } } else if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_3_button_mouse")) { // Handle trackpad (no external mouse) use case - const int mod = _get_key_modifier(m); + const Key mod = _get_key_modifier(m); - if (mod) { + if (mod != Key::NONE) { if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) { nav_mode = NAVIGATION_PAN; } else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) { nav_mode = NAVIGATION_ZOOM; - } else if (mod == KEY_ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) { + } else if (mod == Key::ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) { // Always allow Alt as a modifier to better support graphic tablets. nav_mode = NAVIGATION_ORBIT; } @@ -2164,13 +2164,13 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { NavigationMode nav_mode = NAVIGATION_NONE; if (nav_scheme == NAVIGATION_GODOT) { - const int mod = _get_key_modifier(pan_gesture); + const Key mod = _get_key_modifier(pan_gesture); if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier")) { nav_mode = NAVIGATION_PAN; } else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier")) { nav_mode = NAVIGATION_ZOOM; - } else if (mod == KEY_ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) { + } else if (mod == Key::ALT || mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier")) { // Always allow Alt as a modifier to better support graphic tablets. nav_mode = NAVIGATION_ORBIT; } @@ -2215,9 +2215,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_numpad")) { - const uint32_t code = k->get_keycode(); - if (code >= KEY_0 && code <= KEY_9) { - k->set_keycode(code - KEY_0 + KEY_KP_0); + const Key code = k->get_keycode(); + if (code >= Key::KEY_0 && code <= Key::KEY_9) { + k->set_keycode(code - Key::KEY_0 + Key::KP_0); } } @@ -2316,11 +2316,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { if (!orthogonal && ED_IS_SHORTCUT("spatial_editor/freelook_toggle", p_event)) { set_freelook_active(!is_freelook_active()); - } else if (k->get_keycode() == KEY_ESCAPE) { + } else if (k->get_keycode() == Key::ESCAPE) { set_freelook_active(false); } - if (k->get_keycode() == KEY_SPACE) { + if (k->get_keycode() == Key::SPACE) { if (!k->is_pressed()) { emit_signal(SNAME("toggle_maximize_view"), this); } @@ -2887,13 +2887,13 @@ void Node3DEditorViewport::_notification(int p_what) { // Color labels depending on performance level ("good" = green, "OK" = yellow, "bad" = red). // Middle point is at 15 ms. - cpu_time_label->set_text(vformat(TTR("CPU Time: %s ms"), rtos(cpu_time).pad_decimals(1))); + cpu_time_label->set_text(vformat(TTR("CPU Time: %s ms"), rtos(cpu_time).pad_decimals(2))); cpu_time_label->add_theme_color_override( "font_color", frame_time_gradient->get_color_at_offset( Math::range_lerp(cpu_time, 0, 30, 0, 1))); - gpu_time_label->set_text(vformat(TTR("GPU Time: %s ms"), rtos(gpu_time).pad_decimals(1))); + gpu_time_label->set_text(vformat(TTR("GPU Time: %s ms"), rtos(gpu_time).pad_decimals(2))); // Middle point is at 15 ms. gpu_time_label->add_theme_color_override( "font_color", @@ -4198,8 +4198,8 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_ return; } - bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT); - bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool is_shift = Input::get_singleton()->is_key_pressed(Key::SHIFT); + bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); selected_files.clear(); Dictionary d = p_data; @@ -4394,18 +4394,18 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito view_menu->get_popup()->set_item_tooltip(shadeless_idx, unsupported_tooltip); } - ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), KEY_A); - ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D); - ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W); - ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S); - ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_E); - ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_Q); - ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT); - ED_SHORTCUT("spatial_editor/freelook_slow_modifier", TTR("Freelook Slow Modifier"), KEY_ALT); + ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), Key::A); + ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), Key::D); + ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), Key::W); + ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), Key::S); + ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), Key::E); + ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), Key::Q); + ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), Key::SHIFT); + ED_SHORTCUT("spatial_editor/freelook_slow_modifier", TTR("Freelook Slow Modifier"), Key::ALT); preview_camera = memnew(CheckBox); preview_camera->set_text(TTR("Preview")); - preview_camera->set_shortcut(ED_SHORTCUT("spatial_editor/toggle_camera_preview", TTR("Toggle Camera Preview"), KEY_MASK_CMD | KEY_P)); + preview_camera->set_shortcut(ED_SHORTCUT("spatial_editor/toggle_camera_preview", TTR("Toggle Camera Preview"), KeyModifierMask::CMD | Key::P)); vbox->add_child(preview_camera); preview_camera->set_h_size_flags(0); preview_camera->hide(); @@ -4519,7 +4519,7 @@ void Node3DEditorViewportContainer::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { Vector2 size = get_size(); @@ -6625,7 +6625,7 @@ void Node3DEditor::unhandled_key_input(const Ref<InputEvent> &p_event) { return; } - snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CTRL); + snap_key_enabled = Input::get_singleton()->is_key_pressed(Key::CTRL); } void Node3DEditor::_sun_environ_settings_pressed() { @@ -6637,7 +6637,7 @@ void Node3DEditor::_sun_environ_settings_pressed() { void Node3DEditor::_add_sun_to_scene(bool p_already_added_environment) { sun_environ_popup->hide(); - if (!p_already_added_environment && world_env_count == 0 && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!p_already_added_environment && world_env_count == 0 && Input::get_singleton()->is_key_pressed(Key::SHIFT)) { // Prevent infinite feedback loop between the sun and environment methods. _add_environment_to_scene(true); } @@ -6665,7 +6665,7 @@ void Node3DEditor::_add_sun_to_scene(bool p_already_added_environment) { void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) { sun_environ_popup->hide(); - if (!p_already_added_sun && directional_light_count == 0 && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!p_already_added_sun && directional_light_count == 0 && Input::get_singleton()->is_key_pressed(Key::SHIFT)) { // Prevent infinite feedback loop between the sun and environment methods. _add_sun_to_scene(true); } @@ -7184,7 +7184,7 @@ void Node3DEditor::_update_preview_environment() { void Node3DEditor::_sun_direction_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { sun_rotation.x += mm->get_relative().y * (0.02 * EDSCALE); sun_rotation.y -= mm->get_relative().x * (0.02 * EDSCALE); sun_rotation.x = CLAMP(sun_rotation.x, -Math_TAU / 4, Math_TAU / 4); @@ -7241,9 +7241,9 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SELECT]->set_pressed(true); button_binds.write[0] = MENU_TOOL_SELECT; tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); - tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), KEY_Q)); + tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), Key::Q)); tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this); - tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); + tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); hbc_menu->add_child(memnew(VSeparator)); tool_button[TOOL_MODE_MOVE] = memnew(Button); @@ -7252,7 +7252,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_MOVE]->set_flat(true); button_binds.write[0] = MENU_TOOL_MOVE; tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); - tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), KEY_W)); + tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), Key::W)); tool_button[TOOL_MODE_MOVE]->set_shortcut_context(this); tool_button[TOOL_MODE_ROTATE] = memnew(Button); @@ -7261,7 +7261,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_ROTATE]->set_flat(true); button_binds.write[0] = MENU_TOOL_ROTATE; tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); - tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), KEY_E)); + tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), Key::E)); tool_button[TOOL_MODE_ROTATE]->set_shortcut_context(this); tool_button[TOOL_MODE_SCALE] = memnew(Button); @@ -7270,7 +7270,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SCALE]->set_flat(true); button_binds.write[0] = MENU_TOOL_SCALE; tool_button[TOOL_MODE_SCALE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); - tool_button[TOOL_MODE_SCALE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTR("Scale Mode"), KEY_R)); + tool_button[TOOL_MODE_SCALE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTR("Scale Mode"), Key::R)); tool_button[TOOL_MODE_SCALE]->set_shortcut_context(this); hbc_menu->add_child(memnew(VSeparator)); @@ -7290,7 +7290,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock selected node, preventing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KEY_MASK_CMD | KEY_L)); + tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L)); tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); @@ -7299,7 +7299,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock selected node, allowing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_L)); + tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L)); tool_button[TOOL_GROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]); @@ -7308,7 +7308,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KEY_MASK_CMD | KEY_G)); + tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G)); tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]); @@ -7317,7 +7317,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Restores the object's children's ability to be selected.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. - tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G)); + tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); hbc_menu->add_child(memnew(VSeparator)); @@ -7327,7 +7327,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_flat(true); button_binds.write[0] = MENU_TOOL_LOCAL_COORDS; tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); - tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Use Local Space"), KEY_T)); + tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Use Local Space"), Key::T)); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut_context(this); tool_option_button[TOOL_OPT_USE_SNAP] = memnew(Button); @@ -7336,7 +7336,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_option_button[TOOL_OPT_USE_SNAP]->set_flat(true); button_binds.write[0] = MENU_TOOL_USE_SNAP; tool_option_button[TOOL_OPT_USE_SNAP]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); - tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut(ED_SHORTCUT("spatial_editor/snap", TTR("Use Snap"), KEY_Y)); + tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut(ED_SHORTCUT("spatial_editor/snap", TTR("Use Snap"), Key::Y)); tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut_context(this); hbc_menu->add_child(memnew(VSeparator)); @@ -7382,27 +7382,27 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { preview_node = memnew(Node3D); preview_bounds = AABB(); - ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KEY_MASK_ALT + KEY_KP_7); - ED_SHORTCUT("spatial_editor/top_view", TTR("Top View"), KEY_KP_7); - ED_SHORTCUT("spatial_editor/rear_view", TTR("Rear View"), KEY_MASK_ALT + KEY_KP_1); - ED_SHORTCUT("spatial_editor/front_view", TTR("Front View"), KEY_KP_1); - ED_SHORTCUT("spatial_editor/left_view", TTR("Left View"), KEY_MASK_ALT + KEY_KP_3); - ED_SHORTCUT("spatial_editor/right_view", TTR("Right View"), KEY_KP_3); - ED_SHORTCUT("spatial_editor/orbit_view_down", TTR("Orbit View Down"), KEY_KP_2); - ED_SHORTCUT("spatial_editor/orbit_view_left", TTR("Orbit View Left"), KEY_KP_4); - ED_SHORTCUT("spatial_editor/orbit_view_right", TTR("Orbit View Right"), KEY_KP_6); - ED_SHORTCUT("spatial_editor/orbit_view_up", TTR("Orbit View Up"), KEY_KP_8); - ED_SHORTCUT("spatial_editor/orbit_view_180", TTR("Orbit View 180"), KEY_KP_9); - ED_SHORTCUT("spatial_editor/switch_perspective_orthogonal", TTR("Switch Perspective/Orthogonal View"), KEY_KP_5); - ED_SHORTCUT("spatial_editor/insert_anim_key", TTR("Insert Animation Key"), KEY_K); - ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), KEY_O); - ED_SHORTCUT("spatial_editor/focus_selection", TTR("Focus Selection"), KEY_F); - ED_SHORTCUT("spatial_editor/align_transform_with_view", TTR("Align Transform with View"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_M); - ED_SHORTCUT("spatial_editor/align_rotation_with_view", TTR("Align Rotation with View"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_F); - ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KEY_MASK_SHIFT + KEY_F); - ED_SHORTCUT("spatial_editor/decrease_fov", TTR("Decrease Field of View"), KEY_MASK_CMD + KEY_EQUAL); // Usually direct access key for `KEY_PLUS`. - ED_SHORTCUT("spatial_editor/increase_fov", TTR("Increase Field of View"), KEY_MASK_CMD + KEY_MINUS); - ED_SHORTCUT("spatial_editor/reset_fov", TTR("Reset Field of View to Default"), KEY_MASK_CMD + KEY_0); + ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KeyModifierMask::ALT + Key::KP_7); + ED_SHORTCUT("spatial_editor/top_view", TTR("Top View"), Key::KP_7); + ED_SHORTCUT("spatial_editor/rear_view", TTR("Rear View"), KeyModifierMask::ALT + Key::KP_1); + ED_SHORTCUT("spatial_editor/front_view", TTR("Front View"), Key::KP_1); + ED_SHORTCUT("spatial_editor/left_view", TTR("Left View"), KeyModifierMask::ALT + Key::KP_3); + ED_SHORTCUT("spatial_editor/right_view", TTR("Right View"), Key::KP_3); + ED_SHORTCUT("spatial_editor/orbit_view_down", TTR("Orbit View Down"), Key::KP_2); + ED_SHORTCUT("spatial_editor/orbit_view_left", TTR("Orbit View Left"), Key::KP_4); + ED_SHORTCUT("spatial_editor/orbit_view_right", TTR("Orbit View Right"), Key::KP_6); + ED_SHORTCUT("spatial_editor/orbit_view_up", TTR("Orbit View Up"), Key::KP_8); + ED_SHORTCUT("spatial_editor/orbit_view_180", TTR("Orbit View 180"), Key::KP_9); + ED_SHORTCUT("spatial_editor/switch_perspective_orthogonal", TTR("Switch Perspective/Orthogonal View"), Key::KP_5); + ED_SHORTCUT("spatial_editor/insert_anim_key", TTR("Insert Animation Key"), Key::K); + ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), Key::O); + ED_SHORTCUT("spatial_editor/focus_selection", TTR("Focus Selection"), Key::F); + ED_SHORTCUT("spatial_editor/align_transform_with_view", TTR("Align Transform with View"), KeyModifierMask::ALT + KeyModifierMask::CMD + Key::M); + ED_SHORTCUT("spatial_editor/align_rotation_with_view", TTR("Align Rotation with View"), KeyModifierMask::ALT + KeyModifierMask::CMD + Key::F); + ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KeyModifierMask::SHIFT + Key::F); + ED_SHORTCUT("spatial_editor/decrease_fov", TTR("Decrease Field of View"), KeyModifierMask::CMD + Key::EQUAL); // Usually direct access key for `KEY_PLUS`. + ED_SHORTCUT("spatial_editor/increase_fov", TTR("Increase Field of View"), KeyModifierMask::CMD + Key::MINUS); + ED_SHORTCUT("spatial_editor/reset_fov", TTR("Reset Field of View to Default"), KeyModifierMask::CMD + Key::KEY_0); PopupMenu *p; @@ -7413,7 +7413,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { hbc_menu->add_child(transform_menu); p = transform_menu->get_popup(); - p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap Object to Floor"), KEY_PAGEDOWN), MENU_SNAP_TO_FLOOR); + p->add_shortcut(ED_SHORTCUT("spatial_editor/snap_to_floor", TTR("Snap Object to Floor"), Key::PAGEDOWN), MENU_SNAP_TO_FLOOR); p->add_shortcut(ED_SHORTCUT("spatial_editor/transform_dialog", TTR("Transform Dialog...")), MENU_TRANSFORM_DIALOG); p->add_separator(); @@ -7445,19 +7445,19 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { accept = memnew(AcceptDialog); editor->get_gui_base()->add_child(accept); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KEY_MASK_CMD + KEY_1), MENU_VIEW_USE_1_VIEWPORT); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"), KEY_MASK_CMD + KEY_3), MENU_VIEW_USE_3_VIEWPORTS); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT); - p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KEY_MASK_CMD + KEY_4), MENU_VIEW_USE_4_VIEWPORTS); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KeyModifierMask::CMD + Key::KEY_1), MENU_VIEW_USE_1_VIEWPORT); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KeyModifierMask::CMD + Key::KEY_2), MENU_VIEW_USE_2_VIEWPORTS); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KeyModifierMask::ALT + KeyModifierMask::CMD + Key::KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"), KeyModifierMask::CMD + Key::KEY_3), MENU_VIEW_USE_3_VIEWPORTS); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KeyModifierMask::ALT + KeyModifierMask::CMD + Key::KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT); + p->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KeyModifierMask::CMD + Key::KEY_4), MENU_VIEW_USE_4_VIEWPORTS); p->add_separator(); p->add_submenu_item(TTR("Gizmos"), "GizmosMenu"); p->add_separator(); p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN); - p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid"), KEY_NUMBERSIGN), MENU_VIEW_GRID); + p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid"), Key::NUMBERSIGN), MENU_VIEW_GRID); p->add_separator(); p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings...")), MENU_VIEW_CAMERA_SETTINGS); @@ -7870,7 +7870,7 @@ bool Node3DEditor::is_gizmo_visible() const { double Node3DEditor::get_translate_snap() const { double snap_value; - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { snap_value = snap_translate->get_text().to_float() / 10.0; } else { snap_value = snap_translate->get_text().to_float(); @@ -7881,7 +7881,7 @@ double Node3DEditor::get_translate_snap() const { double Node3DEditor::get_rotate_snap() const { double snap_value; - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { snap_value = snap_rotate->get_text().to_float() / 3.0; } else { snap_value = snap_rotate->get_text().to_float(); @@ -7892,7 +7892,7 @@ double Node3DEditor::get_rotate_snap() const { double Node3DEditor::get_scale_snap() const { double snap_value; - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { snap_value = snap_scale->get_text().to_float() / 2.0; } else { snap_value = snap_scale->get_text().to_float(); diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp index fd42bce06e..c949621e28 100644 --- a/editor/plugins/ot_features_plugin.cpp +++ b/editor/plugins/ot_features_plugin.cpp @@ -185,12 +185,6 @@ bool EditorInspectorPluginOpenTypeFeatures::can_handle(Object *p_object) { return (Object::cast_to<Control>(p_object) != nullptr); } -void EditorInspectorPluginOpenTypeFeatures::parse_begin(Object *p_object) { -} - -void EditorInspectorPluginOpenTypeFeatures::parse_category(Object *p_object, const String &p_parse_category) { -} - bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { if (p_path == "opentype_features/_new") { OpenTypeFeaturesAdd *editor = memnew(OpenTypeFeaturesAdd); diff --git a/editor/plugins/ot_features_plugin.h b/editor/plugins/ot_features_plugin.h index dbafa3bbf6..add491ed48 100644 --- a/editor/plugins/ot_features_plugin.h +++ b/editor/plugins/ot_features_plugin.h @@ -86,8 +86,6 @@ class EditorInspectorPluginOpenTypeFeatures : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual void parse_begin(Object *p_object) override; - virtual void parse_category(Object *p_object, const String &p_parse_category) override; virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; }; diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 119ecddf63..79f8ce95cd 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -88,7 +88,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { real_t dist_to_p_in = gpoint.distance_to(xform.xform(curve->get_point_position(i) + curve->get_point_in(i))); // Check for point movement start (for point + in/out controls). - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mode == MODE_EDIT && !mb->is_shift_pressed() && dist_to_p < grab_threshold) { // Points can only be moved in edit mode. @@ -118,7 +118,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for point deletion. - if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && mode == MODE_DELETE)) { + if ((mb->get_button_index() == MouseButton::RIGHT && mode == MODE_EDIT) || (mb->get_button_index() == MouseButton::LEFT && mode == MODE_DELETE)) { if (dist_to_p < grab_threshold) { undo_redo->create_action(TTR("Remove Point from Curve")); undo_redo->add_do_method(curve.ptr(), "remove_point", i); @@ -149,7 +149,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for point creation. - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && ((mb->is_command_pressed() && mode == MODE_EDIT) || mode == MODE_CREATE)) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && ((mb->is_command_pressed() && mode == MODE_EDIT) || mode == MODE_CREATE)) { Ref<Curve2D> curve = node->get_curve(); undo_redo->create_action(TTR("Add Point to Curve")); @@ -170,7 +170,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for segment split. - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mode == MODE_EDIT && on_edge) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && mode == MODE_EDIT && on_edge) { Vector2 gpoint2 = mb->get_position(); Ref<Curve2D> curve = node->get_curve(); @@ -207,7 +207,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } // Check for point movement completion. - if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && action != ACTION_NONE) { + if (!mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && action != ACTION_NONE) { Ref<Curve2D> curve = node->get_curve(); Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from); @@ -537,7 +537,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CurveEdit"), SNAME("EditorIcons"))); curve_edit->set_toggle_mode(true); curve_edit->set_focus_mode(Control::FOCUS_NONE); - curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); + curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT)); base_hb->add_child(curve_edit); curve_edit_curve = memnew(Button); diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index f9a5f429d2..e83f6481f9 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -316,7 +316,7 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_spatial_gui_input(Camera set_handle_clicked(false); } - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->is_ctrl_pressed()))) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->is_ctrl_pressed()))) { //click into curve, break it down Vector<Vector3> v3a = c->tessellate(); int idx = 0; @@ -411,7 +411,7 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_spatial_gui_input(Camera //add new at pos } - } else if (mb->is_pressed() && ((mb->get_button_index() == MOUSE_BUTTON_LEFT && curve_del->is_pressed()) || (mb->get_button_index() == MOUSE_BUTTON_RIGHT && curve_edit->is_pressed()))) { + } else if (mb->is_pressed() && ((mb->get_button_index() == MouseButton::LEFT && curve_del->is_pressed()) || (mb->get_button_index() == MouseButton::RIGHT && curve_edit->is_pressed()))) { for (int i = 0; i < c->get_point_count(); i++) { real_t dist_to_p = p_camera->unproject_position(gt.xform(c->get_point_position(i))).distance_to(mbpos); real_t dist_to_p_out = p_camera->unproject_position(gt.xform(c->get_point_position(i) + c->get_point_out(i))).distance_to(mbpos); @@ -573,7 +573,7 @@ Path3DEditorPlugin::Path3DEditorPlugin(EditorNode *p_node) { curve_edit->set_toggle_mode(true); curve_edit->hide(); curve_edit->set_focus_mode(Control::FOCUS_NONE); - curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); + curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_edit); curve_create = memnew(Button); curve_create->set_flat(true); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 5afe9ed60c..6ffe99d4d0 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -447,7 +447,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { uv_drag_from = snap_point(mb->get_position()); uv_drag = true; @@ -759,7 +759,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { bone_painting = false; } } - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { + } else if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { _cancel_editing(); if (bone_painting) { @@ -768,9 +768,9 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_edit_draw->update(); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { + } else if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) { uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * mb->get_factor()))); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { + } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) { uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * mb->get_factor()))); } } @@ -778,7 +778,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseMotion> mm = p_input; if (mm.is_valid()) { - if ((mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + if ((mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE || Input::get_singleton()->is_key_pressed(Key::SPACE)) { Vector2 drag = mm->get_relative(); uv_hscroll->set_value(uv_hscroll->get_value() - drag.x); uv_vscroll->set_value(uv_vscroll->get_value() - drag.y); diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index ed91f174d1..0f3c50a861 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -271,11 +271,7 @@ EditorPropertyRootMotion::EditorPropertyRootMotion() { ////////////////////////// bool EditorInspectorRootMotionPlugin::can_handle(Object *p_object) { - return true; //can handle everything -} - -void EditorInspectorRootMotionPlugin::parse_begin(Object *p_object) { - //do none + return true; // Can handle everything. } bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { @@ -288,9 +284,5 @@ bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, const Var return true; } - return false; //can be overridden, although it will most likely be last anyway -} - -void EditorInspectorRootMotionPlugin::parse_end() { - //do none + return false; } diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h index 1484af62e8..c05975b6c3 100644 --- a/editor/plugins/root_motion_editor_plugin.h +++ b/editor/plugins/root_motion_editor_plugin.h @@ -64,9 +64,7 @@ class EditorInspectorRootMotionPlugin : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual void parse_begin(Object *p_object) override; virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; - virtual void parse_end() override; }; #endif // ROOT_MOTION_EDITOR_PLUGIN_H diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index aad378ecec..e87d31f018 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -46,7 +46,7 @@ #include "editor/find_in_files.h" #include "editor/node_dock.h" #include "editor/plugins/shader_editor_plugin.h" -#include "modules/visual_script/visual_script_editor.h" +#include "modules/visual_script/editor/visual_script_editor.h" #include "scene/main/window.h" #include "scene/scene_string_names.h" #include "script_text_editor.h" @@ -309,7 +309,7 @@ void ScriptEditorQuickOpen::_text_changed(const String &p_newtext) { void ScriptEditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) { Ref<InputEventKey> k = p_ie; - if (k.is_valid() && (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_PAGEUP || k->get_keycode() == KEY_PAGEDOWN)) { + if (k.is_valid() && (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::PAGEUP || k->get_keycode() == Key::PAGEDOWN)) { search_options->gui_input(k); search_box->accept_event(); } @@ -989,10 +989,6 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource> &p_res) { RES script = se->get_edited_resource(); - if (script->is_built_in()) { - continue; //internal script, who cares - } - if (script == p_res) { se->tag_saved_version(); } @@ -1002,6 +998,31 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource> &p_res) { _trigger_live_script_reload(); } +void ScriptEditor::_scene_saved_callback(const String &p_path) { + // If scene was saved, mark all built-in scripts from that scene as saved. + for (int i = 0; i < tab_container->get_child_count(); i++) { + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i)); + if (!se) { + continue; + } + + RES edited_res = se->get_edited_resource(); + + if (!edited_res->is_built_in()) { + continue; // External script, who cares. + } + + if (edited_res->get_path().get_slice("::", 0) == p_path) { + se->tag_saved_version(); + } + + Ref<Script> scr = edited_res; + if (scr.is_valid() && scr->is_tool()) { + scr->reload(true); + } + } +} + void ScriptEditor::_trigger_live_script_reload() { if (!pending_auto_reload && auto_reload_running_scripts) { call_deferred(SNAME("_live_auto_reload_running_scripts")); @@ -1525,6 +1546,7 @@ void ScriptEditor::_notification(int p_what) { editor->connect("stop_pressed", callable_mp(this, &ScriptEditor::_editor_stop)); editor->connect("script_add_function_request", callable_mp(this, &ScriptEditor::_add_callback)); editor->connect("resource_saved", callable_mp(this, &ScriptEditor::_res_saved_callback)); + editor->connect("scene_saved", callable_mp(this, &ScriptEditor::_scene_saved_callback)); editor->get_filesystem_dock()->connect("files_moved", callable_mp(this, &ScriptEditor::_files_moved)); editor->get_filesystem_dock()->connect("file_removed", callable_mp(this, &ScriptEditor::_file_removed)); script_list->connect("item_selected", callable_mp(this, &ScriptEditor::_script_selected)); @@ -1619,7 +1641,7 @@ void ScriptEditor::close_builtin_scripts_from_scene(const String &p_scene) { } if (script->is_built_in() && script->get_path().begins_with(p_scene)) { //is an internal script and belongs to scene being closed - _close_tab(i); + _close_tab(i, false); i--; } } @@ -1702,7 +1724,7 @@ void ScriptEditor::_help_overview_selected(int p_idx) { } void ScriptEditor::_script_selected(int p_idx) { - grab_focus_block = !Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT); //amazing hack, simply amazing + grab_focus_block = !Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT); //amazing hack, simply amazing _go_to_tab(script_list->get_item_metadata(p_idx)); grab_focus_block = false; @@ -1926,20 +1948,7 @@ void ScriptEditor::_update_script_names() { // to update original path to previously edited resource. se->set_meta("_edit_res_path", path); } - bool built_in = !path.is_resource_file(); - String name; - - if (built_in) { - name = path.get_file(); - const String &resource_name = se->get_edited_resource()->get_name(); - if (resource_name != "") { - // If the built-in script has a custom resource name defined, - // display the built-in script name as follows: `ResourceName (scene_file.tscn)` - name = vformat("%s (%s)", resource_name, name.substr(0, name.find("::", 0))); - } - } else { - name = se->get_name(); - } + String name = se->get_name(); _ScriptEditorItemData sd; sd.icon = icon; @@ -2403,7 +2412,17 @@ void ScriptEditor::save_current_script() { } } - editor->save_resource(resource); + if (resource->is_built_in()) { + // If built-in script, save the scene instead. + const String scene_path = resource->get_path().get_slice("::", 0); + if (!scene_path.is_empty()) { + Vector<String> scene_to_save; + scene_to_save.push_back(scene_path); + editor->save_scene_list(scene_to_save); + } + } else { + editor->save_resource(resource); + } if (script != nullptr) { const Vector<DocData::ClassDoc> &documentations = script->get_documentation(); @@ -2416,6 +2435,8 @@ void ScriptEditor::save_current_script() { } void ScriptEditor::save_all_scripts() { + Vector<String> scenes_to_save; + for (int i = 0; i < tab_container->get_child_count(); i++) { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i)); if (!se) { @@ -2474,9 +2495,19 @@ void ScriptEditor::save_all_scripts() { update_doc(doc.name); } } + } else { + // For built-in scripts, save their scenes instead. + const String scene_path = edited_res->get_path().get_slice("::", 0); + if (!scenes_to_save.has(scene_path)) { + scenes_to_save.push_back(scene_path); + } } } + if (!scenes_to_save.is_empty()) { + editor->save_scene_list(scenes_to_save); + } + _update_script_names(); EditorFileSystem::get_singleton()->update_script_classes(); } @@ -2920,11 +2951,11 @@ void ScriptEditor::input(const Ref<InputEvent> &p_event) { // This must be hardcoded as the editor shortcuts dialog doesn't allow assigning // more than one shortcut per action. if (mb.is_valid() && mb->is_pressed() && is_visible_in_tree()) { - if (mb->get_button_index() == MOUSE_BUTTON_XBUTTON1) { + if (mb->get_button_index() == MouseButton::MB_XBUTTON1) { _history_back(); } - if (mb->get_button_index() == MOUSE_BUTTON_XBUTTON2) { + if (mb->get_button_index() == MouseButton::MB_XBUTTON2) { _history_forward(); } } @@ -2965,7 +2996,7 @@ void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventMouseButton> mb = ev; if (mb.is_valid() && mb->is_pressed()) { switch (mb->get_button_index()) { - case MOUSE_BUTTON_MIDDLE: { + case MouseButton::MIDDLE: { // Right-click selects automatically; middle-click does not. int idx = script_list->get_item_at_position(mb->get_position(), true); if (idx >= 0) { @@ -2975,7 +3006,7 @@ void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) { } } break; - case MOUSE_BUTTON_RIGHT: { + case MouseButton::RIGHT: { _make_script_list_context_menu(); } break; default: @@ -3245,15 +3276,15 @@ void ScriptEditor::_update_selected_editor_menu() { EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_current_tab_control()); script_search_menu->get_popup()->clear(); if (eh) { - script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F), HELP_SEARCH_FIND); - script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), HELP_SEARCH_FIND_NEXT); - script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3), HELP_SEARCH_FIND_PREVIOUS); + script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find..."), KeyModifierMask::CMD | Key::F), HELP_SEARCH_FIND); + script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), Key::F3), HELP_SEARCH_FIND_NEXT); + script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KeyModifierMask::SHIFT | Key::F3), HELP_SEARCH_FIND_PREVIOUS); script_search_menu->get_popup()->add_separator(); - script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F), SEARCH_IN_FILES); + script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F), SEARCH_IN_FILES); script_search_menu->show(); } else { if (tab_container->get_child_count() == 0) { - script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F), SEARCH_IN_FILES); + script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_in_files", TTR("Find in Files"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F), SEARCH_IN_FILES); script_search_menu->show(); } else { script_search_menu->hide(); @@ -3434,6 +3465,9 @@ void ScriptEditor::_on_find_in_files_result_selected(String fpath, int line_numb shader_editor->make_visible(true); shader_editor->get_shader_editor()->goto_line_selection(line_number - 1, begin, end); return; + } else if (fpath.get_extension() == "tscn") { + editor->load_scene(fpath); + return; } else { Ref<Script> script = res; if (script.is_valid()) { @@ -3634,11 +3668,11 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { find_replace_bar->hide(); ED_SHORTCUT("script_editor/window_sort", TTR("Sort")); - ED_SHORTCUT("script_editor/window_move_up", TTR("Move Up"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_UP); - ED_SHORTCUT("script_editor/window_move_down", TTR("Move Down"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_DOWN); - // FIXME: These should be `KEY_GREATER` and `KEY_LESS` but those don't work. - ED_SHORTCUT("script_editor/next_script", TTR("Next Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_PERIOD); - ED_SHORTCUT("script_editor/prev_script", TTR("Previous Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_COMMA); + ED_SHORTCUT("script_editor/window_move_up", TTR("Move Up"), KeyModifierMask::SHIFT | KeyModifierMask::ALT | Key::UP); + ED_SHORTCUT("script_editor/window_move_down", TTR("Move Down"), KeyModifierMask::SHIFT | KeyModifierMask::ALT | Key::DOWN); + // FIXME: These should be `Key::GREATER` and `Key::LESS` but those don't work. + ED_SHORTCUT("script_editor/next_script", TTR("Next Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::PERIOD); + ED_SHORTCUT("script_editor/prev_script", TTR("Previous Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::COMMA); set_process_input(true); set_process_unhandled_input(true); @@ -3651,7 +3685,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script...")), FILE_NEW); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New Text File...")), FILE_NEW_TEXTFILE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open...")), FILE_OPEN); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_T), FILE_REOPEN_CLOSED); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::T), FILE_REOPEN_CLOSED); file_menu->get_popup()->add_submenu_item(TTR("Open Recent"), "RecentScripts", FILE_OPEN_RECENT); recent_scripts = memnew(PopupMenu); @@ -3661,17 +3695,17 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { _update_recent_scripts(); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KEY_MASK_ALT | KEY_MASK_CMD | KEY_S), FILE_SAVE); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KeyModifierMask::ALT | KeyModifierMask::CMD | Key::S), FILE_SAVE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As...")), FILE_SAVE_AS); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_S), FILE_SAVE_ALL); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KeyModifierMask::SHIFT | KeyModifierMask::ALT | Key::S), FILE_SAVE_ALL); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_R), FILE_TOOL_RELOAD_SOFT); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KeyModifierMask::CMD | KeyModifierMask::ALT | Key::R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show in FileSystem")), SHOW_IN_FILE_SYSTEM); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Previous"), KEY_MASK_ALT | KEY_LEFT), WINDOW_PREV); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_next", TTR("History Next"), KEY_MASK_ALT | KEY_RIGHT), WINDOW_NEXT); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Previous"), KeyModifierMask::ALT | Key::LEFT), WINDOW_PREV); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_next", TTR("History Next"), KeyModifierMask::ALT | Key::RIGHT), WINDOW_NEXT); file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_submenu_item(TTR("Theme"), "Theme", FILE_THEME); @@ -3688,16 +3722,16 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/save_theme_as", TTR("Save Theme As...")), THEME_SAVE_AS); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_file", TTR("Close"), KEY_MASK_CMD | KEY_W), FILE_CLOSE); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_file", TTR("Close"), KeyModifierMask::CMD | Key::W), FILE_CLOSE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_all", TTR("Close All")), CLOSE_ALL); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_other_tabs", TTR("Close Other Tabs")), CLOSE_OTHER_TABS); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_docs", TTR("Close Docs")), CLOSE_DOCS); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/run_file", TTR("Run"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_X), FILE_RUN); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/run_file", TTR("Run"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::X), FILE_RUN); file_menu->get_popup()->add_separator(); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/toggle_scripts_panel", TTR("Toggle Scripts Panel"), KEY_MASK_CMD | KEY_BACKSLASH), TOGGLE_SCRIPTS_PANEL); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/toggle_scripts_panel", TTR("Toggle Scripts Panel"), KeyModifierMask::CMD | Key::BACKSLASH), TOGGLE_SCRIPTS_PANEL); file_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptEditor::_menu_option)); script_search_menu = memnew(MenuButton); @@ -3950,7 +3984,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) { EDITOR_DEF("text_editor/external/exec_flags", "{file}"); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "text_editor/external/exec_flags", PROPERTY_HINT_PLACEHOLDER_TEXT, "Call flags with placeholders: {project}, {file}, {col}, {line}.")); - ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_T); + ED_SHORTCUT("script_editor/reopen_closed_script", TTR("Reopen Closed Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::T); ED_SHORTCUT("script_editor/clear_recent", TTR("Clear Recent Scripts")); } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 2b0bdfd109..0adeca031e 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -365,6 +365,7 @@ class ScriptEditor : public PanelContainer { void _add_callback(Object *p_obj, const String &p_function, const PackedStringArray &p_args); void _res_saved_callback(const Ref<Resource> &p_res); + void _scene_saved_callback(const String &p_path); bool open_textfile_after_create = true; bool trim_trailing_whitespace_on_save; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 24cdc06d78..93adced59d 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -375,18 +375,21 @@ void ScriptTextEditor::ensure_focus() { String ScriptTextEditor::get_name() { String name; - if (!script->is_built_in()) { - name = script->get_path().get_file(); - if (is_unsaved()) { - if (script->get_path().is_empty()) { - name = TTR("[unsaved]"); - } - name += "(*)"; + name = script->get_path().get_file(); + if (name.is_empty()) { + // This appears for newly created built-in scripts before saving the scene. + name = TTR("[unsaved]"); + } else if (script->is_built_in()) { + const String &script_name = script->get_name(); + if (script_name != "") { + // If the built-in script has a custom resource name defined, + // display the built-in script name as follows: `ResourceName (scene_file.tscn)` + name = vformat("%s (%s)", script_name, name.get_slice("::", 0)); } - } else if (script->get_name() != "") { - name = script->get_name(); - } else { - name = script->get_class() + "(" + itos(script->get_instance_id()) + ")"; + } + + if (is_unsaved()) { + name += "(*)"; } return name; @@ -1459,7 +1462,7 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data Array files = d["files"]; String text_to_drop; - bool preload = Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool preload = Input::get_singleton()->is_key_pressed(Key::CTRL); for (int i = 0; i < files.size(); i++) { if (i > 0) { text_to_drop += ", "; @@ -1523,7 +1526,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { bool create_menu = false; CodeEdit *tx = code_editor->get_text_editor(); - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { local_pos = mb->get_global_position() - tx->get_global_position(); create_menu = true; } else if (k.is_valid() && k->is_action("ui_menu", true)) { @@ -1626,10 +1629,7 @@ void ScriptTextEditor::_color_changed(const Color &p_color) { } String line = code_editor->get_text_editor()->get_line(color_position.x); - int color_args_pos = line.find(color_args, color_position.y); - String line_with_replaced_args = line; - line_with_replaced_args.erase(color_args_pos, color_args.length()); - line_with_replaced_args = line_with_replaced_args.insert(color_args_pos, new_args); + String line_with_replaced_args = line.replace(color_args, new_args); color_args = new_args; code_editor->get_text_editor()->begin_complex_operation(); @@ -1804,9 +1804,9 @@ void ScriptTextEditor::_enable_code_editor() { edit_menu->get_popup()->add_child(convert_case); edit_menu->get_popup()->add_submenu_item(TTR("Convert Case"), "convert_case"); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Uppercase"), KEY_MASK_SHIFT | KEY_F4), EDIT_TO_UPPERCASE); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Lowercase"), KEY_MASK_SHIFT | KEY_F5), EDIT_TO_LOWERCASE); - convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F6), EDIT_CAPITALIZE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_uppercase", TTR("Uppercase"), KeyModifierMask::SHIFT | Key::F4), EDIT_TO_UPPERCASE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/convert_to_lowercase", TTR("Lowercase"), KeyModifierMask::SHIFT | Key::F5), EDIT_TO_LOWERCASE); + convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KeyModifierMask::SHIFT | Key::F6), EDIT_CAPITALIZE); convert_case->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option)); edit_menu->get_popup()->add_child(highlighter_menu); @@ -1953,60 +1953,60 @@ static ScriptEditorBase *create_editor(const RES &p_resource) { } void ScriptTextEditor::register_editor() { - ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KEY_MASK_ALT | KEY_UP); - ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT | KEY_DOWN); - ED_SHORTCUT("script_text_editor/delete_line", TTR("Delete Line"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_K); + ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KeyModifierMask::ALT | Key::UP); + ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KeyModifierMask::ALT | Key::DOWN); + ED_SHORTCUT("script_text_editor/delete_line", TTR("Delete Line"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::K); // Leave these at zero, same can be accomplished with tab/shift-tab, including selection. // The next/previous in history shortcut in this case makes a lot more sense. - ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), KEY_NONE); - ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), KEY_NONE); - ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD | KEY_K); - ED_SHORTCUT("script_text_editor/toggle_fold_line", TTR("Fold/Unfold Line"), KEY_MASK_ALT | KEY_F); - ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), KEY_NONE); - ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), KEY_NONE); - ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D); - ED_SHORTCUT_OVERRIDE("script_text_editor/duplicate_selection", "macos", KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C); - ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_E); - ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T); - ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent to Spaces"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Y); - ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_I); - ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD | KEY_I); + ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), Key::NONE); + ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), Key::NONE); + ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KeyModifierMask::CMD | Key::K); + ED_SHORTCUT("script_text_editor/toggle_fold_line", TTR("Fold/Unfold Line"), KeyModifierMask::ALT | Key::F); + ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), Key::NONE); + ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), Key::NONE); + ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::D); + ED_SHORTCUT_OVERRIDE("script_text_editor/duplicate_selection", "macos", KeyModifierMask::SHIFT | KeyModifierMask::CMD | Key::C); + ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::E); + ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KeyModifierMask::CMD | KeyModifierMask::ALT | Key::T); + ED_SHORTCUT("script_text_editor/convert_indent_to_spaces", TTR("Convert Indent to Spaces"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::Y); + ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::I); + ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KeyModifierMask::CMD | Key::I); - ED_SHORTCUT_AND_COMMAND("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F); + ED_SHORTCUT_AND_COMMAND("script_text_editor/find", TTR("Find..."), KeyModifierMask::CMD | Key::F); - ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_F3); - ED_SHORTCUT_OVERRIDE("script_text_editor/find_next", "macos", KEY_MASK_CMD | KEY_G); + ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), Key::F3); + ED_SHORTCUT_OVERRIDE("script_text_editor/find_next", "macos", KeyModifierMask::CMD | Key::G); - ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3); - ED_SHORTCUT_OVERRIDE("script_text_editor/find_previous", "macos", KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G); + ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KeyModifierMask::SHIFT | Key::F3); + ED_SHORTCUT_OVERRIDE("script_text_editor/find_previous", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G); - ED_SHORTCUT_AND_COMMAND("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R); - ED_SHORTCUT_OVERRIDE("script_text_editor/replace", "macos", KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); + ED_SHORTCUT_AND_COMMAND("script_text_editor/replace", TTR("Replace..."), KeyModifierMask::CMD | Key::R); + ED_SHORTCUT_OVERRIDE("script_text_editor/replace", "macos", KeyModifierMask::ALT | KeyModifierMask::CMD | Key::F); - ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F); - ED_SHORTCUT("script_text_editor/replace_in_files", TTR("Replace in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R); + ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F); + ED_SHORTCUT("script_text_editor/replace_in_files", TTR("Replace in Files..."), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R); - ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_ALT | KEY_F1); - ED_SHORTCUT_OVERRIDE("script_text_editor/contextual_help", "macos", KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE); + ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KeyModifierMask::ALT | Key::F1); + ED_SHORTCUT_OVERRIDE("script_text_editor/contextual_help", "macos", KeyModifierMask::ALT | KeyModifierMask::SHIFT | Key::SPACE); - ED_SHORTCUT("script_text_editor/toggle_bookmark", TTR("Toggle Bookmark"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_B); - ED_SHORTCUT("script_text_editor/goto_next_bookmark", TTR("Go to Next Bookmark"), KEY_MASK_CMD | KEY_B); - ED_SHORTCUT("script_text_editor/goto_previous_bookmark", TTR("Go to Previous Bookmark"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B); - ED_SHORTCUT("script_text_editor/remove_all_bookmarks", TTR("Remove All Bookmarks"), KEY_NONE); + ED_SHORTCUT("script_text_editor/toggle_bookmark", TTR("Toggle Bookmark"), KeyModifierMask::CMD | KeyModifierMask::ALT | Key::B); + ED_SHORTCUT("script_text_editor/goto_next_bookmark", TTR("Go to Next Bookmark"), KeyModifierMask::CMD | Key::B); + ED_SHORTCUT("script_text_editor/goto_previous_bookmark", TTR("Go to Previous Bookmark"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::B); + ED_SHORTCUT("script_text_editor/remove_all_bookmarks", TTR("Remove All Bookmarks"), Key::NONE); - ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); - ED_SHORTCUT_OVERRIDE("script_text_editor/goto_function", "macos", KEY_MASK_CTRL | KEY_MASK_CMD | KEY_J); + ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KeyModifierMask::ALT | KeyModifierMask::CMD | Key::F); + ED_SHORTCUT_OVERRIDE("script_text_editor/goto_function", "macos", KeyModifierMask::CTRL | KeyModifierMask::CMD | Key::J); - ED_SHORTCUT("script_text_editor/goto_line", TTR("Go to Line..."), KEY_MASK_CMD | KEY_L); + ED_SHORTCUT("script_text_editor/goto_line", TTR("Go to Line..."), KeyModifierMask::CMD | Key::L); - ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9); - ED_SHORTCUT_OVERRIDE("script_text_editor/toggle_breakpoint", "macos", KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B); + ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), Key::F9); + ED_SHORTCUT_OVERRIDE("script_text_editor/toggle_breakpoint", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::B); - ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F9); - ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Go to Next Breakpoint"), KEY_MASK_CMD | KEY_PERIOD); - ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Go to Previous Breakpoint"), KEY_MASK_CMD | KEY_COMMA); + ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F9); + ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Go to Next Breakpoint"), KeyModifierMask::CMD | Key::PERIOD); + ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Go to Previous Breakpoint"), KeyModifierMask::CMD | Key::COMMA); ScriptEditor::register_create_script_editor_function(create_editor); } diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 9d2b4c88c5..6032267717 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -34,6 +34,7 @@ #include "core/io/resource_saver.h" #include "core/os/keyboard.h" #include "core/os/os.h" +#include "core/version_generated.gen.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -142,10 +143,10 @@ void ShaderTextEditor::_load_theme_settings() { } } - const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); + const Color user_type_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color"); for (const String &E : built_ins) { - syntax_highlighter->add_keyword_color(E, member_variable_color); + syntax_highlighter->add_keyword_color(E, user_type_color); } // Colorize comments. @@ -384,7 +385,7 @@ void ShaderEditor::_menu_option(int p_option) { shader_editor->remove_all_bookmarks(); } break; case HELP_DOCS: { - OS::get_singleton()->shell_open("https://docs.godotengine.org/en/latest/tutorials/shaders/shader_reference/index.html"); + OS::get_singleton()->shell_open(vformat("%s/tutorials/shaders/shader_reference/index.html", VERSION_DOCS_URL)); } break; } if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) { @@ -552,7 +553,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventMouseButton> mb = ev; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { CodeEdit *tx = shader_editor->get_text_editor(); Point2i pos = tx->get_line_column_at_pos(mb->get_global_position() - tx->get_global_position()); diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp index c350004f0f..510e264c48 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.cpp +++ b/editor/plugins/skeleton_2d_editor_plugin.cpp @@ -52,34 +52,34 @@ void Skeleton2DEditor::_menu_option(int p_option) { } switch (p_option) { - case MENU_OPTION_MAKE_REST: { + case MENU_OPTION_SET_REST: { if (node->get_bone_count() == 0) { err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes.")); err_dialog->popup_centered(); return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Create Rest Pose from Bones")); + ur->create_action(TTR("Set Rest Pose to Bones")); for (int i = 0; i < node->get_bone_count(); i++) { Bone2D *bone = node->get_bone(i); - ur->add_do_method(bone, "set_rest", bone->get_transform()); - ur->add_undo_method(bone, "set_rest", bone->get_rest()); + ur->add_do_method(bone, "set_transform", bone->get_rest()); + ur->add_undo_method(bone, "set_transform", bone->get_transform()); } ur->commit_action(); } break; - case MENU_OPTION_SET_REST: { + case MENU_OPTION_MAKE_REST: { if (node->get_bone_count() == 0) { err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes.")); err_dialog->popup_centered(); return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Set Rest Pose to Bones")); + ur->create_action(TTR("Create Rest Pose from Bones")); for (int i = 0; i < node->get_bone_count(); i++) { Bone2D *bone = node->get_bone(i); - ur->add_do_method(bone, "set_transform", bone->get_rest()); - ur->add_undo_method(bone, "set_transform", bone->get_transform()); + ur->add_do_method(bone, "set_rest", bone->get_transform()); + ur->add_undo_method(bone, "set_rest", bone->get_rest()); } ur->commit_action(); @@ -98,10 +98,10 @@ Skeleton2DEditor::Skeleton2DEditor() { options->set_text(TTR("Skeleton2D")); options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton2D"), SNAME("EditorIcons"))); - options->get_popup()->add_item(TTR("Reset to Rest Pose"), MENU_OPTION_MAKE_REST); + options->get_popup()->add_item(TTR("Reset to Rest Pose"), MENU_OPTION_SET_REST); options->get_popup()->add_separator(); // Use the "Overwrite" word to highlight that this is a destructive operation. - options->get_popup()->add_item(TTR("Overwrite Rest Pose"), MENU_OPTION_SET_REST); + options->get_popup()->add_item(TTR("Overwrite Rest Pose"), MENU_OPTION_MAKE_REST); options->set_switch_on_hover(true); options->get_popup()->connect("id_pressed", callable_mp(this, &Skeleton2DEditor::_menu_option)); diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h index dacd8fe43f..066888f685 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.h +++ b/editor/plugins/skeleton_2d_editor_plugin.h @@ -40,8 +40,8 @@ class Skeleton2DEditor : public Control { GDCLASS(Skeleton2DEditor, Control); enum Menu { - MENU_OPTION_MAKE_REST, MENU_OPTION_SET_REST, + MENU_OPTION_MAKE_REST, }; Skeleton2D *node; diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 0b8a56503c..5f21c8c881 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -681,7 +681,7 @@ void Skeleton3DEditor::create_editors() { key_insert_button->set_focus_mode(FOCUS_NONE); key_insert_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(false)); key_insert_button->set_tooltip(TTR("Insert key of bone poses already exist track.")); - key_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTR("Insert Key (Existing Tracks)"), KEY_INSERT)); + key_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTR("Insert Key (Existing Tracks)"), Key::INSERT)); animation_hb->add_child(key_insert_button); key_insert_all_button = memnew(Button); @@ -689,7 +689,7 @@ void Skeleton3DEditor::create_editors() { key_insert_all_button->set_focus_mode(FOCUS_NONE); key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(true)); key_insert_all_button->set_tooltip(TTR("Insert key of all bone poses.")); - key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KEY_MASK_CMD + KEY_INSERT)); + key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KeyModifierMask::CMD + Key::INSERT)); animation_hb->add_child(key_insert_all_button); // Bone tree. @@ -1028,7 +1028,7 @@ EditorPlugin::AfterGUIInput Skeleton3DEditorPlugin::forward_spatial_gui_input(Ca Node3DEditor *ne = Node3DEditor::get_singleton(); if (se->is_edit_mode()) { const Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (ne->get_tool_mode() != Node3DEditor::TOOL_MODE_SELECT) { if (!ne->is_gizmo_visible()) { return EditorPlugin::AFTER_GUI_INPUT_STOP; diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 8a8d80891a..d455f4618b 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -126,7 +126,7 @@ void SpriteFramesEditor::_sheet_preview_draw() { void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { const Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { const int idx = _sheet_preview_position_to_frame_index(mb->get_position()); if (idx != -1) { @@ -166,12 +166,12 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { frames_toggled_by_mouse_hover.clear(); } const Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { // Select by holding down the mouse button on frames. const int idx = _sheet_preview_position_to_frame_index(mm->get_position()); @@ -200,11 +200,11 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) { // Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer // to allow performing this action anywhere, even if the cursor isn't // hovering the texture in the workspace. - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) { _sheet_zoom_in(); // Don't scroll up after zooming in. accept_event(); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) { + } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) { _sheet_zoom_out(); // Don't scroll down after zooming out. accept_event(); @@ -746,11 +746,11 @@ void SpriteFramesEditor::_tree_input(const Ref<InputEvent> &p_event) { const Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed() && mb->is_ctrl_pressed()) { _zoom_in(); // Don't scroll up after zooming in. accept_event(); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) { + } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed() && mb->is_ctrl_pressed()) { _zoom_out(); // Don't scroll down after zooming out. accept_event(); @@ -1006,7 +1006,7 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da if (String(d["type"]) == "files") { Vector<String> files = d["files"]; - if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { _prepare_sprite_sheet(files[0]); } else { _file_load_request(files, at_pos); diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp index 91c5e96f08..1c7f319280 100644 --- a/editor/plugins/style_box_editor_plugin.cpp +++ b/editor/plugins/style_box_editor_plugin.cpp @@ -44,13 +44,6 @@ void EditorInspectorPluginStyleBox::parse_begin(Object *p_object) { add_custom_control(preview); } -bool EditorInspectorPluginStyleBox::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, bool p_wide) { - return false; //do not want -} - -void EditorInspectorPluginStyleBox::parse_end() { -} - void StyleBoxPreview::edit(const Ref<StyleBox> &p_stylebox) { if (stylebox.is_valid()) { stylebox->disconnect("changed", callable_mp(this, &StyleBoxPreview::_sb_changed)); diff --git a/editor/plugins/style_box_editor_plugin.h b/editor/plugins/style_box_editor_plugin.h index 8ca348bd80..d82e5ab05e 100644 --- a/editor/plugins/style_box_editor_plugin.h +++ b/editor/plugins/style_box_editor_plugin.h @@ -61,8 +61,6 @@ class EditorInspectorPluginStyleBox : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; virtual void parse_begin(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; - virtual void parse_end() override; }; class StyleBoxEditorPlugin : public EditorPlugin { diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 3b45f32927..ebfe6c9ee3 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -65,18 +65,21 @@ void TextEditor::_load_theme_settings() { String TextEditor::get_name() { String name; - if (!text_file->is_built_in()) { - name = text_file->get_path().get_file(); - if (is_unsaved()) { - if (text_file->get_path().is_empty()) { - name = TTR("[unsaved]"); - } - name += "(*)"; + name = text_file->get_path().get_file(); + if (name.is_empty()) { + // This appears for newly created built-in text_files before saving the scene. + name = TTR("[unsaved]"); + } else if (text_file->is_built_in()) { + const String &text_file_name = text_file->get_name(); + if (text_file_name != "") { + // If the built-in text_file has a custom resource name defined, + // display the built-in text_file name as follows: `ResourceName (scene_file.tscn)` + name = vformat("%s (%s)", text_file_name, name.get_slice("::", 0)); } - } else if (text_file->get_name() != "") { - name = text_file->get_name(); - } else { - name = text_file->get_class() + "(" + itos(text_file->get_instance_id()) + ")"; + } + + if (is_unsaved()) { + name += "(*)"; } return name; @@ -422,7 +425,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventMouseButton> mb = ev; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->get_button_index() == MouseButton::RIGHT) { CodeEdit *tx = code_editor->get_text_editor(); Point2i pos = tx->get_line_column_at_pos(mb->get_global_position() - tx->get_global_position()); diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp index ee62138d12..1f536d13cf 100644 --- a/editor/plugins/texture_layered_editor_plugin.cpp +++ b/editor/plugins/texture_layered_editor_plugin.cpp @@ -38,7 +38,7 @@ void TextureLayeredEditor::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { y_rot += -mm->get_relative().x * 0.01; x_rot += mm->get_relative().y * 0.01; _update_material(); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index ce90d61616..8e1c81a876 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -284,7 +284,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (node_ninepatch || obj_styleBox.is_valid()) { edited_margin = -1; @@ -330,7 +330,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { for (const Rect2 &E : autoslice_cache) { if (E.has_point(point)) { rect = E; - if (Input::get_singleton()->is_key_pressed(KEY_CTRL) && !(Input::get_singleton()->is_key_pressed(Key(KEY_SHIFT | KEY_ALT)))) { + if (Input::get_singleton()->is_key_pressed(Key::CTRL) && !(Input::get_singleton()->is_key_pressed(Key(Key::SHIFT | Key::ALT)))) { Rect2 r; if (atlas_tex.is_valid()) { r = atlas_tex->get_region(); @@ -446,7 +446,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { creating = false; } - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { + } else if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { if (drag) { drag = false; if (edited_margin >= 0) { @@ -465,9 +465,9 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { drag_index = -1; } } - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { + } else if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) { _zoom_on_position(draw_zoom * ((0.95 + (0.05 * mb->get_factor())) / 0.95), mb->get_position()); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { + } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) { _zoom_on_position(draw_zoom * (1 - (0.05 * mb->get_factor())), mb->get_position()); } } @@ -475,7 +475,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseMotion> mm = p_input; if (mm.is_valid()) { - if (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + if ((mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE || Input::get_singleton()->is_key_pressed(Key::SPACE)) { Vector2 dragged(mm->get_relative().x / draw_zoom, mm->get_relative().y / draw_zoom); hscroll->set_value(hscroll->get_value() - dragged.x); vscroll->set_value(vscroll->get_value() - dragged.y); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index b1ef85b4f4..f94439f344 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -1711,13 +1711,13 @@ void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref<InputEvent> &p_ } switch (k->get_keycode()) { - case KEY_KP_ENTER: - case KEY_ENTER: { + case Key::KP_ENTER: + case Key::ENTER: { _confirm_edit_theme_item(); edit_theme_item_dialog->hide(); edit_theme_item_dialog->set_input_as_handled(); } break; - case KEY_ESCAPE: { + case Key::ESCAPE: { edit_theme_item_dialog->hide(); edit_theme_item_dialog->set_input_as_handled(); } break; diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp index e13a10fe3f..df0b35908b 100644 --- a/editor/plugins/theme_editor_preview.cpp +++ b/editor/plugins/theme_editor_preview.cpp @@ -144,7 +144,7 @@ void ThemeEditorPreview::_gui_input_picker_overlay(const Ref<InputEvent> &p_even Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (hovered_control) { StringName theme_type = hovered_control->get_theme_type_variation(); if (theme_type == StringName()) { diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index c064073b77..604143ef93 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -46,7 +46,7 @@ void TileAtlasView::gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid()) { drag_type = DRAG_TYPE_NONE; - Vector2i scroll_vec = Vector2((mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT) - (mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT), (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) - (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN)); + Vector2i scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_LEFT) - (mb->get_button_index() == MouseButton::WHEEL_RIGHT), (mb->get_button_index() == MouseButton::WHEEL_UP) - (mb->get_button_index() == MouseButton::WHEEL_DOWN)); if (scroll_vec != Vector2()) { if (mb->is_ctrl_pressed()) { if (mb->is_shift_pressed()) { @@ -69,7 +69,7 @@ void TileAtlasView::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE || mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->get_button_index() == MouseButton::MIDDLE || mb->get_button_index() == MouseButton::RIGHT) { if (mb->is_pressed()) { drag_type = DRAG_TYPE_PAN; } else { diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index e9d80bb4b8..d165f44334 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -125,7 +125,14 @@ void GenericTilePolygonEditor::_base_control_draw() { Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color"); const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorPathSharpHandle"), SNAME("EditorIcons")); const Ref<Texture2D> add_handle = get_theme_icon(SNAME("EditorHandleAdd"), SNAME("EditorIcons")); + const Ref<StyleBox> focus_stylebox = get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles")); + // Draw the focus rectangle. + if (base_control->has_focus()) { + base_control->draw_style_box(focus_stylebox, Rect2(Vector2(), base_control->get_size())); + } + + // Draw tile-related things. Size2 tile_size = tile_set->get_tile_size(); Transform2D xform; @@ -240,9 +247,10 @@ void GenericTilePolygonEditor::_zoom_changed() { } void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { + UndoRedo *undo_redo = use_undo_redo ? editor_undo_redo : memnew(UndoRedo); switch (p_item_pressed) { case RESET_TO_DEFAULT_TILE: { - undo_redo->create_action(TTR("Edit Polygons")); + undo_redo->create_action(TTR("Reset Polygons")); undo_redo->add_do_method(this, "clear_polygons"); Vector<Vector2> polygon = tile_set->get_tile_shape_polygon(); for (int i = 0; i < polygon.size(); i++) { @@ -260,7 +268,7 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { undo_redo->commit_action(true); } break; case CLEAR_TILE: { - undo_redo->create_action(TTR("Edit Polygons")); + undo_redo->create_action(TTR("Clear Polygons")); undo_redo->add_do_method(this, "clear_polygons"); undo_redo->add_do_method(base_control, "update"); undo_redo->add_do_method(this, "emit_signal", "polygons_changed"); @@ -272,9 +280,50 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { undo_redo->add_undo_method(this, "emit_signal", "polygons_changed"); undo_redo->commit_action(true); } break; + case ROTATE_RIGHT: + case ROTATE_LEFT: + case FLIP_HORIZONTALLY: + case FLIP_VERTICALLY: { + undo_redo->create_action(TTR("Rotate Polygons Left")); + for (unsigned int i = 0; i < polygons.size(); i++) { + Vector<Point2> new_polygon; + for (int point_index = 0; point_index < polygons[i].size(); point_index++) { + Vector2 point = polygons[i][point_index]; + switch (p_item_pressed) { + case ROTATE_RIGHT: { + point = Vector2(-point.y, point.x); + } break; + case ROTATE_LEFT: { + point = Vector2(point.y, -point.x); + } break; + case FLIP_HORIZONTALLY: { + point = Vector2(-point.x, point.y); + } break; + case FLIP_VERTICALLY: { + point = Vector2(point.x, -point.y); + } break; + default: + break; + } + new_polygon.push_back(point); + } + undo_redo->add_do_method(this, "set_polygon", i, new_polygon); + } + undo_redo->add_do_method(base_control, "update"); + undo_redo->add_do_method(this, "emit_signal", "polygons_changed"); + for (unsigned int i = 0; i < polygons.size(); i++) { + undo_redo->add_undo_method(this, "set_polygon", polygons[i]); + } + undo_redo->add_undo_method(base_control, "update"); + undo_redo->add_undo_method(this, "emit_signal", "polygons_changed"); + undo_redo->commit_action(true); + } break; default: break; } + if (!use_undo_redo) { + memdelete(undo_redo); + } } void GenericTilePolygonEditor::_grab_polygon_point(Vector2 p_pos, const Transform2D &p_polygon_xform, int &r_polygon_index, int &r_point_index) { @@ -359,6 +408,7 @@ void GenericTilePolygonEditor::_snap_to_half_pixel(Point2 &r_point) { } void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) { + UndoRedo *undo_redo = use_undo_redo ? editor_undo_redo : memnew(UndoRedo); real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); hovered_polygon_index = -1; @@ -399,15 +449,15 @@ void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_ctrl_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_ctrl_pressed()) { editor_zoom_widget->set_zoom_by_increments(1); _zoom_changed(); accept_event(); - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_ctrl_pressed()) { + } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_ctrl_pressed()) { editor_zoom_widget->set_zoom_by_increments(-1); _zoom_changed(); accept_event(); - } else if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + } else if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (tools_button_group->get_pressed_button() != button_create) { in_creation_polygon.clear(); @@ -504,7 +554,7 @@ void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) drag_point_index = -1; } - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + } else if (mb->get_button_index() == MouseButton::RIGHT) { if (mb->is_pressed()) { if (tools_button_group->get_pressed_button() == button_edit) { // Remove point or pan. @@ -538,7 +588,7 @@ void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) } else { drag_type = DRAG_TYPE_NONE; } - } else if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE) { + } else if (mb->get_button_index() == MouseButton::MIDDLE) { if (mb->is_pressed()) { drag_type = DRAG_TYPE_PAN; drag_last_pos = mb->get_position(); @@ -549,21 +599,47 @@ void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) } base_control->update(); + + if (!use_undo_redo) { + memdelete(undo_redo); + } +} + +void GenericTilePolygonEditor::set_use_undo_redo(bool p_use_undo_redo) { + use_undo_redo = p_use_undo_redo; } void GenericTilePolygonEditor::set_tile_set(Ref<TileSet> p_tile_set) { - if (tile_set != p_tile_set) { - // Set the default tile shape - clear_polygons(); - if (p_tile_set.is_valid()) { - Vector<Vector2> polygon = p_tile_set->get_tile_shape_polygon(); - for (int i = 0; i < polygon.size(); i++) { - polygon.write[i] = polygon[i] * p_tile_set->get_tile_size(); - } - add_polygon(polygon); + ERR_FAIL_COND(!p_tile_set.is_valid()); + if (tile_set == p_tile_set) { + return; + } + + // Set the default tile shape + clear_polygons(); + if (p_tile_set.is_valid()) { + Vector<Vector2> polygon = p_tile_set->get_tile_shape_polygon(); + for (int i = 0; i < polygon.size(); i++) { + polygon.write[i] = polygon[i] * p_tile_set->get_tile_size(); } + add_polygon(polygon); } + tile_set = p_tile_set; + + // Set the default zoom value. + int default_control_y_size = 200 * EDSCALE; + Vector2 zoomed_tile = editor_zoom_widget->get_zoom() * tile_set->get_tile_size(); + while (zoomed_tile.y < default_control_y_size) { + editor_zoom_widget->set_zoom_by_increments(6, false); + zoomed_tile = editor_zoom_widget->get_zoom() * tile_set->get_tile_size(); + } + while (zoomed_tile.y > default_control_y_size) { + editor_zoom_widget->set_zoom_by_increments(-6, false); + zoomed_tile = editor_zoom_widget->get_zoom() * tile_set->get_tile_size(); + } + editor_zoom_widget->set_zoom_by_increments(-6, false); + _zoom_changed(); } void GenericTilePolygonEditor::set_background(Ref<Texture2D> p_texture, Rect2 p_region, Vector2 p_offset, bool p_flip_h, bool p_flip_v, bool p_transpose, Color p_modulate) { @@ -644,6 +720,12 @@ void GenericTilePolygonEditor::_notification(int p_what) { button_center_view->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons"))); button_pixel_snap->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Snap"), SNAME("EditorIcons"))); button_advanced_menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); + + PopupMenu *p = button_advanced_menu->get_popup(); + p->set_item_icon(p->get_item_index(ROTATE_RIGHT), get_theme_icon(SNAME("RotateRight"), SNAME("EditorIcons"))); + p->set_item_icon(p->get_item_index(ROTATE_LEFT), get_theme_icon(SNAME("RotateLeft"), SNAME("EditorIcons"))); + p->set_item_icon(p->get_item_index(FLIP_HORIZONTALLY), get_theme_icon(SNAME("MirrorX"), SNAME("EditorIcons"))); + p->set_item_icon(p->get_item_index(FLIP_VERTICALLY), get_theme_icon(SNAME("MirrorY"), SNAME("EditorIcons"))); break; } } @@ -670,18 +752,21 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() { button_create->set_toggle_mode(true); button_create->set_button_group(tools_button_group); button_create->set_pressed(true); + button_create->set_tooltip(TTR("Add polygon tool")); toolbar->add_child(button_create); button_edit = memnew(Button); button_edit->set_flat(true); button_edit->set_toggle_mode(true); button_edit->set_button_group(tools_button_group); + button_edit->set_tooltip(TTR("Edit points tool")); toolbar->add_child(button_edit); button_delete = memnew(Button); button_delete->set_flat(true); button_delete->set_toggle_mode(true); button_delete->set_button_group(tools_button_group); + button_delete->set_tooltip(TTR("Delete points tool")); toolbar->add_child(button_delete); button_advanced_menu = memnew(MenuButton); @@ -689,7 +774,13 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() { button_advanced_menu->set_toggle_mode(true); button_advanced_menu->get_popup()->add_item(TTR("Reset to default tile shape"), RESET_TO_DEFAULT_TILE); button_advanced_menu->get_popup()->add_item(TTR("Clear"), CLEAR_TILE); + button_advanced_menu->get_popup()->add_separator(); + button_advanced_menu->get_popup()->add_icon_item(get_theme_icon(SNAME("RotateRight"), SNAME("EditorIcons")), TTR("Rotate Right"), ROTATE_RIGHT); + button_advanced_menu->get_popup()->add_icon_item(get_theme_icon(SNAME("RotateLeft"), SNAME("EditorIcons")), TTR("Rotate Left"), ROTATE_LEFT); + button_advanced_menu->get_popup()->add_icon_item(get_theme_icon(SNAME("MirrorX"), SNAME("EditorIcons")), TTR("Flip Horizontally"), FLIP_HORIZONTALLY); + button_advanced_menu->get_popup()->add_icon_item(get_theme_icon(SNAME("MirrorY"), SNAME("EditorIcons")), TTR("Flip Vertically"), FLIP_VERTICALLY); button_advanced_menu->get_popup()->connect("id_pressed", callable_mp(this, &GenericTilePolygonEditor::_advanced_menu_item_pressed)); + button_advanced_menu->set_focus_mode(FOCUS_ALL); toolbar->add_child(button_advanced_menu); toolbar->add_child(memnew(VSeparator)); @@ -698,6 +789,7 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() { button_pixel_snap->set_flat(true); button_pixel_snap->set_toggle_mode(true); button_pixel_snap->set_pressed(true); + button_pixel_snap->set_tooltip(TTR("Snap to half-pixel")); toolbar->add_child(button_pixel_snap); Control *root = memnew(Control); @@ -717,6 +809,7 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() { base_control->connect("draw", callable_mp(this, &GenericTilePolygonEditor::_base_control_draw)); base_control->connect("gui_input", callable_mp(this, &GenericTilePolygonEditor::_base_control_gui_input)); base_control->set_clip_contents(true); + base_control->set_focus_mode(Control::FOCUS_CLICK); root->add_child(base_control); editor_zoom_widget = memnew(EditorZoomWidget); @@ -836,7 +929,7 @@ void TileDataDefaultEditor::forward_painting_atlas_gui_input(TileAtlasView *p_ti Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (picker_button->is_pressed()) { Vector2i coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position()); @@ -927,7 +1020,7 @@ void TileDataDefaultEditor::forward_painting_alternatives_gui_input(TileAtlasVie Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (picker_button->is_pressed()) { Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mb->get_position()); @@ -1082,7 +1175,7 @@ TileDataDefaultEditor::TileDataDefaultEditor() { picker_button = memnew(Button); picker_button->set_flat(true); picker_button->set_toggle_mode(true); - picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", KEY_P)); + picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P)); toolbar->add_child(picker_button); } @@ -1432,7 +1525,7 @@ TileDataCollisionEditor::TileDataCollisionEditor() { angular_velocity_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1)); angular_velocity_editor->update_property(); add_child(angular_velocity_editor); - property_editors["angular_velocity"] = linear_velocity_editor; + property_editors["angular_velocity"] = angular_velocity_editor; _polygons_changed(); } @@ -1873,7 +1966,7 @@ void TileDataTerrainsEditor::forward_painting_atlas_gui_input(TileAtlasView *p_t Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (picker_button->is_pressed()) { Vector2i coords = p_tile_atlas_view->get_atlas_tile_coords_at_pos(mb->get_position()); @@ -2214,7 +2307,7 @@ void TileDataTerrainsEditor::forward_painting_alternatives_gui_input(TileAtlasVi Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { if (picker_button->is_pressed()) { Vector3i tile = p_tile_atlas_view->get_alternative_tile_at_pos(mb->get_position()); @@ -2385,7 +2478,7 @@ TileDataTerrainsEditor::TileDataTerrainsEditor() { picker_button = memnew(Button); picker_button->set_flat(true); picker_button->set_toggle_mode(true); - picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", KEY_P)); + picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P)); toolbar->add_child(picker_button); // Setup diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h index acb4c5882d..3fc5e738bb 100644 --- a/editor/plugins/tiles/tile_data_editors.h +++ b/editor/plugins/tiles/tile_data_editors.h @@ -94,7 +94,8 @@ private: LocalVector<Vector<Point2>> polygons; bool multiple_polygon_mode = false; - UndoRedo *undo_redo = EditorNode::get_undo_redo(); + bool use_undo_redo = true; + UndoRedo *editor_undo_redo = EditorNode::get_undo_redo(); // UI int hovered_polygon_index = -1; @@ -108,7 +109,7 @@ private: DRAG_TYPE_CREATE_POINT, DRAG_TYPE_PAN, }; - DragType drag_type; + DragType drag_type = DRAG_TYPE_NONE; int drag_polygon_index; int drag_point_index; Vector2 drag_last_pos; @@ -143,6 +144,10 @@ private: enum AdvancedMenuOption { RESET_TO_DEFAULT_TILE, CLEAR_TILE, + ROTATE_RIGHT, + ROTATE_LEFT, + FLIP_HORIZONTALLY, + FLIP_VERTICALLY, }; void _base_control_draw(); @@ -161,6 +166,8 @@ protected: static void _bind_methods(); public: + void set_use_undo_redo(bool p_use_undo_redo); + void set_tile_set(Ref<TileSet> p_tile_set); void set_background(Ref<Texture2D> p_texture, Rect2 p_region = Rect2(), Vector2 p_offset = Vector2(), bool p_flip_h = false, bool p_flip_v = false, bool p_transpose = false, Color p_modulate = Color(1.0, 1.0, 1.0, 0.0)); diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 39fbd86f77..73b1fc7c67 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -415,7 +415,7 @@ void TileMapEditorTilesPlugin::_scenes_list_multi_selected(int p_index, bool p_s TileMapCell selected = TileMapCell(source_id, Vector2i(), scene_id); // Clear the selection if shift is not pressed. - if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!Input::get_singleton()->is_key_pressed(Key::SHIFT)) { tile_set_selection.clear(); } @@ -590,10 +590,10 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform(); Vector2 mpos = xform.affine_inverse().xform(mb->get_position()); - if (mb->get_button_index() == MOUSE_BUTTON_LEFT || mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT) { if (mb->is_pressed()) { // Pressed - if (erase_button->is_pressed() || mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (erase_button->is_pressed() || mb->get_button_index() == MouseButton::RIGHT) { drag_erasing = true; } @@ -617,12 +617,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p } } else { // Check if we are picking a tile. - if (picker_button->is_pressed() || (Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + if (picker_button->is_pressed() || (Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) { drag_type = DRAG_TYPE_PICK; drag_start_mouse_pos = mpos; } else { // Paint otherwise. - if (tool_buttons_group->get_pressed_button() == paint_tool_button && !Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (tool_buttons_group->get_pressed_button() == paint_tool_button && !Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT)) { drag_type = DRAG_TYPE_PAINT; drag_start_mouse_pos = mpos; drag_modified.clear(); @@ -638,11 +638,11 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } _fix_invalid_tiles_in_tile_map_selection(); - } else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(KEY_SHIFT) && !Input::get_singleton()->is_key_pressed(KEY_CTRL))) { + } else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CTRL))) { drag_type = DRAG_TYPE_LINE; drag_start_mouse_pos = mpos; drag_modified.clear(); - } else if (tool_buttons_group->get_pressed_button() == rect_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(KEY_SHIFT) && Input::get_singleton()->is_key_pressed(KEY_CTRL))) { + } else if (tool_buttons_group->get_pressed_button() == rect_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && Input::get_singleton()->is_key_pressed(Key::CTRL))) { drag_type = DRAG_TYPE_RECT; drag_start_mouse_pos = mpos; drag_modified.clear(); @@ -713,7 +713,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over // Draw the selection. if ((tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree()) && tool_buttons_group->get_pressed_button() == select_tool_button) { // In select mode, we only draw the current selection if we are modifying it (pressing control or shift). - if (drag_type == DRAG_TYPE_MOVE || (drag_type == DRAG_TYPE_SELECT && !Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + if (drag_type == DRAG_TYPE_MOVE || (drag_type == DRAG_TYPE_SELECT && !Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) { // Do nothing } else { Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color"); @@ -783,7 +783,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over Vector2i coords = tile_map->map_pattern(tile_map->world_to_map(drag_last_mouse_pos - mouse_offset), clipboard_used_cells[i], tile_map_clipboard); preview[coords] = TileMapCell(tile_map_clipboard->get_cell_source_id(clipboard_used_cells[i]), tile_map_clipboard->get_cell_atlas_coords(clipboard_used_cells[i]), tile_map_clipboard->get_cell_alternative_tile(clipboard_used_cells[i])); } - } else if (!picker_button->is_pressed() && !(drag_type == DRAG_TYPE_NONE && Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + } else if (!picker_button->is_pressed() && !(drag_type == DRAG_TYPE_NONE && Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) { bool expand_grid = false; if (tool_buttons_group->get_pressed_button() == paint_tool_button && drag_type == DRAG_TYPE_NONE) { // Preview for a single pattern. @@ -1212,14 +1212,14 @@ void TileMapEditorTilesPlugin::_stop_dragging() { undo_redo->create_action(TTR("Change selection")); undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection()); - if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT) && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (!Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { tile_map_selection.clear(); } Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos) - tile_map->world_to_map(drag_start_mouse_pos)).abs(); for (int x = rect.position.x; x <= rect.get_end().x; x++) { for (int y = rect.position.y; y <= rect.get_end().y; y++) { Vector2i coords = Vector2i(x, y); - if (Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { if (tile_map_selection.has(coords)) { tile_map_selection.erase(coords); } @@ -1734,7 +1734,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { // Pressed tile_set_dragging_selection = true; tile_set_drag_start_mouse_pos = tile_atlas_control->get_local_mouse_position(); @@ -1892,7 +1892,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In } Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { // Pressed // Left click pressed. if (!mb->is_shift_pressed()) { @@ -1957,11 +1957,11 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { CanvasItemEditor::get_singleton()->get_viewport_control()->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_mouse_exited_viewport)); // --- Shortcuts --- - ED_SHORTCUT("tiles_editor/cut", TTR("Cut"), KEY_MASK_CMD | KEY_X); - ED_SHORTCUT("tiles_editor/copy", TTR("Copy"), KEY_MASK_CMD | KEY_C); - ED_SHORTCUT("tiles_editor/paste", TTR("Paste"), KEY_MASK_CMD | KEY_V); - ED_SHORTCUT("tiles_editor/cancel", TTR("Cancel"), KEY_ESCAPE); - ED_SHORTCUT("tiles_editor/delete", TTR("Delete"), KEY_DELETE); + ED_SHORTCUT("tiles_editor/cut", TTR("Cut"), KeyModifierMask::CMD | Key::X); + ED_SHORTCUT("tiles_editor/copy", TTR("Copy"), KeyModifierMask::CMD | Key::C); + ED_SHORTCUT("tiles_editor/paste", TTR("Paste"), KeyModifierMask::CMD | Key::V); + ED_SHORTCUT("tiles_editor/cancel", TTR("Cancel"), Key::ESCAPE); + ED_SHORTCUT("tiles_editor/delete", TTR("Delete"), Key::KEY_DELETE); // --- Initialize references --- tile_map_clipboard.instantiate(); @@ -1979,7 +1979,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { select_tool_button->set_flat(true); select_tool_button->set_toggle_mode(true); select_tool_button->set_button_group(tool_buttons_group); - select_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/selection_tool", "Selection", KEY_S)); + select_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/selection_tool", "Selection", Key::S)); select_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(select_tool_button); @@ -1987,7 +1987,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { paint_tool_button->set_flat(true); paint_tool_button->set_toggle_mode(true); paint_tool_button->set_button_group(tool_buttons_group); - paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", KEY_D)); + paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D)); paint_tool_button->set_tooltip(TTR("Shift: Draw line.") + "\n" + TTR("Shift+Ctrl: Draw rectangle.")); paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(paint_tool_button); @@ -1996,7 +1996,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { line_tool_button->set_flat(true); line_tool_button->set_toggle_mode(true); line_tool_button->set_button_group(tool_buttons_group); - line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", KEY_L)); + line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", Key::L)); line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(line_tool_button); @@ -2004,7 +2004,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { rect_tool_button->set_flat(true); rect_tool_button->set_toggle_mode(true); rect_tool_button->set_button_group(tool_buttons_group); - rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", KEY_R)); + rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", Key::R)); rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(rect_tool_button); @@ -2012,7 +2012,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { bucket_tool_button->set_flat(true); bucket_tool_button->set_toggle_mode(true); bucket_tool_button->set_button_group(tool_buttons_group); - bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", KEY_B)); + bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", Key::B)); bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(bucket_tool_button); toolbar->add_child(tilemap_tiles_tools_buttons); @@ -2028,7 +2028,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { picker_button = memnew(Button); picker_button->set_flat(true); picker_button->set_toggle_mode(true); - picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", KEY_P)); + picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P)); picker_button->set_tooltip(TTR("Alternatively hold Ctrl with other tools to pick tile.")); picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(picker_button); @@ -2037,7 +2037,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { erase_button = memnew(Button); erase_button->set_flat(true); erase_button->set_toggle_mode(true); - erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", KEY_E)); + erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E)); erase_button->set_tooltip(TTR("Alternatively use RMB to erase tiles.")); erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(erase_button); @@ -2766,10 +2766,10 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform(); Vector2 mpos = xform.affine_inverse().xform(mb->get_position()); - if (mb->get_button_index() == MOUSE_BUTTON_LEFT || mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT) { if (mb->is_pressed()) { // Pressed - if (erase_button->is_pressed() || mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (erase_button->is_pressed() || mb->get_button_index() == MouseButton::RIGHT) { drag_erasing = true; } @@ -2777,7 +2777,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> drag_type = DRAG_TYPE_PICK; } else { // Paint otherwise. - if (tool_buttons_group->get_pressed_button() == paint_tool_button && !Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (tool_buttons_group->get_pressed_button() == paint_tool_button && !Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT)) { if (selected_terrain_set < 0 || !selected_terrains_pattern.is_valid()) { return true; } @@ -2792,14 +2792,14 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key); tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); } - } else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(KEY_SHIFT) && !Input::get_singleton()->is_key_pressed(KEY_CTRL))) { + } else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CTRL))) { if (selected_terrain_set < 0 || !selected_terrains_pattern.is_valid()) { return true; } drag_type = DRAG_TYPE_LINE; drag_start_mouse_pos = mpos; drag_modified.clear(); - } else if (tool_buttons_group->get_pressed_button() == rect_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(KEY_SHIFT) && Input::get_singleton()->is_key_pressed(KEY_CTRL))) { + } else if (tool_buttons_group->get_pressed_button() == rect_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && Input::get_singleton()->is_key_pressed(Key::CTRL))) { if (selected_terrain_set < 0 || !selected_terrains_pattern.is_valid()) { return true; } @@ -2884,7 +2884,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o tile_xform.set_scale(tile_shape_size); tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0), false); } - } else if (!picker_button->is_pressed() && !(drag_type == DRAG_TYPE_NONE && Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + } else if (!picker_button->is_pressed() && !(drag_type == DRAG_TYPE_NONE && Input::get_singleton()->is_key_pressed(Key::CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) { bool expand_grid = false; if (tool_buttons_group->get_pressed_button() == paint_tool_button && drag_type == DRAG_TYPE_NONE) { // Preview for a single tile. @@ -3230,7 +3230,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { paint_tool_button->set_toggle_mode(true); paint_tool_button->set_button_group(tool_buttons_group); paint_tool_button->set_pressed(true); - paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", KEY_D)); + paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D)); paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(paint_tool_button); @@ -3238,7 +3238,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { line_tool_button->set_flat(true); line_tool_button->set_toggle_mode(true); line_tool_button->set_button_group(tool_buttons_group); - line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", KEY_L)); + line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", Key::L)); line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(line_tool_button); @@ -3246,7 +3246,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { rect_tool_button->set_flat(true); rect_tool_button->set_toggle_mode(true); rect_tool_button->set_button_group(tool_buttons_group); - rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", KEY_R)); + rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", Key::R)); rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(rect_tool_button); @@ -3254,7 +3254,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { bucket_tool_button->set_flat(true); bucket_tool_button->set_toggle_mode(true); bucket_tool_button->set_button_group(tool_buttons_group); - bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", KEY_B)); + bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", Key::B)); bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(bucket_tool_button); @@ -3271,7 +3271,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { picker_button = memnew(Button); picker_button->set_flat(true); picker_button->set_toggle_mode(true); - picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", KEY_P)); + picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P)); picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(picker_button); @@ -3279,7 +3279,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { erase_button = memnew(Button); erase_button->set_flat(true); erase_button->set_toggle_mode(true); - erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", KEY_E)); + erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E)); erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(erase_button); @@ -3897,8 +3897,8 @@ TileMapEditor::TileMapEditor() { set_process_internal(true); // Shortcuts. - ED_SHORTCUT("tiles_editor/select_next_layer", TTR("Select Next Tile Map Layer"), KEY_PAGEUP); - ED_SHORTCUT("tiles_editor/select_previous_layer", TTR("Select Previous Tile Map Layer"), KEY_PAGEDOWN); + ED_SHORTCUT("tiles_editor/select_next_layer", TTR("Select Next Tile Map Layer"), Key::PAGEUP); + ED_SHORTCUT("tiles_editor/select_previous_layer", TTR("Select Previous Tile Map Layer"), Key::PAGEDOWN); // TileMap editor plugins tile_map_editor_plugins.push_back(memnew(TileMapEditorTilesPlugin)); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index ae744f697b..a48c0e795c 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -99,6 +99,7 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, "")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, "")); + p_list->push_back(PropertyInfo(Variant::BOOL, "use_texture_padding", PROPERTY_HINT_NONE, "")); } void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_bind_methods() { @@ -1141,7 +1142,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position(); - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { // Left click pressed. if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) { @@ -1287,7 +1288,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven alternative_tiles_control_unscaled->update(); tile_atlas_view->update(); return; - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + } else if (mb->get_button_index() == MouseButton::RIGHT) { // Right click pressed. if (mb->is_pressed()) { drag_type = DRAG_TYPE_MAY_POPUP_MENU; @@ -1426,7 +1427,7 @@ void TileSetAtlasSourceEditor::_end_dragging() { // Determine if we clear, then add or remove to the selection. bool add_to_selection = true; - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { Vector2i coords = tile_set_atlas_source->get_tile_at_coords(start_base_tiles_coords); if (coords != TileSetSource::INVALID_ATLAS_COORDS) { if (selection.has({ coords, 0 })) { @@ -1891,7 +1892,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In drag_type = DRAG_TYPE_NONE; Vector2 mouse_local_pos = alternative_tiles_control->get_local_mouse_position(); - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { // Left click pressed. if (tools_button_group->get_pressed_button() == tool_select_button) { @@ -1907,7 +1908,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In _update_tile_id_label(); } } - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + } else if (mb->get_button_index() == MouseButton::RIGHT) { if (mb->is_pressed()) { // Right click pressed Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos); @@ -2061,7 +2062,7 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo int new_polygons_count = p_new_value; int old_polygons_count = tile_data_proxy->get(vformat("physics_layer_%d/polygons_count", layer_index)); if (new_polygons_count < old_polygons_count) { - for (int i = new_polygons_count - 1; i < old_polygons_count; i++) { + for (int i = new_polygons_count; i < old_polygons_count; i++) { ADD_UNDO(tile_data_proxy, vformat("physics_layer_%d/polygon_%d/points", layer_index, i)); ADD_UNDO(tile_data_proxy, vformat("physics_layer_%d/polygon_%d/one_way", layer_index, i)); ADD_UNDO(tile_data_proxy, vformat("physics_layer_%d/polygon_%d/one_way_margin", layer_index, i)); @@ -2453,7 +2454,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tools_settings_erase_button = memnew(Button); tools_settings_erase_button->set_flat(true); tools_settings_erase_button->set_toggle_mode(true); - tools_settings_erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", KEY_E)); + tools_settings_erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E)); tools_settings_erase_button->set_shortcut_context(this); tool_settings->add_child(tools_settings_erase_button); @@ -2485,7 +2486,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { right_panel->add_child(tile_atlas_view); base_tile_popup_menu = memnew(PopupMenu); - base_tile_popup_menu->add_shortcut(ED_SHORTCUT("tiles_editor/delete", TTR("Delete"), KEY_DELETE), TILE_DELETE); + base_tile_popup_menu->add_shortcut(ED_SHORTCUT("tiles_editor/delete", TTR("Delete"), Key::KEY_DELETE), TILE_DELETE); base_tile_popup_menu->add_item(TTR("Create an Alternative Tile"), TILE_CREATE_ALTERNATIVE); base_tile_popup_menu->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option)); tile_atlas_view->add_child(base_tile_popup_menu); @@ -2508,7 +2509,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_atlas_control_unscaled->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); alternative_tile_popup_menu = memnew(PopupMenu); - alternative_tile_popup_menu->add_shortcut(ED_SHORTCUT("tiles_editor/delete_tile", TTR("Delete"), KEY_DELETE), TILE_DELETE); + alternative_tile_popup_menu->add_shortcut(ED_SHORTCUT("tiles_editor/delete_tile", TTR("Delete"), Key::KEY_DELETE), TILE_DELETE); alternative_tile_popup_menu->connect("id_pressed", callable_mp(this, &TileSetAtlasSourceEditor::_menu_option)); tile_atlas_view->add_child(alternative_tile_popup_menu); @@ -2534,9 +2535,194 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { right_panel->add_child(tile_atlas_view_missing_source_label); EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetAtlasSourceEditor::_undo_redo_inspector_callback)); + + // Inspector plugin. + Ref<EditorInspectorPluginTileData> tile_data_inspector_plugin; + tile_data_inspector_plugin.instantiate(); + EditorInspector::add_inspector_plugin(tile_data_inspector_plugin); } TileSetAtlasSourceEditor::~TileSetAtlasSourceEditor() { memdelete(tile_proxy_object); memdelete(atlas_source_proxy_object); } + +////// EditorPropertyTilePolygon ////// + +void EditorPropertyTilePolygon::_add_focusable_children(Node *p_node) { + Control *control = Object::cast_to<Control>(p_node); + if (control && control->get_focus_mode() != Control::FOCUS_NONE) { + add_focusable(control); + } + for (int i = 0; i < p_node->get_child_count(); i++) { + _add_focusable_children(p_node->get_child(i)); + } +} + +void EditorPropertyTilePolygon::_polygons_changed() { + if (String(count_property).is_empty()) { + if (base_type == "OccluderPolygon2D") { + // Single OccluderPolygon2D. + Ref<OccluderPolygon2D> occluder; + if (generic_tile_polygon_editor->get_polygon_count() >= 1) { + occluder.instantiate(); + occluder->set_polygon(generic_tile_polygon_editor->get_polygon(0)); + } + emit_changed(get_edited_property(), occluder); + } else if (base_type == "NavigationPolygon") { + Ref<NavigationPolygon> navigation_polygon; + if (generic_tile_polygon_editor->get_polygon_count() >= 1) { + navigation_polygon.instantiate(); + for (int i = 0; i < generic_tile_polygon_editor->get_polygon_count(); i++) { + Vector<Vector2> polygon = generic_tile_polygon_editor->get_polygon(i); + navigation_polygon->add_outline(polygon); + } + navigation_polygon->make_polygons_from_outlines(); + } + emit_changed(get_edited_property(), navigation_polygon); + } + } else { + if (base_type.is_empty()) { + // Multiple array of vertices. + Vector<String> changed_properties; + Array values; + int count = generic_tile_polygon_editor->get_polygon_count(); + changed_properties.push_back(count_property); + values.push_back(count); + for (int i = 0; i < count; i++) { + changed_properties.push_back(vformat(element_pattern, i)); + values.push_back(generic_tile_polygon_editor->get_polygon(i)); + } + emit_signal("multiple_properties_changed", changed_properties, values, false); + } + } +} + +void EditorPropertyTilePolygon::update_property() { + TileSetAtlasSourceEditor::AtlasTileProxyObject *atlas_tile_proxy_object = Object::cast_to<TileSetAtlasSourceEditor::AtlasTileProxyObject>(get_edited_object()); + ERR_FAIL_COND(!atlas_tile_proxy_object); + ERR_FAIL_COND(atlas_tile_proxy_object->get_edited_tiles().is_empty()); + + TileSetAtlasSource *tile_set_atlas_source = atlas_tile_proxy_object->get_edited_tile_set_atlas_source(); + generic_tile_polygon_editor->set_tile_set(Ref<TileSet>(tile_set_atlas_source->get_tile_set())); + + // Set the background + Vector2i coords = atlas_tile_proxy_object->get_edited_tiles().front()->get().tile; + int alternative = atlas_tile_proxy_object->get_edited_tiles().front()->get().alternative; + TileData *tile_data = Object::cast_to<TileData>(tile_set_atlas_source->get_tile_data(coords, alternative)); + generic_tile_polygon_editor->set_background(tile_set_atlas_source->get_texture(), tile_set_atlas_source->get_tile_texture_region(coords), tile_set_atlas_source->get_tile_effective_texture_offset(coords, alternative), tile_data->get_flip_h(), tile_data->get_flip_v(), tile_data->get_transpose(), tile_data->get_modulate()); + + // Reset the polygons. + generic_tile_polygon_editor->clear_polygons(); + + if (String(count_property).is_empty()) { + if (base_type == "OccluderPolygon2D") { + // Single OccluderPolygon2D. + Ref<OccluderPolygon2D> occluder = get_edited_object()->get(get_edited_property()); + generic_tile_polygon_editor->clear_polygons(); + if (occluder.is_valid()) { + generic_tile_polygon_editor->add_polygon(occluder->get_polygon()); + } + } else if (base_type == "NavigationPolygon") { + // Single OccluderPolygon2D. + Ref<NavigationPolygon> navigation_polygon = get_edited_object()->get(get_edited_property()); + generic_tile_polygon_editor->clear_polygons(); + if (navigation_polygon.is_valid()) { + for (int i = 0; i < navigation_polygon->get_outline_count(); i++) { + generic_tile_polygon_editor->add_polygon(navigation_polygon->get_outline(i)); + } + } + } + } else { + int count = get_edited_object()->get(count_property); + if (base_type.is_empty()) { + // Multiple array of vertices. + generic_tile_polygon_editor->clear_polygons(); + for (int i = 0; i < count; i++) { + generic_tile_polygon_editor->add_polygon(get_edited_object()->get(vformat(element_pattern, i))); + } + } + } +} + +void EditorPropertyTilePolygon::setup_single_mode(const StringName &p_property, const String &p_base_type) { + set_object_and_property(nullptr, p_property); + base_type = p_base_type; + + generic_tile_polygon_editor->set_multiple_polygon_mode(false); +} + +void EditorPropertyTilePolygon::setup_multiple_mode(const StringName &p_property, const StringName &p_count_property, const String &p_element_pattern, const String &p_base_type) { + set_object_and_property(nullptr, p_property); + count_property = p_count_property; + element_pattern = p_element_pattern; + base_type = p_base_type; + + generic_tile_polygon_editor->set_multiple_polygon_mode(true); +} + +EditorPropertyTilePolygon::EditorPropertyTilePolygon() { + // Setup the polygon editor. + generic_tile_polygon_editor = memnew(GenericTilePolygonEditor); + generic_tile_polygon_editor->set_use_undo_redo(false); + generic_tile_polygon_editor->clear_polygons(); + add_child(generic_tile_polygon_editor); + generic_tile_polygon_editor->connect("polygons_changed", callable_mp(this, &EditorPropertyTilePolygon::_polygons_changed)); + + // Add all focussable children of generic_tile_polygon_editor as focussable. + _add_focusable_children(generic_tile_polygon_editor); +} + +////// EditorInspectorPluginTileData ////// + +bool EditorInspectorPluginTileData::can_handle(Object *p_object) { + return Object::cast_to<TileSetAtlasSourceEditor::AtlasTileProxyObject>(p_object) != nullptr; +} + +bool EditorInspectorPluginTileData::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { + Vector<String> components = String(p_path).split("/", true, 2); + if (components.size() == 2 && components[0].begins_with("occlusion_layer_") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) { + // Occlusion layers. + int layer_index = components[0].trim_prefix("occlusion_layer_").to_int(); + ERR_FAIL_COND_V(layer_index < 0, false); + if (components[1] == "polygon") { + EditorPropertyTilePolygon *ep = memnew(EditorPropertyTilePolygon); + ep->setup_single_mode(p_path, "OccluderPolygon2D"); + add_property_editor(p_path, ep); + return true; + } + } else if (components.size() >= 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_int()) { + // Physics layers. + int layer_index = components[0].trim_prefix("physics_layer_").to_int(); + ERR_FAIL_COND_V(layer_index < 0, false); + if (components[1] == "polygons_count") { + EditorPropertyTilePolygon *ep = memnew(EditorPropertyTilePolygon); + ep->setup_multiple_mode(vformat("physics_layer_%d/polygons", layer_index), vformat("physics_layer_%d/polygons_count", layer_index), vformat("physics_layer_%d/polygon_%%d/points", layer_index), ""); + Vector<String> properties; + properties.push_back(p_path); + int count = p_object->get(vformat("physics_layer_%d/polygons_count", layer_index)); + for (int i = 0; i < count; i++) { + properties.push_back(vformat(vformat("physics_layer_%d/polygon_%d/points", layer_index, i))); + } + add_property_editor_for_multiple_properties("Polygons", properties, ep); + return true; + } else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) { + int polygon_index = components[1].trim_prefix("polygon_").to_int(); + ERR_FAIL_COND_V(polygon_index < 0, false); + if (components[2] == "points") { + return true; + } + } + } else if (components.size() == 2 && components[0].begins_with("navigation_layer_") && components[0].trim_prefix("navigation_layer_").is_valid_int()) { + // Navigation layers. + int layer_index = components[0].trim_prefix("navigation_layer_").to_int(); + ERR_FAIL_COND_V(layer_index < 0, false); + if (components[1] == "polygon") { + EditorPropertyTilePolygon *ep = memnew(EditorPropertyTilePolygon); + ep->setup_single_mode(p_path, "NavigationPolygon"); + add_property_editor(p_path, ep); + return true; + } + } + return false; +} diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index ea6f2847ae..bd1fd2e7d0 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -43,7 +43,7 @@ class TileSet; class TileSetAtlasSourceEditor : public HBoxContainer { GDCLASS(TileSetAtlasSourceEditor, HBoxContainer); -private: +public: // A class to store which tiles are selected. struct TileSelection { Vector2i tile = TileSetSource::INVALID_ATLAS_COORDS; @@ -99,6 +99,9 @@ private: static void _bind_methods(); public: + TileSetAtlasSource *get_edited_tile_set_atlas_source() const { return tile_set_atlas_source; }; + Set<TileSelection> get_edited_tiles() const { return tiles; }; + // Update the proxyed object. void edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles = Set<TileSelection>()); @@ -107,6 +110,7 @@ private: } }; +private: Ref<TileSet> tile_set; TileSetAtlasSource *tile_set_atlas_source = nullptr; int tile_set_atlas_source_id = TileSet::INVALID_SOURCE; @@ -281,4 +285,34 @@ public: ~TileSetAtlasSourceEditor(); }; +class EditorPropertyTilePolygon : public EditorProperty { + GDCLASS(EditorPropertyTilePolygon, EditorProperty); + + StringName count_property; + String element_pattern; + String base_type; + + void _add_focusable_children(Node *p_node); + + GenericTilePolygonEditor *generic_tile_polygon_editor; + void _polygons_changed(); + +public: + virtual void update_property() override; + void setup_single_mode(const StringName &p_property, const String &p_base_type); + void setup_multiple_mode(const StringName &p_property, const StringName &p_count_property, const String &p_element_pattern, const String &p_base_type); + EditorPropertyTilePolygon(); +}; + +class EditorInspectorPluginTileData : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginTileData, EditorInspectorPlugin); + + void _occlusion_polygon_set_callback(); + void _polygons_changed(Object *p_generic_tile_polygon_editor, Object *p_object, const String &p_path); + +public: + virtual bool can_handle(Object *p_object) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; +}; + #endif // TILE_SET_ATLAS_SOURCE_EDITOR_H diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index aaa29bcb7a..b97095ef39 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -488,7 +488,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { commit_message->connect("text_changed", callable_mp(this, &VersionControlEditorPlugin::_update_commit_button)); commit_message->connect("gui_input", callable_mp(this, &VersionControlEditorPlugin::_commit_message_gui_input)); commit_box_vbc->add_child(commit_message); - ED_SHORTCUT("version_control/commit", TTR("Commit"), KEY_MASK_CMD | KEY_ENTER); + ED_SHORTCUT("version_control/commit", TTR("Commit"), KeyModifierMask::CMD | Key::ENTER); commit_button = memnew(Button); commit_button->set_text(TTR("Commit Changes")); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 10a9b2bb10..a4706bf0d9 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -3051,7 +3051,7 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; VisualShader::Type type = get_current_shader_type(); - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) { selected_constants.clear(); selected_uniforms.clear(); selected_comment = -1; @@ -3211,7 +3211,7 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNod void VisualShaderEditor::_sbox_input(const Ref<InputEvent> &p_ie) { Ref<InputEventKey> ie = p_ie; - if (ie.is_valid() && (ie->get_keycode() == KEY_UP || ie->get_keycode() == KEY_DOWN || ie->get_keycode() == KEY_ENTER || ie->get_keycode() == KEY_KP_ENTER)) { + if (ie.is_valid() && (ie->get_keycode() == Key::UP || ie->get_keycode() == Key::DOWN || ie->get_keycode() == Key::ENTER || ie->get_keycode() == Key::KP_ENTER)) { members->gui_input(ie); node_filter->accept_event(); } @@ -4527,6 +4527,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("MultiplyByAxisAngle", "Particles", "Transform", "VisualShaderNodeParticleMultiplyByAxisAngle", "A node for help to multiply a position input vector by rotation using specific axis. Intended to work with emitters.", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("BoxEmitter", "Particles", "Emitters", "VisualShaderNodeParticleBoxEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("MeshEmitter", "Particles", "Emitters", "VisualShaderNodeParticleMeshEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("RingEmitter", "Particles", "Emitters", "VisualShaderNodeParticleRingEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("SphereEmitter", "Particles", "Emitters", "VisualShaderNodeParticleSphereEmitter", "", -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); @@ -5186,11 +5187,7 @@ EditorPropertyShaderMode::EditorPropertyShaderMode() { } bool EditorInspectorShaderModePlugin::can_handle(Object *p_object) { - return true; //can handle everything -} - -void EditorInspectorShaderModePlugin::parse_begin(Object *p_object) { - //do none + return true; // Can handle everything. } bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { @@ -5203,11 +5200,7 @@ bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, const Var return true; } - return false; //can be overridden, although it will most likely be last anyway -} - -void EditorInspectorShaderModePlugin::parse_end() { - //do none + return false; } ////////////////////////////////// @@ -5224,7 +5217,9 @@ void VisualShaderNodePortPreview::_shader_changed() { preview_shader.instantiate(); preview_shader->set_code(shader_code); for (int i = 0; i < default_textures.size(); i++) { - preview_shader->set_default_texture_param(default_textures[i].name, default_textures[i].param); + for (int j = 0; j < default_textures[i].params.size(); j++) { + preview_shader->set_default_texture_param(default_textures[i].name, default_textures[i].params[j], j); + } } Ref<ShaderMaterial> material; diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index c4a392469b..74ccda3c9a 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -523,9 +523,7 @@ class EditorInspectorShaderModePlugin : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual void parse_begin(Object *p_object) override; virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; - virtual void parse_end() override; }; class VisualShaderNodePortPreview : public Control { diff --git a/editor/project_export.cpp b/editor/project_export.cpp index ad9c81458f..d48d45d848 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -38,6 +38,7 @@ #include "core/io/resource_saver.h" #include "core/os/os.h" #include "core/string/optimized_translation.h" +#include "core/version_generated.gen.h" #include "editor_data.h" #include "editor_node.h" #include "editor_scale.h" @@ -456,7 +457,7 @@ void ProjectExportDialog::_enc_filters_changed(const String &p_filters) { } void ProjectExportDialog::_open_key_help_link() { - OS::get_singleton()->shell_open("https://docs.godotengine.org/en/latest/development/compiling/compiling_with_script_encryption_key.html"); + OS::get_singleton()->shell_open(vformat("%s/development/compiling/compiling_with_script_encryption_key.html", VERSION_DOCS_URL)); } void ProjectExportDialog::_enc_pck_changed(bool p_pressed) { diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 150dde79e5..7b942adb54 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -52,6 +52,7 @@ #include "scene/gui/texture_rect.h" #include "scene/main/window.h" #include "servers/display_server.h" +#include "servers/navigation_server_3d.h" static inline String get_project_key_from_path(const String &dir) { return dir.replace("/", "::"); @@ -1735,7 +1736,7 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { int clicked_index = p_hb->get_index(); const Item &clicked_project = _projects[clicked_index]; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_shift_pressed() && _selected_project_keys.size() > 0 && _last_clicked != "" && clicked_project.project_key != _last_clicked) { int anchor_index = -1; for (int i = 0; i < _projects.size(); ++i) { @@ -1899,7 +1900,7 @@ void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) { // This is handled by the platform implementation on macOS, // so only define the shortcut on other platforms #ifndef OSX_ENABLED - if (k->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_Q)) { + if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::Q)) { _dim_window(); get_tree()->quit(); } @@ -1912,24 +1913,24 @@ void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) { bool keycode_handled = true; switch (k->get_keycode()) { - case KEY_ENTER: { + case Key::ENTER: { _open_selected_projects_ask(); } break; - case KEY_HOME: { + case Key::HOME: { if (_project_list->get_project_count() > 0) { _project_list->select_project(0); _update_project_buttons(); } } break; - case KEY_END: { + case Key::END: { if (_project_list->get_project_count() > 0) { _project_list->select_project(_project_list->get_project_count() - 1); _update_project_buttons(); } } break; - case KEY_UP: { + case Key::UP: { if (k->is_shift_pressed()) { break; } @@ -1943,7 +1944,7 @@ void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) { break; } - case KEY_DOWN: { + case Key::DOWN: { if (k->is_shift_pressed()) { break; } @@ -1956,7 +1957,7 @@ void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) { } } break; - case KEY_F: { + case Key::F: { if (k->is_command_pressed()) { this->search_box->grab_focus(); } else { @@ -2382,6 +2383,11 @@ ProjectManager::ProjectManager() { EditorSettings::create(); } + // Turn off some servers we aren't going to be using in the Project Manager. + NavigationServer3D::get_singleton()->set_active(false); + PhysicsServer3D::get_singleton()->set_active(false); + PhysicsServer2D::get_singleton()->set_active(false); + EditorSettings::get_singleton()->set_optimize_save(false); //just write settings as they came { @@ -2520,19 +2526,19 @@ ProjectManager::ProjectManager() { Button *create = memnew(Button); create->set_text(TTR("New Project")); - create->set_shortcut(ED_SHORTCUT("project_manager/new_project", TTR("New Project"), KEY_MASK_CMD | KEY_N)); + create->set_shortcut(ED_SHORTCUT("project_manager/new_project", TTR("New Project"), KeyModifierMask::CMD | Key::N)); create->connect("pressed", callable_mp(this, &ProjectManager::_new_project)); tree_vb->add_child(create); Button *import = memnew(Button); import->set_text(TTR("Import")); - import->set_shortcut(ED_SHORTCUT("project_manager/import_project", TTR("Import Project"), KEY_MASK_CMD | KEY_I)); + import->set_shortcut(ED_SHORTCUT("project_manager/import_project", TTR("Import Project"), KeyModifierMask::CMD | Key::I)); import->connect("pressed", callable_mp(this, &ProjectManager::_import_project)); tree_vb->add_child(import); Button *scan = memnew(Button); scan->set_text(TTR("Scan")); - scan->set_shortcut(ED_SHORTCUT("project_manager/scan_projects", TTR("Scan Projects"), KEY_MASK_CMD | KEY_S)); + scan->set_shortcut(ED_SHORTCUT("project_manager/scan_projects", TTR("Scan Projects"), KeyModifierMask::CMD | Key::S)); scan->connect("pressed", callable_mp(this, &ProjectManager::_scan_projects)); tree_vb->add_child(scan); @@ -2540,25 +2546,26 @@ ProjectManager::ProjectManager() { open_btn = memnew(Button); open_btn->set_text(TTR("Edit")); - open_btn->set_shortcut(ED_SHORTCUT("project_manager/edit_project", TTR("Edit Project"), KEY_MASK_CMD | KEY_E)); + open_btn->set_shortcut(ED_SHORTCUT("project_manager/edit_project", TTR("Edit Project"), KeyModifierMask::CMD | Key::E)); open_btn->connect("pressed", callable_mp(this, &ProjectManager::_open_selected_projects_ask)); tree_vb->add_child(open_btn); run_btn = memnew(Button); run_btn->set_text(TTR("Run")); - run_btn->set_shortcut(ED_SHORTCUT("project_manager/run_project", TTR("Run Project"), KEY_MASK_CMD | KEY_R)); + run_btn->set_shortcut(ED_SHORTCUT("project_manager/run_project", TTR("Run Project"), KeyModifierMask::CMD | Key::R)); run_btn->connect("pressed", callable_mp(this, &ProjectManager::_run_project)); tree_vb->add_child(run_btn); rename_btn = memnew(Button); rename_btn->set_text(TTR("Rename")); - rename_btn->set_shortcut(ED_SHORTCUT("project_manager/rename_project", TTR("Rename Project"), KEY_F2)); + // The F2 shortcut isn't overridden with Enter on macOS as Enter is already used to edit a project. + rename_btn->set_shortcut(ED_SHORTCUT("project_manager/rename_project", TTR("Rename Project"), Key::F2)); rename_btn->connect("pressed", callable_mp(this, &ProjectManager::_rename_project)); tree_vb->add_child(rename_btn); erase_btn = memnew(Button); erase_btn->set_text(TTR("Remove")); - erase_btn->set_shortcut(ED_SHORTCUT("project_manager/remove_project", TTR("Remove Project"), KEY_DELETE)); + erase_btn->set_shortcut(ED_SHORTCUT("project_manager/remove_project", TTR("Remove Project"), Key::KEY_DELETE)); erase_btn->connect("pressed", callable_mp(this, &ProjectManager::_erase_project)); tree_vb->add_child(erase_btn); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 62c5cc5cc1..f10ecab34e 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -1343,7 +1343,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) { void CustomPropertyEditor::_drag_easing(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseMotion> mm = p_ev; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { float rel = mm->get_relative().x; if (rel == 0) { return; @@ -1628,7 +1628,7 @@ real_t CustomPropertyEditor::_parse_real_expression(String text) { } void CustomPropertyEditor::_emit_changed_whole_or_field() { - if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!Input::get_singleton()->is_key_pressed(Key::SHIFT)) { emit_signal(SNAME("variant_changed")); } else { emit_signal(SNAME("variant_field_changed"), field_names[focused_value_editor]); diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index f167ded4e7..877b4552c1 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -44,10 +44,10 @@ void PropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) { if (k.is_valid()) { switch (k->get_keycode()) { - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: { + case Key::UP: + case Key::DOWN: + case Key::PAGEUP: + case Key::PAGEDOWN: { search_options->gui_input(k); search_box->accept_event(); diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index f0ec78bde6..7868414d89 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -167,10 +167,10 @@ void EditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) { Ref<InputEventKey> k = p_ie; if (k.is_valid()) { switch (k->get_keycode()) { - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: { + case Key::UP: + case Key::DOWN: + case Key::PAGEUP: + case Key::PAGEDOWN: { search_options->gui_input(k); search_box->accept_event(); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index f5b70504fa..eb73f88e61 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -30,6 +30,7 @@ #include "rename_dialog.h" +#include "modules/modules_enabled.gen.h" // For regex. #ifdef MODULE_REGEX_ENABLED #include "core/string/print_string.h" diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h index 4db3ef6740..f383877eb2 100644 --- a/editor/rename_dialog.h +++ b/editor/rename_dialog.h @@ -31,17 +31,16 @@ #ifndef RENAME_DIALOG_H #define RENAME_DIALOG_H -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For regex. #ifdef MODULE_REGEX_ENABLED +#include "core/object/undo_redo.h" +#include "editor/scene_tree_editor.h" #include "scene/gui/check_box.h" #include "scene/gui/dialogs.h" #include "scene/gui/option_button.h" #include "scene/gui/spin_box.h" -#include "core/object/undo_redo.h" -#include "editor/scene_tree_editor.h" - /** @author Blazej Floch */ diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 921befbb6b..0b293c9caf 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -52,6 +52,8 @@ #include "servers/display_server.h" #include "servers/rendering_server.h" +#include "modules/modules_enabled.gen.h" // For regex. + void SceneTreeDock::_nodes_drag_begin() { if (restore_script_editor_on_drag) { EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT); @@ -68,7 +70,7 @@ void SceneTreeDock::input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { restore_script_editor_on_drag = false; //lost chance } } @@ -214,7 +216,7 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N for (int i = 0; i < instances.size(); i++) { Node *instantiated_scene = instances[i]; - editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene); + editor_data->get_undo_redo().add_do_method(parent, "add_child", instantiated_scene, true); if (p_pos >= 0) { editor_data->get_undo_redo().add_do_method(parent, "move_child", instantiated_scene, p_pos + i); } @@ -259,8 +261,8 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) int pos = base->get_index(); undo_redo->add_do_method(parent, "remove_child", base); undo_redo->add_undo_method(parent, "remove_child", instantiated_scene); - undo_redo->add_do_method(parent, "add_child", instantiated_scene); - undo_redo->add_undo_method(parent, "add_child", base); + undo_redo->add_do_method(parent, "add_child", instantiated_scene, true); + undo_redo->add_undo_method(parent, "add_child", base, true); undo_redo->add_do_method(parent, "move_child", instantiated_scene, pos); undo_redo->add_undo_method(parent, "move_child", base, pos); @@ -512,7 +514,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { ERR_CONTINUE(!dup); - editor_data->get_undo_redo().add_do_method(paste_parent, "add_child", dup); + editor_data->get_undo_redo().add_do_method(paste_parent, "add_child", dup, true); for (KeyValue<const Node *, Node *> &E2 : duplimap) { Node *d = E2.value; @@ -814,7 +816,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().create_action(TTR("Make node as Root")); editor_data->get_undo_redo().add_do_method(node->get_parent(), "remove_child", node); editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", node); - editor_data->get_undo_redo().add_do_method(node, "add_child", root); + editor_data->get_undo_redo().add_do_method(node, "add_child", root, true); editor_data->get_undo_redo().add_do_method(node, "set_scene_file_path", root->get_scene_file_path()); editor_data->get_undo_redo().add_do_method(root, "set_scene_file_path", String()); editor_data->get_undo_redo().add_do_method(node, "set_owner", (Object *)nullptr); @@ -825,7 +827,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_undo_method(node, "set_scene_file_path", String()); editor_data->get_undo_redo().add_undo_method(node, "remove_child", root); editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", root); - editor_data->get_undo_redo().add_undo_method(node->get_parent(), "add_child", node); + editor_data->get_undo_redo().add_undo_method(node->get_parent(), "add_child", node, true); editor_data->get_undo_redo().add_undo_method(node->get_parent(), "move_child", node, node->get_index()); editor_data->get_undo_redo().add_undo_method(root, "set_owner", (Object *)nullptr); editor_data->get_undo_redo().add_undo_method(node, "set_owner", root); @@ -1193,7 +1195,7 @@ void SceneTreeDock::_node_collapsed(Object *p_obj) { return; } - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) { _set_collapsed_recursive(ti, ti->is_collapsed()); } } @@ -1786,7 +1788,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V } editor_data->get_undo_redo().add_do_method(node->get_parent(), "remove_child", node); - editor_data->get_undo_redo().add_do_method(new_parent, "add_child", node); + editor_data->get_undo_redo().add_do_method(new_parent, "add_child", node, true); if (p_position_in_parent >= 0) { editor_data->get_undo_redo().add_do_method(new_parent, "move_child", node, p_position_in_parent + inc); @@ -1859,7 +1861,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V int child_pos = node->get_index(); - editor_data->get_undo_redo().add_undo_method(node->get_parent(), "add_child", node); + editor_data->get_undo_redo().add_undo_method(node->get_parent(), "add_child", node, true); editor_data->get_undo_redo().add_undo_method(node->get_parent(), "move_child", node, child_pos); editor_data->get_undo_redo().add_undo_method(this, "_set_owners", edited_scene, owners); if (AnimationPlayerEditor::get_singleton()->get_track_editor()->get_root() == node) { @@ -2072,7 +2074,7 @@ void SceneTreeDock::_delete_confirm(bool p_cut) { } editor_data->get_undo_redo().add_do_method(n->get_parent(), "remove_child", n); - editor_data->get_undo_redo().add_undo_method(n->get_parent(), "add_child", n); + editor_data->get_undo_redo().add_undo_method(n->get_parent(), "add_child", n, true); editor_data->get_undo_redo().add_undo_method(n->get_parent(), "move_child", n, n->get_index()); if (AnimationPlayerEditor::get_singleton()->get_track_editor()->get_root() == n) { editor_data->get_undo_redo().add_undo_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", n); @@ -2616,7 +2618,7 @@ void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) { int to_pos = -1; _normalize_drop(to_node, to_pos, p_type); - _do_reparent(to_node, to_pos, nodes, !Input::get_singleton()->is_key_pressed(KEY_SHIFT)); + _do_reparent(to_node, to_pos, nodes, !Input::get_singleton()->is_key_pressed(Key::SHIFT)); } void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) { @@ -2827,7 +2829,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (profile_allow_editing) { menu->add_separator(); - menu->add_icon_shortcut(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE); + menu->add_icon_shortcut(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), Key::KEY_DELETE), TOOL_ERASE); } menu->set_size(Size2(1, 1)); menu->set_position(p_menu_pos); @@ -3227,28 +3229,32 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel HBoxContainer *filter_hbc = memnew(HBoxContainer); filter_hbc->add_theme_constant_override("separate", 0); - ED_SHORTCUT("scene_tree/rename", TTR("Rename"), KEY_F2); - ED_SHORTCUT("scene_tree/batch_rename", TTR("Batch Rename"), KEY_MASK_SHIFT | KEY_F2); - ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KEY_MASK_CMD | KEY_A); - ED_SHORTCUT("scene_tree/instance_scene", TTR("Instantiate Child Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_A); + ED_SHORTCUT("scene_tree/rename", TTR("Rename"), Key::F2); + ED_SHORTCUT_OVERRIDE("scene_tree/rename", "macos", Key::ENTER); + + ED_SHORTCUT("scene_tree/batch_rename", TTR("Batch Rename"), KeyModifierMask::SHIFT | Key::F2); + ED_SHORTCUT_OVERRIDE("scene_tree/batch_rename", "macos", KeyModifierMask::SHIFT | Key::ENTER); + + ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KeyModifierMask::CMD | Key::A); + ED_SHORTCUT("scene_tree/instance_scene", TTR("Instantiate Child Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::A); ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse All")); - ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KEY_MASK_CMD | KEY_X); - ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KEY_MASK_CMD | KEY_C); - ED_SHORTCUT("scene_tree/paste_node", TTR("Paste"), KEY_MASK_CMD | KEY_V); + ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KeyModifierMask::CMD | Key::X); + ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KeyModifierMask::CMD | Key::C); + ED_SHORTCUT("scene_tree/paste_node", TTR("Paste"), KeyModifierMask::CMD | Key::V); ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type")); ED_SHORTCUT("scene_tree/attach_script", TTR("Attach Script")); ED_SHORTCUT("scene_tree/extend_script", TTR("Extend Script")); ED_SHORTCUT("scene_tree/detach_script", TTR("Detach Script")); - ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KEY_MASK_CMD | KEY_UP); - ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KEY_MASK_CMD | KEY_DOWN); - ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"), KEY_MASK_CMD | KEY_D); + ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KeyModifierMask::CMD | Key::UP); + ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KeyModifierMask::CMD | Key::DOWN); + ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"), KeyModifierMask::CMD | Key::D); ED_SHORTCUT("scene_tree/reparent", TTR("Reparent")); ED_SHORTCUT("scene_tree/reparent_to_new_node", TTR("Reparent to New Node")); ED_SHORTCUT("scene_tree/make_root", TTR("Make Scene Root")); ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene")); - ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_C); - ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KEY_MASK_SHIFT | KEY_DELETE); - ED_SHORTCUT("scene_tree/delete", TTR("Delete"), KEY_DELETE); + ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::C); + ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KeyModifierMask::SHIFT | Key::KEY_DELETE); + ED_SHORTCUT("scene_tree/delete", TTR("Delete"), Key::KEY_DELETE); button_add = memnew(Button); button_add->set_flat(true); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 8de9884019..c6e47fa002 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -48,6 +48,8 @@ #include "scene/gui/tree.h" #include "scene_tree_editor.h" +#include "modules/modules_enabled.gen.h" // For regex. + class EditorNode; class ShaderCreateDialog; diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index 78dc85aa7d..684f8aa37e 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -164,7 +164,7 @@ void EditorSettingsDialog::unhandled_input(const Ref<InputEvent> &p_event) { handled = true; } - if (k->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) { + if (k->get_keycode_with_modifiers() == (KeyModifierMask::CMD | Key::F)) { _focus_current_search_box(); handled = true; } diff --git a/main/main.cpp b/main/main.cpp index 0cf805f94a..f0f8c01592 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -57,7 +57,6 @@ #include "main/performance.h" #include "main/splash.gen.h" #include "main/splash_editor.gen.h" -#include "modules/modules_enabled.gen.h" #include "modules/register_module_types.h" #include "platform/register_platform_apis.h" #include "scene/main/scene_tree.h" @@ -81,16 +80,16 @@ #endif #ifdef TOOLS_ENABLED - #include "editor/doc_data_class_path.gen.h" #include "editor/doc_tools.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/progress_dialog.h" #include "editor/project_manager.h" - #endif +#include "modules/modules_enabled.gen.h" // For mono. + /* Static members */ // Singletons @@ -2050,7 +2049,7 @@ bool Main::start() { GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000); GLOBAL_DEF("mono/profiler/args", "log:calls,alloc,sample,output=output.mlpd"); GLOBAL_DEF("mono/profiler/enabled", false); - GLOBAL_DEF("mono/unhandled_exception_policy", 0); + GLOBAL_DEF("mono/runtime/unhandled_exception_policy", 0); #endif DocTools doc; @@ -2687,10 +2686,10 @@ bool Main::iteration() { if (frame > 1000000) { if (editor || project_manager) { if (print_fps) { - print_line(vformat("Editor FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(1))); + print_line(vformat("Editor FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2))); } } else if (GLOBAL_GET("debug/settings/stdout/print_fps") || print_fps) { - print_line(vformat("Project FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(1))); + print_line(vformat("Project FPS: %d (%s mspf)", frames, rtos(1000.0 / frames).pad_decimals(2))); } Engine::get_singleton()->_fps = frames; diff --git a/methods.py b/methods.py index b2eb7b7c77..3331e159c7 100644 --- a/methods.py +++ b/methods.py @@ -105,6 +105,8 @@ def update_version(module_version_string=""): f.write('#define VERSION_MODULE_CONFIG "' + str(version.module_config) + module_version_string + '"\n') f.write("#define VERSION_YEAR " + str(version.year) + "\n") f.write('#define VERSION_WEBSITE "' + str(version.website) + '"\n') + f.write('#define VERSION_DOCS_BRANCH "' + str(version.docs) + '"\n') + f.write('#define VERSION_DOCS_URL "https://docs.godotengine.org/en/" VERSION_DOCS_BRANCH\n') f.write("#endif // VERSION_GENERATED_GEN_H\n") f.close() diff --git a/misc/hooks/README.md b/misc/hooks/README.md index e420c6cb5c..8732237244 100644 --- a/misc/hooks/README.md +++ b/misc/hooks/README.md @@ -28,7 +28,7 @@ so they should work out of the box on Linux/macOS. #### Windows ##### clang-format -- Download LLVM for Windows (version 8 or later) from +- Download LLVM for Windows (version 13 or later) from <https://releases.llvm.org/download.html> - Make sure LLVM is added to the `PATH` during installation diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 610d2145cd..684a20cf4d 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -837,8 +837,17 @@ void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) { } PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_body) { + if (!rigid_body_owner.owns(p_body)) { + return nullptr; + } + RigidBodyBullet *body = rigid_body_owner.get_or_null(p_body); ERR_FAIL_COND_V(!body, nullptr); + + if (!body->get_space()) { + return nullptr; + } + return BulletPhysicsDirectBodyState3D::get_singleton(body); } diff --git a/modules/csg/doc_classes/CSGShape3D.xml b/modules/csg/doc_classes/CSGShape3D.xml index 446269f3f0..f5031064d6 100644 --- a/modules/csg/doc_classes/CSGShape3D.xml +++ b/modules/csg/doc_classes/CSGShape3D.xml @@ -59,10 +59,10 @@ <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> The physics layers this area is in. Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property. - A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The physics layers this CSG shape scans for collisions. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers this CSG shape scans for collisions. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape3D.Operation" default="0"> The operation that is performed on this shape. This is ignored for the first CSG child node as the operation is between this node and the previous child of this nodes parent. diff --git a/modules/enet/doc_classes/ENetMultiplayerPeer.xml b/modules/enet/doc_classes/ENetMultiplayerPeer.xml index 22136c3944..d2456d3360 100644 --- a/modules/enet/doc_classes/ENetMultiplayerPeer.xml +++ b/modules/enet/doc_classes/ENetMultiplayerPeer.xml @@ -8,7 +8,7 @@ [b]Note:[/b] ENet only uses UDP, not TCP. When forwarding the server port to make your server accessible on the public Internet, you only need to forward the server port in UDP. You can use the [UPNP] class to try to forward the server port automatically when starting the server. </description> <tutorials> - <link title="High-level multiplayer">https://docs.godotengine.org/en/latest/tutorials/networking/high_level_multiplayer.html</link> + <link title="High-level multiplayer">$DOCS_URL/tutorials/networking/high_level_multiplayer.html</link> <link title="API documentation on the ENet website">http://enet.bespin.org/usergroup0.html</link> </tutorials> <methods> diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml index 6b3bd714b9..21df640ebc 100644 --- a/modules/gdnative/doc_classes/GDNativeLibrary.xml +++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml @@ -7,8 +7,8 @@ A GDNative library can implement [NativeScript]s, global functions to call with the [GDNative] class, or low-level engine extensions through interfaces such as XRInterfaceGDNative. The library must be compiled for each platform and architecture that the project will run on. </description> <tutorials> - <link title="GDNative C example">https://docs.godotengine.org/en/latest/tutorials/scripting/gdnative/gdnative_c_example.html</link> - <link title="GDNative C++ example">https://docs.godotengine.org/en/latest/tutorials/scripting/gdnative/gdnative_cpp_example.html</link> + <link title="GDNative C example">$DOCS_URL/tutorials/scripting/gdnative/gdnative_c_example.html</link> + <link title="GDNative C++ example">$DOCS_URL/tutorials/scripting/gdnative/gdnative_cpp_example.html</link> </tutorials> <methods> <method name="get_current_dependencies" qualifiers="const"> diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 5b476cda01..9c8adb4cf1 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -7,7 +7,7 @@ List of core built-in GDScript functions. Math functions and other utilities. Everything else is provided by objects. (Keywords: builtin, built in, global functions.) </description> <tutorials> - <link title="Random number generation">https://docs.godotengine.org/en/latest/tutorials/math/random_number_generation.html</link> + <link title="Random number generation">$DOCS_URL/tutorials/math/random_number_generation.html</link> </tutorials> <methods> <method name="Color8"> diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml index 0a448ed88c..5acb29e748 100644 --- a/modules/gdscript/doc_classes/GDScript.xml +++ b/modules/gdscript/doc_classes/GDScript.xml @@ -8,7 +8,7 @@ [method new] creates a new instance of the script. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes. </description> <tutorials> - <link title="GDScript documentation index">https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/index.html</link> + <link title="GDScript documentation index">$DOCS_URL/tutorials/scripting/gdscript/index.html</link> </tutorials> <methods> <method name="get_as_byte_code" qualifiers="const"> diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index e4d3ed118c..68da588c3d 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -361,7 +361,7 @@ ScriptInstance *GDScript::instance_create(Object *p_this) { if (top->native.is_valid()) { if (!ClassDB::is_parent_class(p_this->get_class_name(), top->native->get_name())) { if (EngineDebugger::is_active()) { - GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type: '" + p_this->get_class() + "'"); + GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), 1, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type: '" + p_this->get_class() + "'"); } ERR_FAIL_V_MSG(nullptr, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instantiated in object of type '" + p_this->get_class() + "'" + "."); } @@ -789,6 +789,14 @@ void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) { } } +String GDScript::_get_debug_path() const { + if (is_built_in() && !get_name().is_empty()) { + return get_name() + " (" + get_path().get_slice("::", 0) + ")"; + } else { + return get_path(); + } +} + Error GDScript::reload(bool p_keep_state) { bool has_instances; { @@ -832,7 +840,7 @@ Error GDScript::reload(bool p_keep_state) { Error err = parser.parse(source, path, false); if (err) { if (EngineDebugger::is_active()) { - GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), parser.get_errors().front()->get().line, "Parser Error: " + parser.get_errors().front()->get().message); + GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), parser.get_errors().front()->get().line, "Parser Error: " + parser.get_errors().front()->get().message); } // TODO: Show all error messages. _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); @@ -844,7 +852,7 @@ Error GDScript::reload(bool p_keep_state) { if (err) { if (EngineDebugger::is_active()) { - GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), parser.get_errors().front()->get().line, "Parser Error: " + parser.get_errors().front()->get().message); + GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), parser.get_errors().front()->get().line, "Parser Error: " + parser.get_errors().front()->get().message); } const List<GDScriptParser::ParserError>::Element *e = parser.get_errors().front(); @@ -867,7 +875,7 @@ Error GDScript::reload(bool p_keep_state) { if (err) { if (can_run) { if (EngineDebugger::is_active()) { - GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error()); + GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error()); } _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), false, ERR_HANDLER_SCRIPT); ERR_FAIL_V(ERR_COMPILATION_FAILED); diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 791f8a1431..ade4f247c9 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -135,6 +135,7 @@ class GDScript : public Script { GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error); void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path); + String _get_debug_path() const; #ifdef TOOLS_ENABLED Set<PlaceHolderScriptInstance *> placeholders; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index b96139ac51..bde6783322 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -740,10 +740,24 @@ void GDScriptParser::parse_class_member(T *(GDScriptParser::*p_parse_function)() #endif // TOOLS_ENABLED if (member->identifier != nullptr) { - // Enums may be unnamed. - // TODO: Consider names in outer scope too, for constants and classes (and static functions?) - if (current_class->members_indices.has(member->identifier->name)) { - push_error(vformat(R"(%s "%s" has the same name as a previously declared %s.)", p_member_kind.capitalize(), member->identifier->name, current_class->get_member(member->identifier->name).get_type_name()), member->identifier); + if (!((String)member->identifier->name).is_empty()) { // Enums may be unnamed. + List<MethodInfo> gdscript_funcs; + GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); + for (MethodInfo &info : gdscript_funcs) { + if (info.name == member->identifier->name) { + push_error(vformat(R"(%s "%s" has the same name as a built-in function.)", p_member_kind.capitalize(), member->identifier->name), member->identifier); + return; + } + } + if (current_class->members_indices.has(member->identifier->name)) { + push_error(vformat(R"(%s "%s" has the same name as a previously declared %s.)", p_member_kind.capitalize(), member->identifier->name, current_class->get_member(member->identifier->name).get_type_name()), member->identifier); + } else if (Variant::has_utility_function(member->identifier->name)) { + push_error(vformat(R"(%s "%s" has the same name as a built-in function.)", p_member_kind.capitalize(), member->identifier->name), member->identifier); + } else if (ClassDB::class_exists(member->identifier->name)) { + push_error(vformat(R"(%s "%s" has the same name as a global class.)", p_member_kind.capitalize(), member->identifier->name), member->identifier); + } else { + current_class->add_member(member); + } } else { current_class->add_member(member); } @@ -811,9 +825,27 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper return nullptr; } + GDScriptParser::IdentifierNode *identifier = parse_identifier(); + + List<MethodInfo> gdscript_funcs; + GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); + for (MethodInfo &info : gdscript_funcs) { + if (info.name == identifier->name) { + push_error(vformat(R"(Local var "%s" has the same name as a built-in function.)", identifier->name), identifier); + return nullptr; + } + } + if (Variant::has_utility_function(identifier->name)) { + push_error(vformat(R"(Local var "%s" has the same name as a built-in function.)", identifier->name), identifier); + return nullptr; + } else if (ClassDB::class_exists(identifier->name)) { + push_error(vformat(R"(Local var "%s" has the same name as a global class.)", identifier->name), identifier); + return nullptr; + } + VariableNode *variable = alloc_node<VariableNode>(); - variable->identifier = parse_identifier(); - variable->export_info.name = variable->identifier->name; + variable->identifier = identifier; + variable->export_info.name = identifier->name; if (match(GDScriptTokenizer::Token::COLON)) { if (check(GDScriptTokenizer::Token::NEWLINE)) { @@ -1066,8 +1098,26 @@ GDScriptParser::ParameterNode *GDScriptParser::parse_parameter() { return nullptr; } + GDScriptParser::IdentifierNode *identifier = parse_identifier(); + + List<MethodInfo> gdscript_funcs; + GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); + for (MethodInfo &info : gdscript_funcs) { + if (info.name == identifier->name) { + push_error(vformat(R"(Parameter "%s" has the same name as a built-in function.)", identifier->name), identifier); + return nullptr; + } + } + if (Variant::has_utility_function(identifier->name)) { + push_error(vformat(R"(Parameter "%s" has the same name as a built-in function.)", identifier->name), identifier); + return nullptr; + } else if (ClassDB::class_exists(identifier->name)) { + push_error(vformat(R"(Parameter "%s" has the same name as a global class.)", identifier->name), identifier); + return nullptr; + } + ParameterNode *parameter = alloc_node<ParameterNode>(); - parameter->identifier = parse_identifier(); + parameter->identifier = identifier; if (match(GDScriptTokenizer::Token::COLON)) { if (check((GDScriptTokenizer::Token::EQUAL))) { @@ -1145,13 +1195,31 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { HashMap<StringName, int> elements; + List<MethodInfo> gdscript_funcs; + GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); + do { if (check(GDScriptTokenizer::Token::BRACE_CLOSE)) { break; // Allow trailing comma. } if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for enum key.)")) { EnumNode::Value item; - item.identifier = parse_identifier(); + GDScriptParser::IdentifierNode *identifier = parse_identifier(); + + for (MethodInfo &info : gdscript_funcs) { + if (info.name == identifier->name) { + push_error(vformat(R"(Enum member "%s" has the same name as a built-in function.)", identifier->name), identifier); + return nullptr; + } + } + if (Variant::has_utility_function(identifier->name)) { + push_error(vformat(R"(Enum member "%s" has the same name as a built-in function.)", identifier->name), identifier); + return nullptr; + } else if (ClassDB::class_exists(identifier->name)) { + push_error(vformat(R"(Enum member "%s" has the same name as a global class.)", identifier->name), identifier); + return nullptr; + } + item.identifier = identifier; item.parent_enum = enum_node; item.line = previous.start_line; item.leftmost_column = previous.leftmost_column; @@ -2774,6 +2842,23 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p get_node->chain.push_back(identifier); } while (match(GDScriptTokenizer::Token::SLASH)); return get_node; + } else if (match(GDScriptTokenizer::Token::SLASH)) { + GetNodeNode *get_node = alloc_node<GetNodeNode>(); + IdentifierNode *identifier_root = alloc_node<IdentifierNode>(); + get_node->chain.push_back(identifier_root); + int chain_position = 0; + do { + make_completion_context(COMPLETION_GET_NODE, get_node, chain_position++); + if (!current.is_node_name()) { + push_error(R"(Expect node path after "/".)"); + return nullptr; + } + advance(); + IdentifierNode *identifier = alloc_node<IdentifierNode>(); + identifier->name = previous.get_identifier(); + get_node->chain.push_back(identifier); + } while (match(GDScriptTokenizer::Token::SLASH)); + return get_node; } else { push_error(R"(Expect node path as string or identifier after "$".)"); return nullptr; diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index cd247d1d26..3725fb58f5 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -795,6 +795,15 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() { char32_t ch = _peek(); + if (ch == 0x200E || ch == 0x200F || (ch >= 0x202A && ch <= 0x202E) || (ch >= 0x2066 && ch <= 0x2069)) { + Token error = make_error("Invisible text direction control character present in the string, escape it (\"\\u" + String::num_int64(ch, 16) + "\") to avoid confusion."); + error.start_column = column; + error.leftmost_column = error.start_column; + error.end_column = column + 1; + error.rightmost_column = error.end_column; + push_error(error); + } + if (ch == '\\') { // Escape pattern. _advance(); diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h index 899446fb42..a4a63a23a8 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.h +++ b/modules/gdscript/language_server/gdscript_language_protocol.h @@ -38,7 +38,7 @@ #include "gdscript_workspace.h" #include "lsp.hpp" -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For jsonrpc. #ifdef MODULE_JSONRPC_ENABLED #include "modules/jsonrpc/jsonrpc.h" #else diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index ced80e26b5..fac1e61b18 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -68,7 +68,7 @@ #include "scene/resources/multimesh.h" #include "scene/resources/surface_tool.h" -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For csg, gridmap. #ifdef MODULE_CSG_ENABLED #include "modules/csg/csg_shape.h" @@ -5856,7 +5856,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, animation->set_name(name); if (anim->get_loop()) { - animation->set_loop(true); + animation->set_loop_mode(Animation::LOOP_LINEAR); } float length = 0.0; diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index f2f0b439a5..27a1f64bca 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -46,7 +46,8 @@ #include "scene/resources/material.h" #include "scene/resources/texture.h" -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For csg, gridmap. + #include <cstdint> class GLTFState; diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index c1dbe63628..73315350ff 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -11,7 +11,7 @@ [b]Note:[/b] GridMap doesn't extend [VisualInstance3D] and therefore can't be hidden or cull masked based on [member VisualInstance3D.layers]. If you make a light not affect the first layer, the whole GridMap won't be lit by the light in question. </description> <tutorials> - <link title="Using gridmaps">https://docs.godotengine.org/en/latest/tutorials/3d/using_gridmaps.html</link> + <link title="Using gridmaps">$DOCS_URL/tutorials/3d/using_gridmaps.html</link> <link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link> <link title="3D Kinematic Character Demo">https://godotengine.org/asset-library/asset/126</link> </tutorials> @@ -173,7 +173,7 @@ GridMaps act as static bodies, meaning they aren't affected by gravity or other forces. They only affect other physics bodies that collide with them. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The physics layers this GridMap detects collisions in. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers this GridMap detects collisions in. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="mesh_library" type="MeshLibrary" setter="set_mesh_library" getter="get_mesh_library"> The assigned [MeshLibrary]. diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 08d55de976..d827ce2fb0 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -611,13 +611,13 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && (mb->is_command_pressed() || mb->is_shift_pressed())) { + if (mb->get_button_index() == MouseButton::WHEEL_UP && (mb->is_command_pressed() || mb->is_shift_pressed())) { if (mb->is_pressed()) { floor->set_value(floor->get_value() + mb->get_factor()); } return EditorPlugin::AFTER_GUI_INPUT_STOP; // Eaten. - } else if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && (mb->is_command_pressed() || mb->is_shift_pressed())) { + } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && (mb->is_command_pressed() || mb->is_shift_pressed())) { if (mb->is_pressed()) { floor->set_value(floor->get_value() - mb->get_factor()); } @@ -628,7 +628,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D Node3DEditorViewport::NavigationScheme nav_scheme = (Node3DEditorViewport::NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); if ((nav_scheme == Node3DEditorViewport::NAVIGATION_MAYA || nav_scheme == Node3DEditorViewport::NAVIGATION_MODO) && mb->is_alt_pressed()) { input_action = INPUT_NONE; - } else if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + } else if (mb->get_button_index() == MouseButton::LEFT) { bool can_edit = (node && node->get_mesh_library().is_valid()); if (input_action == INPUT_PASTE) { _do_paste(); @@ -643,7 +643,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D input_action = INPUT_PAINT; set_items.clear(); } - } else if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + } else if (mb->get_button_index() == MouseButton::RIGHT) { if (input_action == INPUT_PASTE) { _clear_clipboard_data(); input_action = INPUT_NONE; @@ -665,7 +665,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D } return EditorPlugin::AFTER_GUI_INPUT_PASS; } else { - if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action == INPUT_PAINT)) { + if ((mb->get_button_index() == MouseButton::RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == MouseButton::LEFT && input_action == INPUT_PAINT)) { if (set_items.size()) { undo_redo->create_action(TTR("GridMap Paint")); for (const SetItem &si : set_items) { @@ -687,19 +687,19 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D return EditorPlugin::AFTER_GUI_INPUT_PASS; } - if (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action == INPUT_SELECT) { + if (mb->get_button_index() == MouseButton::LEFT && input_action == INPUT_SELECT) { undo_redo->create_action(TTR("GridMap Selection")); undo_redo->add_do_method(this, "_set_selection", selection.active, selection.begin, selection.end); undo_redo->add_undo_method(this, "_set_selection", last_selection.active, last_selection.begin, last_selection.end); undo_redo->commit_action(); } - if (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action != INPUT_NONE) { + if (mb->get_button_index() == MouseButton::LEFT && input_action != INPUT_NONE) { set_items.clear(); input_action = INPUT_NONE; return EditorPlugin::AFTER_GUI_INPUT_STOP; } - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_PASTE)) { + if (mb->get_button_index() == MouseButton::RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_PASTE)) { input_action = INPUT_NONE; return EditorPlugin::AFTER_GUI_INPUT_STOP; } @@ -719,7 +719,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D if (k.is_valid()) { if (k->is_pressed()) { - if (k->get_keycode() == KEY_ESCAPE) { + if (k->get_keycode() == Key::ESCAPE) { if (input_action == INPUT_PASTE) { _clear_clipboard_data(); input_action = INPUT_NONE; @@ -738,12 +738,12 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D } if (k->is_shift_pressed() && selection.active && input_action != INPUT_PASTE) { - if (k->get_keycode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) { + if (k->get_keycode() == (Key)options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) { selection.click[edit_axis]--; _validate_selection(); return EditorPlugin::AFTER_GUI_INPUT_STOP; } - if (k->get_keycode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL))) { + if (k->get_keycode() == (Key)options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL))) { selection.click[edit_axis]++; _validate_selection(); return EditorPlugin::AFTER_GUI_INPUT_STOP; @@ -759,7 +759,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D accumulated_floor_delta += delta; int step = 0; if (ABS(accumulated_floor_delta) > 1.0) { - step = SGN(accumulated_floor_delta); + step = SIGN(accumulated_floor_delta); accumulated_floor_delta -= step; } if (step) { @@ -804,7 +804,7 @@ void GridMapEditor::_text_changed(const String &p_text) { void GridMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) { const Ref<InputEventKey> k = p_ie; - if (k.is_valid() && (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_PAGEUP || k->get_keycode() == KEY_PAGEDOWN)) { + if (k.is_valid() && (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::PAGEUP || k->get_keycode() == Key::PAGEDOWN)) { // Forward the key input to the ItemList so it can be scrolled mesh_library_palette->gui_input(k); search_box->accept_event(); @@ -816,11 +816,11 @@ void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) { // Zoom in/out using Ctrl + mouse wheel if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed()) { - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { size_slider->set_value(size_slider->get_value() + 0.2); } - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { size_slider->set_value(size_slider->get_value() - 0.2); } } @@ -1097,7 +1097,7 @@ void GridMapEditor::_notification(int p_what) { // Simulate mouse released event to stop drawing when editor focus exists. Ref<InputEventMouseButton> release; release.instantiate(); - release->set_button_index(MOUSE_BUTTON_LEFT); + release->set_button_index(MouseButton::LEFT); forward_spatial_input_event(nullptr, release); } } break; @@ -1188,33 +1188,33 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { spatial_editor_hb->hide(); options->set_text(TTR("Grid Map")); - options->get_popup()->add_item(TTR("Previous Floor"), MENU_OPTION_PREV_LEVEL, KEY_Q); - options->get_popup()->add_item(TTR("Next Floor"), MENU_OPTION_NEXT_LEVEL, KEY_E); + options->get_popup()->add_item(TTR("Previous Floor"), MENU_OPTION_PREV_LEVEL, Key::Q); + options->get_popup()->add_item(TTR("Next Floor"), MENU_OPTION_NEXT_LEVEL, Key::E); options->get_popup()->add_separator(); options->get_popup()->add_radio_check_item(TTR("Clip Disabled"), MENU_OPTION_CLIP_DISABLED); options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_CLIP_DISABLED), true); options->get_popup()->add_radio_check_item(TTR("Clip Above"), MENU_OPTION_CLIP_ABOVE); options->get_popup()->add_radio_check_item(TTR("Clip Below"), MENU_OPTION_CLIP_BELOW); options->get_popup()->add_separator(); - options->get_popup()->add_radio_check_item(TTR("Edit X Axis"), MENU_OPTION_X_AXIS, KEY_Z); - options->get_popup()->add_radio_check_item(TTR("Edit Y Axis"), MENU_OPTION_Y_AXIS, KEY_X); - options->get_popup()->add_radio_check_item(TTR("Edit Z Axis"), MENU_OPTION_Z_AXIS, KEY_C); + options->get_popup()->add_radio_check_item(TTR("Edit X Axis"), MENU_OPTION_X_AXIS, Key::Z); + options->get_popup()->add_radio_check_item(TTR("Edit Y Axis"), MENU_OPTION_Y_AXIS, Key::X); + options->get_popup()->add_radio_check_item(TTR("Edit Z Axis"), MENU_OPTION_Z_AXIS, Key::C); options->get_popup()->set_item_checked(options->get_popup()->get_item_index(MENU_OPTION_Y_AXIS), true); options->get_popup()->add_separator(); - options->get_popup()->add_item(TTR("Cursor Rotate X"), MENU_OPTION_CURSOR_ROTATE_X, KEY_A); - options->get_popup()->add_item(TTR("Cursor Rotate Y"), MENU_OPTION_CURSOR_ROTATE_Y, KEY_S); - options->get_popup()->add_item(TTR("Cursor Rotate Z"), MENU_OPTION_CURSOR_ROTATE_Z, KEY_D); - options->get_popup()->add_item(TTR("Cursor Back Rotate X"), MENU_OPTION_CURSOR_BACK_ROTATE_X, KEY_MASK_SHIFT + KEY_A); - options->get_popup()->add_item(TTR("Cursor Back Rotate Y"), MENU_OPTION_CURSOR_BACK_ROTATE_Y, KEY_MASK_SHIFT + KEY_S); - options->get_popup()->add_item(TTR("Cursor Back Rotate Z"), MENU_OPTION_CURSOR_BACK_ROTATE_Z, KEY_MASK_SHIFT + KEY_D); - options->get_popup()->add_item(TTR("Cursor Clear Rotation"), MENU_OPTION_CURSOR_CLEAR_ROTATION, KEY_W); + options->get_popup()->add_item(TTR("Cursor Rotate X"), MENU_OPTION_CURSOR_ROTATE_X, Key::A); + options->get_popup()->add_item(TTR("Cursor Rotate Y"), MENU_OPTION_CURSOR_ROTATE_Y, Key::S); + options->get_popup()->add_item(TTR("Cursor Rotate Z"), MENU_OPTION_CURSOR_ROTATE_Z, Key::D); + options->get_popup()->add_item(TTR("Cursor Back Rotate X"), MENU_OPTION_CURSOR_BACK_ROTATE_X, KeyModifierMask::SHIFT + Key::A); + options->get_popup()->add_item(TTR("Cursor Back Rotate Y"), MENU_OPTION_CURSOR_BACK_ROTATE_Y, KeyModifierMask::SHIFT + Key::S); + options->get_popup()->add_item(TTR("Cursor Back Rotate Z"), MENU_OPTION_CURSOR_BACK_ROTATE_Z, KeyModifierMask::SHIFT + Key::D); + options->get_popup()->add_item(TTR("Cursor Clear Rotation"), MENU_OPTION_CURSOR_CLEAR_ROTATION, Key::W); options->get_popup()->add_separator(); options->get_popup()->add_check_item(TTR("Paste Selects"), MENU_OPTION_PASTE_SELECTS); options->get_popup()->add_separator(); - options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KEY_MASK_CTRL + KEY_C); - options->get_popup()->add_item(TTR("Cut Selection"), MENU_OPTION_SELECTION_CUT, KEY_MASK_CTRL + KEY_X); - options->get_popup()->add_item(TTR("Clear Selection"), MENU_OPTION_SELECTION_CLEAR, KEY_DELETE); - options->get_popup()->add_item(TTR("Fill Selection"), MENU_OPTION_SELECTION_FILL, KEY_MASK_CTRL + KEY_F); + options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KeyModifierMask::CTRL + Key::C); + options->get_popup()->add_item(TTR("Cut Selection"), MENU_OPTION_SELECTION_CUT, KeyModifierMask::CTRL + Key::X); + options->get_popup()->add_item(TTR("Clear Selection"), MENU_OPTION_SELECTION_CLEAR, Key::KEY_DELETE); + options->get_popup()->add_item(TTR("Fill Selection"), MENU_OPTION_SELECTION_FILL, KeyModifierMask::CTRL + Key::F); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Settings..."), MENU_OPTION_GRIDMAP_SETTINGS); diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp index dc360c12ba..b2a755e23b 100644 --- a/modules/minimp3/resource_importer_mp3.cpp +++ b/modules/minimp3/resource_importer_mp3.cpp @@ -54,7 +54,7 @@ String ResourceImporterMP3::get_resource_type() const { return "AudioStreamMP3"; } -bool ResourceImporterMP3::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterMP3::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -66,7 +66,7 @@ String ResourceImporterMP3::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterMP3::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterMP3::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); } diff --git a/modules/minimp3/resource_importer_mp3.h b/modules/minimp3/resource_importer_mp3.h index 71b51887a2..356ec77d22 100644 --- a/modules/minimp3/resource_importer_mp3.h +++ b/modules/minimp3/resource_importer_mp3.h @@ -47,8 +47,8 @@ public: virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index d9b291489b..544f2a7584 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1355,7 +1355,7 @@ void CSharpLanguage::_editor_init_callback() { // Enable it as a plugin EditorNode::add_editor_plugin(godotsharp_editor); - ED_SHORTCUT("mono/build_solution", TTR("Build Solution"), KEY_MASK_ALT | KEY_B); + ED_SHORTCUT("mono/build_solution", TTR("Build Solution"), KeyModifierMask::ALT | Key::B); godotsharp_editor->enable_plugin(); get_singleton()->godotsharp_editor = godotsharp_editor; diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml index 2bca8bc24e..14c62b4bb0 100644 --- a/modules/mono/doc_classes/CSharpScript.xml +++ b/modules/mono/doc_classes/CSharpScript.xml @@ -8,7 +8,7 @@ See also [GodotSharp]. </description> <tutorials> - <link title="C# documentation index">https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/index.html</link> + <link title="C# documentation index">$DOCS_URL/tutorials/scripting/c_sharp/index.html</link> </tutorials> <methods> <method name="new" qualifiers="vararg"> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs index 70a2cf5695..850ae7fc3b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs @@ -666,21 +666,40 @@ namespace Godot _size = new Vector3(width, height, depth); } + /// <summary> + /// Returns <see langword="true"/> if the AABBs are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left AABB.</param> + /// <param name="right">The right AABB.</param> + /// <returns>Whether or not the AABBs are exactly equal.</returns> public static bool operator ==(AABB left, AABB right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the AABBs are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left AABB.</param> + /// <param name="right">The right AABB.</param> + /// <returns>Whether or not the AABBs are not equal.</returns> public static bool operator !=(AABB left, AABB right) { return !left.Equals(right); } /// <summary> - /// Returns <see langword="true"/> if this AABB and <paramref name="obj"/> are equal. + /// Returns <see langword="true"/> if the AABB is exactly equal + /// to the given object (<see paramref="obj"/>). + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the AABB structure and the other object are equal.</returns> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the AABB and the object are equal.</returns> public override bool Equals(object obj) { if (obj is AABB) @@ -692,10 +711,12 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this AABB and <paramref name="other"/> are equal + /// Returns <see langword="true"/> if the AABBs are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="other">The other AABB to compare.</param> - /// <returns>Whether or not the AABBs are equal.</returns> + /// <param name="other">The other AABB.</param> + /// <returns>Whether or not the AABBs are exactly equal.</returns> public bool Equals(AABB other) { return _position == other._position && _size == other._size; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 0fb1df6c2f..bfbf1a097e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -827,6 +827,14 @@ namespace Godot Row2 = new Vector3(xz, yz, zz); } + /// <summary> + /// Composes these two basis matrices by multiplying them + /// together. This has the effect of transforming the second basis + /// (the child) by the first basis (the parent). + /// </summary> + /// <param name="left">The parent basis.</param> + /// <param name="right">The child basis.</param> + /// <returns>The composed basis.</returns> public static Basis operator *(Basis left, Basis right) { return new Basis @@ -837,21 +845,40 @@ namespace Godot ); } + /// <summary> + /// Returns <see langword="true"/> if the basis matrices are exactly + /// equal. Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left basis.</param> + /// <param name="right">The right basis.</param> + /// <returns>Whether or not the basis matrices are exactly equal.</returns> public static bool operator ==(Basis left, Basis right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the basis matrices are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left basis.</param> + /// <param name="right">The right basis.</param> + /// <returns>Whether or not the basis matrices are not equal.</returns> public static bool operator !=(Basis left, Basis right) { return !left.Equals(right); } /// <summary> - /// Returns <see langword="true"/> if this basis and <paramref name="obj"/> are equal. + /// Returns <see langword="true"/> if the <see cref="Basis"/> is + /// exactly equal to the given object (<see paramref="obj"/>). + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the basis and the other object are equal.</returns> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the basis matrix and the object are exactly equal.</returns> public override bool Equals(object obj) { if (obj is Basis) @@ -863,10 +890,12 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this basis and <paramref name="other"/> are equal + /// Returns <see langword="true"/> if the basis matrices are exactly + /// equal. Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="other">The other basis to compare.</param> - /// <returns>Whether or not the bases are equal.</returns> + /// <param name="other">The other basis.</param> + /// <returns>Whether or not the basis matrices are exactly equal.</returns> public bool Equals(Basis other) { return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index 2a869bc335..fc9d40ca48 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -878,6 +878,13 @@ namespace Godot return true; } + /// <summary> + /// Adds each component of the <see cref="Color"/> + /// with the components of the given <see cref="Color"/>. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>The added color.</returns> public static Color operator +(Color left, Color right) { left.r += right.r; @@ -887,6 +894,13 @@ namespace Godot return left; } + /// <summary> + /// Subtracts each component of the <see cref="Color"/> + /// by the components of the given <see cref="Color"/>. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>The subtracted color.</returns> public static Color operator -(Color left, Color right) { left.r -= right.r; @@ -896,11 +910,25 @@ namespace Godot return left; } + /// <summary> + /// Inverts the given color. This is equivalent to + /// <c>Colors.White - c</c> or + /// <c>new Color(1 - c.r, 1 - c.g, 1 - c.b, 1 - c.a)</c>. + /// </summary> + /// <param name="color">The color to invert.</param> + /// <returns>The inverted color</returns> public static Color operator -(Color color) { return Colors.White - color; } + /// <summary> + /// Multiplies each component of the <see cref="Color"/> + /// by the given <see langword="float"/>. + /// </summary> + /// <param name="color">The color to multiply.</param> + /// <param name="scale">The value to multiply by.</param> + /// <returns>The multiplied color.</returns> public static Color operator *(Color color, float scale) { color.r *= scale; @@ -910,6 +938,13 @@ namespace Godot return color; } + /// <summary> + /// Multiplies each component of the <see cref="Color"/> + /// by the given <see langword="float"/>. + /// </summary> + /// <param name="scale">The value to multiply by.</param> + /// <param name="color">The color to multiply.</param> + /// <returns>The multiplied color.</returns> public static Color operator *(float scale, Color color) { color.r *= scale; @@ -919,6 +954,13 @@ namespace Godot return color; } + /// <summary> + /// Multiplies each component of the <see cref="Color"/> + /// by the components of the given <see cref="Color"/>. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>The multiplied color.</returns> public static Color operator *(Color left, Color right) { left.r *= right.r; @@ -928,6 +970,13 @@ namespace Godot return left; } + /// <summary> + /// Divides each component of the <see cref="Color"/> + /// by the given <see langword="float"/>. + /// </summary> + /// <param name="color">The dividend vector.</param> + /// <param name="scale">The divisor value.</param> + /// <returns>The divided color.</returns> public static Color operator /(Color color, float scale) { color.r /= scale; @@ -937,6 +986,13 @@ namespace Godot return color; } + /// <summary> + /// Divides each component of the <see cref="Color"/> + /// by the components of the given <see cref="Color"/>. + /// </summary> + /// <param name="left">The dividend color.</param> + /// <param name="right">The divisor color.</param> + /// <returns>The divided color.</returns> public static Color operator /(Color left, Color right) { left.r /= right.r; @@ -946,23 +1002,51 @@ namespace Godot return left; } + /// <summary> + /// Returns <see langword="true"/> if the colors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>Whether or not the colors are equal.</returns> public static bool operator ==(Color left, Color right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the colors are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>Whether or not the colors are equal.</returns> public static bool operator !=(Color left, Color right) { return !left.Equals(right); } + /// <summary> + /// Compares two <see cref="Color"/>s by first checking if + /// the red value of the <paramref name="left"/> color is less than + /// the red value of the <paramref name="right"/> color. + /// If the red values are exactly equal, then it repeats this check + /// with the green values of the two colors, then with the blue values, + /// and then with the alpha value. + /// This operator is useful for sorting colors. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>Whether or not the left is less than the right.</returns> public static bool operator <(Color left, Color right) { - if (Mathf.IsEqualApprox(left.r, right.r)) + if (left.r == right.r) { - if (Mathf.IsEqualApprox(left.g, right.g)) + if (left.g == right.g) { - if (Mathf.IsEqualApprox(left.b, right.b)) + if (left.b == right.b) { return left.a < right.a; } @@ -973,13 +1057,25 @@ namespace Godot return left.r < right.r; } + /// <summary> + /// Compares two <see cref="Color"/>s by first checking if + /// the red value of the <paramref name="left"/> color is greater than + /// the red value of the <paramref name="right"/> color. + /// If the red values are exactly equal, then it repeats this check + /// with the green values of the two colors, then with the blue values, + /// and then with the alpha value. + /// This operator is useful for sorting colors. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>Whether or not the left is greater than the right.</returns> public static bool operator >(Color left, Color right) { - if (Mathf.IsEqualApprox(left.r, right.r)) + if (left.r == right.r) { - if (Mathf.IsEqualApprox(left.g, right.g)) + if (left.g == right.g) { - if (Mathf.IsEqualApprox(left.b, right.b)) + if (left.b == right.b) { return left.a > right.a; } @@ -991,6 +1087,64 @@ namespace Godot } /// <summary> + /// Compares two <see cref="Color"/>s by first checking if + /// the red value of the <paramref name="left"/> color is less than + /// or equal to the red value of the <paramref name="right"/> color. + /// If the red values are exactly equal, then it repeats this check + /// with the green values of the two colors, then with the blue values, + /// and then with the alpha value. + /// This operator is useful for sorting colors. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> + public static bool operator <=(Color left, Color right) + { + if (left.r == right.r) + { + if (left.g == right.g) + { + if (left.b == right.b) + { + return left.a <= right.a; + } + return left.b < right.b; + } + return left.g < right.g; + } + return left.r < right.r; + } + + /// <summary> + /// Compares two <see cref="Color"/>s by first checking if + /// the red value of the <paramref name="left"/> color is greater than + /// or equal to the red value of the <paramref name="right"/> color. + /// If the red values are exactly equal, then it repeats this check + /// with the green values of the two colors, then with the blue values, + /// and then with the alpha value. + /// This operator is useful for sorting colors. + /// </summary> + /// <param name="left">The left color.</param> + /// <param name="right">The right color.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> + public static bool operator >=(Color left, Color right) + { + if (left.r == right.r) + { + if (left.g == right.g) + { + if (left.b == right.b) + { + return left.a >= right.a; + } + return left.b > right.b; + } + return left.g > right.g; + } + return left.r > right.r; + } + + /// <summary> /// Returns <see langword="true"/> if this color and <paramref name="obj"/> are equal. /// </summary> /// <param name="obj">The other object to compare.</param> @@ -1006,9 +1160,11 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this color and <paramref name="other"/> are equal + /// Returns <see langword="true"/> if the colors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="other">The other color to compare.</param> + /// <param name="other">The other color.</param> /// <returns>Whether or not the colors are equal.</returns> public bool Equals(Color other) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs index d64c8b563e..68c821b447 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs @@ -158,6 +158,7 @@ namespace Godot {"YELLOWGREEN", new Color(0.60f, 0.80f, 0.20f)}, }; +#pragma warning disable CS1591 // Disable warning: "Missing XML comment for publicly visible type or member" public static Color AliceBlue { get { return namedColors["ALICEBLUE"]; } } public static Color AntiqueWhite { get { return namedColors["ANTIQUEWHITE"]; } } public static Color Aqua { get { return namedColors["AQUA"]; } } @@ -304,5 +305,6 @@ namespace Godot public static Color WhiteSmoke { get { return namedColors["WHITESMOKE"]; } } public static Color Yellow { get { return namedColors["YELLOW"]; } } public static Color YellowGreen { get { return namedColors["YELLOWGREEN"]; } } +#pragma warning restore CS1591 } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs index 2dfe304aaa..75240b0c09 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs @@ -314,13 +314,13 @@ namespace Godot.Collections internal static extern int godot_icall_Dictionary_Count(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static int godot_icall_Dictionary_KeyValuePairs(IntPtr ptr, out IntPtr keys, out IntPtr values); + internal static extern int godot_icall_Dictionary_KeyValuePairs(IntPtr ptr, out IntPtr keys, out IntPtr values); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value); + internal static extern void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value); + internal static extern void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void godot_icall_Dictionary_Clear(IntPtr ptr); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs index ef42374041..a3afc83222 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs @@ -323,6 +323,16 @@ namespace Godot } /// <summary> + /// Returns a normally-distributed pseudo-random number, using Box-Muller transform with the specified <c>mean</c> and a standard <c>deviation</c>. + /// This is also called Gaussian distribution. + /// </summary> + /// <returns>A random normally-distributed <see langword="float"/> number.</returns> + public static double Randfn(double mean, double deviation) + { + return godot_icall_GD_randfn(mean, deviation); + } + + /// <summary> /// Returns a random unsigned 32-bit integer. /// Use remainder to obtain a random value in the interval <c>[0, N - 1]</c> (where N is smaller than 2^32). /// </summary> @@ -564,19 +574,22 @@ namespace Godot internal static extern void godot_icall_GD_printt(object[] what); [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern float godot_icall_GD_randf(); + internal static extern void godot_icall_GD_randomize(); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern uint godot_icall_GD_randi(); [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_GD_randomize(); + internal static extern float godot_icall_GD_randf(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern int godot_icall_GD_randi_range(int from, int to); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern double godot_icall_GD_randf_range(double from, double to); [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int godot_icall_GD_randi_range(int from, int to); + internal static extern double godot_icall_GD_randfn(double mean, double deviation); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index 6f7fac7429..fbc8ff64a6 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -693,5 +693,23 @@ namespace Godot } return min + ((((value - min) % range) + range) % range); } + + private static real_t Fract(real_t value) + { + return value - (real_t)Math.Floor(value); + } + + /// <summary> + /// Returns the [code]value[/code] wrapped between [code]0[/code] and the [code]length[/code]. + /// If the limit is reached, the next value the function returned is decreased to the [code]0[/code] side or increased to the [code]length[/code] side (like a triangle wave). + /// If [code]length[/code] is less than zero, it becomes positive. + /// </summary> + /// <param name="value">The value to pingpong.</param> + /// <param name="length">The maximum value of the function.</param> + /// <returns>The ping-ponged value.</returns> + public static real_t PingPong(real_t value, real_t length) + { + return (length != (real_t)0.0) ? Abs(Fract((value - length) / (length * (real_t)2.0)) * length * (real_t)2.0 - length) : (real_t)0.0; + } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 66f7b745f7..63af1c5892 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -309,16 +309,43 @@ namespace Godot D = _normal.Dot(v1); } + /// <summary> + /// Returns the negative value of the <see cref="Plane"/>. + /// This is the same as writing <c>new Plane(-p.Normal, -p.D)</c>. + /// This operation flips the direction of the normal vector and + /// also flips the distance value, resulting in a Plane that is + /// in the same place, but facing the opposite direction. + /// </summary> + /// <param name="plane">The plane to negate/flip.</param> + /// <returns>The negated/flipped plane.</returns> public static Plane operator -(Plane plane) { return new Plane(-plane._normal, -plane.D); } + /// <summary> + /// Returns <see langword="true"/> if the + /// <see cref="Plane"/>s are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left rect.</param> + /// <param name="right">The right rect.</param> + /// <returns>Whether or not the planes are exactly equal.</returns> public static bool operator ==(Plane left, Plane right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the + /// <see cref="Plane"/>s are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left rect.</param> + /// <param name="right">The right rect.</param> + /// <returns>Whether or not the planes are not equal.</returns> public static bool operator !=(Plane left, Plane right) { return !left.Equals(right); @@ -328,7 +355,7 @@ namespace Godot /// Returns <see langword="true"/> if this plane and <paramref name="obj"/> are equal. /// </summary> /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the plane and the other object are equal.</returns> + /// <returns>Whether or not the plane and the other object are exactly equal.</returns> public override bool Equals(object obj) { if (obj is Plane) @@ -343,7 +370,7 @@ namespace Godot /// Returns <see langword="true"/> if this plane and <paramref name="other"/> are equal. /// </summary> /// <param name="other">The other plane to compare.</param> - /// <returns>Whether or not the planes are equal.</returns> + /// <returns>Whether or not the planes are exactly equal.</returns> public bool Equals(Plane other) { return _normal == other._normal && D == other.D; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs index c18f818ed2..dfb8e87bce 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs @@ -446,6 +446,14 @@ namespace Godot } } + /// <summary> + /// Composes these two quaternions by multiplying them together. + /// This has the effect of rotating the second quaternion + /// (the child) by the first quaternion (the parent). + /// </summary> + /// <param name="left">The parent quaternion.</param> + /// <param name="right">The child quaternion.</param> + /// <returns>The composed quaternion.</returns> public static Quaternion operator *(Quaternion left, Quaternion right) { return new Quaternion @@ -457,21 +465,55 @@ namespace Godot ); } + /// <summary> + /// Adds each component of the left <see cref="Quaternion"/> + /// to the right <see cref="Quaternion"/>. This operation is not + /// meaningful on its own, but it can be used as a part of a + /// larger expression, such as approximating an intermediate + /// rotation between two nearby rotations. + /// </summary> + /// <param name="left">The left quaternion to add.</param> + /// <param name="right">The right quaternion to add.</param> + /// <returns>The added quaternion.</returns> public static Quaternion operator +(Quaternion left, Quaternion right) { return new Quaternion(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w); } + /// <summary> + /// Subtracts each component of the left <see cref="Quaternion"/> + /// by the right <see cref="Quaternion"/>. This operation is not + /// meaningful on its own, but it can be used as a part of a + /// larger expression. + /// </summary> + /// <param name="left">The left quaternion to subtract.</param> + /// <param name="right">The right quaternion to subtract.</param> + /// <returns>The subtracted quaternion.</returns> public static Quaternion operator -(Quaternion left, Quaternion right) { return new Quaternion(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w); } - public static Quaternion operator -(Quaternion left) + /// <summary> + /// Returns the negative value of the <see cref="Quaternion"/>. + /// This is the same as writing + /// <c>new Quaternion(-q.x, -q.y, -q.z, -q.w)</c>. This operation + /// results in a quaternion that represents the same rotation. + /// </summary> + /// <param name="quat">The quaternion to negate.</param> + /// <returns>The negated quaternion.</returns> + public static Quaternion operator -(Quaternion quat) { - return new Quaternion(-left.x, -left.y, -left.z, -left.w); + return new Quaternion(-quat.x, -quat.y, -quat.z, -quat.w); } + /// <summary> + /// Rotates (multiplies) the <see cref="Vector3"/> + /// by the given <see cref="Quaternion"/>. + /// </summary> + /// <param name="quat">The quaternion to rotate by.</param> + /// <param name="vec">The vector to rotate.</param> + /// <returns>The rotated vector.</returns> public static Vector3 operator *(Quaternion quat, Vector3 vec) { #if DEBUG @@ -485,31 +527,81 @@ namespace Godot return vec + (((uv * quat.w) + u.Cross(uv)) * 2); } + /// <summary> + /// Inversely rotates (multiplies) the <see cref="Vector3"/> + /// by the given <see cref="Quaternion"/>. + /// </summary> + /// <param name="vec">The vector to rotate.</param> + /// <param name="quat">The quaternion to rotate by.</param> + /// <returns>The inversely rotated vector.</returns> public static Vector3 operator *(Vector3 vec, Quaternion quat) { return quat.Inverse() * vec; } + /// <summary> + /// Multiplies each component of the <see cref="Quaternion"/> + /// by the given <see cref="real_t"/>. This operation is not + /// meaningful on its own, but it can be used as a part of a + /// larger expression. + /// </summary> + /// <param name="left">The quaternion to multiply.</param> + /// <param name="right">The value to multiply by.</param> + /// <returns>The multiplied quaternion.</returns> public static Quaternion operator *(Quaternion left, real_t right) { return new Quaternion(left.x * right, left.y * right, left.z * right, left.w * right); } + /// <summary> + /// Multiplies each component of the <see cref="Quaternion"/> + /// by the given <see cref="real_t"/>. This operation is not + /// meaningful on its own, but it can be used as a part of a + /// larger expression. + /// </summary> + /// <param name="left">The value to multiply by.</param> + /// <param name="right">The quaternion to multiply.</param> + /// <returns>The multiplied quaternion.</returns> public static Quaternion operator *(real_t left, Quaternion right) { return new Quaternion(right.x * left, right.y * left, right.z * left, right.w * left); } + /// <summary> + /// Divides each component of the <see cref="Quaternion"/> + /// by the given <see cref="real_t"/>. This operation is not + /// meaningful on its own, but it can be used as a part of a + /// larger expression. + /// </summary> + /// <param name="left">The quaternion to divide.</param> + /// <param name="right">The value to divide by.</param> + /// <returns>The divided quaternion.</returns> public static Quaternion operator /(Quaternion left, real_t right) { return left * (1.0f / right); } + /// <summary> + /// Returns <see langword="true"/> if the quaternions are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left quaternion.</param> + /// <param name="right">The right quaternion.</param> + /// <returns>Whether or not the quaternions are exactly equal.</returns> public static bool operator ==(Quaternion left, Quaternion right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the quaternions are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left quaternion.</param> + /// <param name="right">The right quaternion.</param> + /// <returns>Whether or not the quaternions are not equal.</returns> public static bool operator !=(Quaternion left, Quaternion right) { return !left.Equals(right); @@ -519,7 +611,7 @@ namespace Godot /// Returns <see langword="true"/> if this quaternion and <paramref name="obj"/> are equal. /// </summary> /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the quaternion and the other object are equal.</returns> + /// <returns>Whether or not the quaternion and the other object are exactly equal.</returns> public override bool Equals(object obj) { if (obj is Quaternion) @@ -534,7 +626,7 @@ namespace Godot /// Returns <see langword="true"/> if this quaternion and <paramref name="other"/> are equal. /// </summary> /// <param name="other">The other quaternion to compare.</param> - /// <returns>Whether or not the quaternions are equal.</returns> + /// <returns>Whether or not the quaternions are exactly equal.</returns> public bool Equals(Quaternion other) { return x == other.x && y == other.y && z == other.z && w == other.w; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs index af94484577..ec16920fed 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs @@ -396,11 +396,29 @@ namespace Godot _size = new Vector2(width, height); } + /// <summary> + /// Returns <see langword="true"/> if the + /// <see cref="Rect2"/>s are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left rect.</param> + /// <param name="right">The right rect.</param> + /// <returns>Whether or not the rects are exactly equal.</returns> public static bool operator ==(Rect2 left, Rect2 right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the + /// <see cref="Rect2"/>s are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left rect.</param> + /// <param name="right">The right rect.</param> + /// <returns>Whether or not the rects are not equal.</returns> public static bool operator !=(Rect2 left, Rect2 right) { return !left.Equals(right); @@ -410,7 +428,7 @@ namespace Godot /// Returns <see langword="true"/> if this rect and <paramref name="obj"/> are equal. /// </summary> /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the rect and the other object are equal.</returns> + /// <returns>Whether or not the rect and the other object are exactly equal.</returns> public override bool Equals(object obj) { if (obj is Rect2) @@ -425,7 +443,7 @@ namespace Godot /// Returns <see langword="true"/> if this rect and <paramref name="other"/> are equal. /// </summary> /// <param name="other">The other rect to compare.</param> - /// <returns>Whether or not the rects are equal.</returns> + /// <returns>Whether or not the rects are exactly equal.</returns> public bool Equals(Rect2 other) { return _position.Equals(other._position) && _size.Equals(other._size); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs index 03f406a910..5d53b8330e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs @@ -377,11 +377,25 @@ namespace Godot _size = new Vector2i(width, height); } + /// <summary> + /// Returns <see langword="true"/> if the + /// <see cref="Rect2i"/>s are exactly equal. + /// </summary> + /// <param name="left">The left rect.</param> + /// <param name="right">The right rect.</param> + /// <returns>Whether or not the rects are equal.</returns> public static bool operator ==(Rect2i left, Rect2i right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the + /// <see cref="Rect2i"/>s are not equal. + /// </summary> + /// <param name="left">The left rect.</param> + /// <param name="right">The right rect.</param> + /// <returns>Whether or not the rects are not equal.</returns> public static bool operator !=(Rect2i left, Rect2i right) { return !left.Equals(right); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index 6b3eb09581..d9ee684c5b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -1345,7 +1345,7 @@ namespace Godot } [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static string godot_icall_String_simplify_path(string str); + internal static extern string godot_icall_String_simplify_path(string str); /// <summary> /// Split the string by a divisor string, return an array of the substrings. diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index c82c5f4588..6f1d9574a8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -447,6 +447,14 @@ namespace Godot this.origin = origin; } + /// <summary> + /// Composes these two transformation matrices by multiplying them + /// together. This has the effect of transforming the second transform + /// (the child) by the first transform (the parent). + /// </summary> + /// <param name="left">The parent transform.</param> + /// <param name="right">The child transform.</param> + /// <returns>The composed transform.</returns> public static Transform2D operator *(Transform2D left, Transform2D right) { left.origin = left * right.origin; @@ -554,31 +562,52 @@ namespace Godot return newArray; } + /// <summary> + /// Returns <see langword="true"/> if the transforms are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left transform.</param> + /// <param name="right">The right transform.</param> + /// <returns>Whether or not the transforms are exactly equal.</returns> public static bool operator ==(Transform2D left, Transform2D right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the transforms are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left transform.</param> + /// <param name="right">The right transform.</param> + /// <returns>Whether or not the transforms are not equal.</returns> public static bool operator !=(Transform2D left, Transform2D right) { return !left.Equals(right); } /// <summary> - /// Returns <see langword="true"/> if this transform and <paramref name="obj"/> are equal. + /// Returns <see langword="true"/> if the transform is exactly equal + /// to the given object (<see paramref="obj"/>). + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the transform and the other object are equal.</returns> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the transform and the object are exactly equal.</returns> public override bool Equals(object obj) { return obj is Transform2D transform2D && Equals(transform2D); } /// <summary> - /// Returns <see langword="true"/> if this transform and <paramref name="other"/> are equal. + /// Returns <see langword="true"/> if the transforms are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> /// <param name="other">The other transform to compare.</param> - /// <returns>Whether or not the matrices are equal.</returns> + /// <returns>Whether or not the matrices are exactly equal.</returns> public bool Equals(Transform2D other) { return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 7176cd60dc..4bb8308c12 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -352,6 +352,14 @@ namespace Godot this.origin = origin; } + /// <summary> + /// Composes these two transformation matrices by multiplying them + /// together. This has the effect of transforming the second transform + /// (the child) by the first transform (the parent). + /// </summary> + /// <param name="left">The parent transform.</param> + /// <param name="right">The child transform.</param> + /// <returns>The composed transform.</returns> public static Transform3D operator *(Transform3D left, Transform3D right) { left.origin = left.Xform(right.origin); @@ -359,21 +367,40 @@ namespace Godot return left; } + /// <summary> + /// Returns <see langword="true"/> if the transforms are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left transform.</param> + /// <param name="right">The right transform.</param> + /// <returns>Whether or not the transforms are exactly equal.</returns> public static bool operator ==(Transform3D left, Transform3D right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the transforms are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left transform.</param> + /// <param name="right">The right transform.</param> + /// <returns>Whether or not the transforms are not equal.</returns> public static bool operator !=(Transform3D left, Transform3D right) { return !left.Equals(right); } /// <summary> - /// Returns <see langword="true"/> if this transform and <paramref name="obj"/> are equal. + /// Returns <see langword="true"/> if the transform is exactly equal + /// to the given object (<see paramref="obj"/>). + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the transform and the other object are equal.</returns> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the transform and the object are exactly equal.</returns> public override bool Equals(object obj) { if (obj is Transform3D) @@ -385,10 +412,12 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this transform and <paramref name="other"/> are equal. + /// Returns <see langword="true"/> if the transforms are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> /// <param name="other">The other transform to compare.</param> - /// <returns>Whether or not the matrices are equal.</returns> + /// <returns>Whether or not the matrices are exactly equal.</returns> public bool Equals(Transform3D other) { return basis.Equals(other.basis) && origin.Equals(other.origin); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index fe70d71cce..0c3331900a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -642,6 +642,13 @@ namespace Godot return new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); } + /// <summary> + /// Adds each component of the <see cref="Vector2"/> + /// with the components of the given <see cref="Vector2"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The added vector.</returns> public static Vector2 operator +(Vector2 left, Vector2 right) { left.x += right.x; @@ -649,6 +656,13 @@ namespace Godot return left; } + /// <summary> + /// Subtracts each component of the <see cref="Vector2"/> + /// by the components of the given <see cref="Vector2"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The subtracted vector.</returns> public static Vector2 operator -(Vector2 left, Vector2 right) { left.x -= right.x; @@ -656,6 +670,15 @@ namespace Godot return left; } + /// <summary> + /// Returns the negative value of the <see cref="Vector2"/>. + /// This is the same as writing <c>new Vector2(-v.x, -v.y)</c>. + /// This operation flips the direction of the vector while + /// keeping the same magnitude. + /// With floats, the number zero can be either positive or negative. + /// </summary> + /// <param name="vec">The vector to negate/flip.</param> + /// <returns>The negated/flipped vector.</returns> public static Vector2 operator -(Vector2 vec) { vec.x = -vec.x; @@ -663,6 +686,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector2"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="vec">The vector to multiply.</param> + /// <param name="scale">The scale to multiply by.</param> + /// <returns>The multiplied vector.</returns> public static Vector2 operator *(Vector2 vec, real_t scale) { vec.x *= scale; @@ -670,6 +700,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector2"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="scale">The scale to multiply by.</param> + /// <param name="vec">The vector to multiply.</param> + /// <returns>The multiplied vector.</returns> public static Vector2 operator *(real_t scale, Vector2 vec) { vec.x *= scale; @@ -677,6 +714,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector2"/> + /// by the components of the given <see cref="Vector2"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The multiplied vector.</returns> public static Vector2 operator *(Vector2 left, Vector2 right) { left.x *= right.x; @@ -684,6 +728,13 @@ namespace Godot return left; } + /// <summary> + /// Multiplies each component of the <see cref="Vector2"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The divided vector.</returns> public static Vector2 operator /(Vector2 vec, real_t divisor) { vec.x /= divisor; @@ -691,6 +742,13 @@ namespace Godot return vec; } + /// <summary> + /// Divides each component of the <see cref="Vector2"/> + /// by the components of the given <see cref="Vector2"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The divided vector.</returns> public static Vector2 operator /(Vector2 vec, Vector2 divisorv) { vec.x /= divisorv.x; @@ -698,6 +756,22 @@ namespace Godot return vec; } + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector2"/> + /// with the components of the given <see cref="real_t"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// Consider using <see cref="PosMod(real_t)"/> instead + /// if you want to handle negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector2(10, -20) % 7); // Prints "(3, -6)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The remainder vector.</returns> public static Vector2 operator %(Vector2 vec, real_t divisor) { vec.x %= divisor; @@ -705,6 +779,22 @@ namespace Godot return vec; } + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector2"/> + /// with the components of the given <see cref="Vector2"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// Consider using <see cref="PosMod(Vector2)"/> instead + /// if you want to handle negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector2(10, -20) % new Vector2(7, 8)); // Prints "(3, -4)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The remainder vector.</returns> public static Vector2 operator %(Vector2 vec, Vector2 divisorv) { vec.x %= divisorv.x; @@ -712,16 +802,43 @@ namespace Godot return vec; } + /// <summary> + /// Returns <see langword="true"/> if the vectors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are exactly equal.</returns> public static bool operator ==(Vector2 left, Vector2 right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the vectors are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are not equal.</returns> public static bool operator !=(Vector2 left, Vector2 right) { return !left.Equals(right); } + /// <summary> + /// Compares two <see cref="Vector2"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than the right.</returns> public static bool operator <(Vector2 left, Vector2 right) { if (left.x == right.x) @@ -731,6 +848,17 @@ namespace Godot return left.x < right.x; } + /// <summary> + /// Compares two <see cref="Vector2"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than the right.</returns> public static bool operator >(Vector2 left, Vector2 right) { if (left.x == right.x) @@ -740,29 +868,54 @@ namespace Godot return left.x > right.x; } + /// <summary> + /// Compares two <see cref="Vector2"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> public static bool operator <=(Vector2 left, Vector2 right) { if (left.x == right.x) { return left.y <= right.y; } - return left.x <= right.x; + return left.x < right.x; } + /// <summary> + /// Compares two <see cref="Vector2"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> public static bool operator >=(Vector2 left, Vector2 right) { if (left.x == right.x) { return left.y >= right.y; } - return left.x >= right.x; + return left.x > right.x; } /// <summary> - /// Returns <see langword="true"/> if this vector and <paramref name="obj"/> are equal. + /// Returns <see langword="true"/> if the vector is exactly equal + /// to the given object (<see paramref="obj"/>). + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the vector and the other object are equal.</returns> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { if (obj is Vector2) @@ -773,10 +926,12 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are equal. + /// Returns <see langword="true"/> if the vectors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="other">The other vector to compare.</param> - /// <returns>Whether or not the vectors are equal.</returns> + /// <param name="other">The other vector.</param> + /// <returns>Whether or not the vectors are exactly equal.</returns> public bool Equals(Vector2 other) { return x == other.x && y == other.y; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index ca4531d885..6cac16d53b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -366,6 +366,13 @@ namespace Godot this.y = Mathf.RoundToInt(v.y); } + /// <summary> + /// Adds each component of the <see cref="Vector2i"/> + /// with the components of the given <see cref="Vector2i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The added vector.</returns> public static Vector2i operator +(Vector2i left, Vector2i right) { left.x += right.x; @@ -373,6 +380,13 @@ namespace Godot return left; } + /// <summary> + /// Subtracts each component of the <see cref="Vector2i"/> + /// by the components of the given <see cref="Vector2i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The subtracted vector.</returns> public static Vector2i operator -(Vector2i left, Vector2i right) { left.x -= right.x; @@ -380,6 +394,14 @@ namespace Godot return left; } + /// <summary> + /// Returns the negative value of the <see cref="Vector2i"/>. + /// This is the same as writing <c>new Vector2i(-v.x, -v.y)</c>. + /// This operation flips the direction of the vector while + /// keeping the same magnitude. + /// </summary> + /// <param name="vec">The vector to negate/flip.</param> + /// <returns>The negated/flipped vector.</returns> public static Vector2i operator -(Vector2i vec) { vec.x = -vec.x; @@ -387,6 +409,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector2i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The vector to multiply.</param> + /// <param name="scale">The scale to multiply by.</param> + /// <returns>The multiplied vector.</returns> public static Vector2i operator *(Vector2i vec, int scale) { vec.x *= scale; @@ -394,6 +423,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector2i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="scale">The scale to multiply by.</param> + /// <param name="vec">The vector to multiply.</param> + /// <returns>The multiplied vector.</returns> public static Vector2i operator *(int scale, Vector2i vec) { vec.x *= scale; @@ -401,6 +437,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector2i"/> + /// by the components of the given <see cref="Vector2i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The multiplied vector.</returns> public static Vector2i operator *(Vector2i left, Vector2i right) { left.x *= right.x; @@ -408,6 +451,13 @@ namespace Godot return left; } + /// <summary> + /// Multiplies each component of the <see cref="Vector2i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The divided vector.</returns> public static Vector2i operator /(Vector2i vec, int divisor) { vec.x /= divisor; @@ -415,6 +465,13 @@ namespace Godot return vec; } + /// <summary> + /// Divides each component of the <see cref="Vector2i"/> + /// by the components of the given <see cref="Vector2i"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The divided vector.</returns> public static Vector2i operator /(Vector2i vec, Vector2i divisorv) { vec.x /= divisorv.x; @@ -422,6 +479,22 @@ namespace Godot return vec; } + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector2i"/> + /// with the components of the given <see langword="int"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// Consider using <see cref="PosMod(int)"/> instead + /// if you want to handle negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector2i(10, -20) % 7); // Prints "(3, -6)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The remainder vector.</returns> public static Vector2i operator %(Vector2i vec, int divisor) { vec.x %= divisor; @@ -429,6 +502,22 @@ namespace Godot return vec; } + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector2i"/> + /// with the components of the given <see cref="Vector2i"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// Consider using <see cref="PosMod(Vector2i)"/> instead + /// if you want to handle negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector2i(10, -20) % new Vector2i(7, 8)); // Prints "(3, -4)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The remainder vector.</returns> public static Vector2i operator %(Vector2i vec, Vector2i divisorv) { vec.x %= divisorv.x; @@ -436,6 +525,13 @@ namespace Godot return vec; } + /// <summary> + /// Performs a bitwise AND operation with this <see cref="Vector2i"/> + /// and the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The vector to AND with.</param> + /// <param name="and">The integer to AND with.</param> + /// <returns>The result of the bitwise AND.</returns> public static Vector2i operator &(Vector2i vec, int and) { vec.x &= and; @@ -443,6 +539,13 @@ namespace Godot return vec; } + /// <summary> + /// Performs a bitwise AND operation with this <see cref="Vector2i"/> + /// and the given <see cref="Vector2i"/>. + /// </summary> + /// <param name="vec">The left vector to AND with.</param> + /// <param name="andv">The right vector to AND with.</param> + /// <returns>The result of the bitwise AND.</returns> public static Vector2i operator &(Vector2i vec, Vector2i andv) { vec.x &= andv.x; @@ -450,50 +553,106 @@ namespace Godot return vec; } + /// <summary> + /// Returns <see langword="true"/> if the vectors are equal. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are equal.</returns> public static bool operator ==(Vector2i left, Vector2i right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the vectors are not equal. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are not equal.</returns> public static bool operator !=(Vector2i left, Vector2i right) { return !left.Equals(right); } + /// <summary> + /// Compares two <see cref="Vector2i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than the right.</returns> public static bool operator <(Vector2i left, Vector2i right) { - if (left.x.Equals(right.x)) + if (left.x == right.x) { return left.y < right.y; } return left.x < right.x; } + /// <summary> + /// Compares two <see cref="Vector2i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than the right.</returns> public static bool operator >(Vector2i left, Vector2i right) { - if (left.x.Equals(right.x)) + if (left.x == right.x) { return left.y > right.y; } return left.x > right.x; } + /// <summary> + /// Compares two <see cref="Vector2i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> public static bool operator <=(Vector2i left, Vector2i right) { - if (left.x.Equals(right.x)) + if (left.x == right.x) { return left.y <= right.y; } - return left.x <= right.x; + return left.x < right.x; } + /// <summary> + /// Compares two <see cref="Vector2i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> public static bool operator >=(Vector2i left, Vector2i right) { - if (left.x.Equals(right.x)) + if (left.x == right.x) { return left.y >= right.y; } - return left.x >= right.x; + return left.x > right.x; } /// <summary> @@ -515,10 +674,11 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this vector and <paramref name="obj"/> are equal. + /// Returns <see langword="true"/> if the vector is equal + /// to the given object (<see paramref="obj"/>). /// </summary> - /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the vector and the other object are equal.</returns> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { if (obj is Vector2i) @@ -530,9 +690,9 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are equal. + /// Returns <see langword="true"/> if the vectors are equal. /// </summary> - /// <param name="other">The other vector to compare.</param> + /// <param name="other">The other vector.</param> /// <returns>Whether or not the vectors are equal.</returns> public bool Equals(Vector2i other) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 01e3a71bcb..63d9be0a6d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -699,6 +699,13 @@ namespace Godot z = v.z; } + /// <summary> + /// Adds each component of the <see cref="Vector3"/> + /// with the components of the given <see cref="Vector3"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The added vector.</returns> public static Vector3 operator +(Vector3 left, Vector3 right) { left.x += right.x; @@ -707,6 +714,13 @@ namespace Godot return left; } + /// <summary> + /// Subtracts each component of the <see cref="Vector3"/> + /// by the components of the given <see cref="Vector3"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The subtracted vector.</returns> public static Vector3 operator -(Vector3 left, Vector3 right) { left.x -= right.x; @@ -715,6 +729,15 @@ namespace Godot return left; } + /// <summary> + /// Returns the negative value of the <see cref="Vector3"/>. + /// This is the same as writing <c>new Vector3(-v.x, -v.y, -v.z)</c>. + /// This operation flips the direction of the vector while + /// keeping the same magnitude. + /// With floats, the number zero can be either positive or negative. + /// </summary> + /// <param name="vec">The vector to negate/flip.</param> + /// <returns>The negated/flipped vector.</returns> public static Vector3 operator -(Vector3 vec) { vec.x = -vec.x; @@ -723,6 +746,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector3"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="vec">The vector to multiply.</param> + /// <param name="scale">The scale to multiply by.</param> + /// <returns>The multiplied vector.</returns> public static Vector3 operator *(Vector3 vec, real_t scale) { vec.x *= scale; @@ -731,6 +761,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector3"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="scale">The scale to multiply by.</param> + /// <param name="vec">The vector to multiply.</param> + /// <returns>The multiplied vector.</returns> public static Vector3 operator *(real_t scale, Vector3 vec) { vec.x *= scale; @@ -739,6 +776,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector3"/> + /// by the components of the given <see cref="Vector3"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The multiplied vector.</returns> public static Vector3 operator *(Vector3 left, Vector3 right) { left.x *= right.x; @@ -747,6 +791,13 @@ namespace Godot return left; } + /// <summary> + /// Divides each component of the <see cref="Vector3"/> + /// by the given <see cref="real_t"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The divided vector.</returns> public static Vector3 operator /(Vector3 vec, real_t divisor) { vec.x /= divisor; @@ -755,6 +806,13 @@ namespace Godot return vec; } + /// <summary> + /// Divides each component of the <see cref="Vector3"/> + /// by the components of the given <see cref="Vector3"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The divided vector.</returns> public static Vector3 operator /(Vector3 vec, Vector3 divisorv) { vec.x /= divisorv.x; @@ -763,6 +821,22 @@ namespace Godot return vec; } + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector3"/> + /// with the components of the given <see cref="real_t"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// Consider using <see cref="PosMod(real_t)"/> instead + /// if you want to handle negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector3(10, -20, 30) % 7); // Prints "(3, -6, 2)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The remainder vector.</returns> public static Vector3 operator %(Vector3 vec, real_t divisor) { vec.x %= divisor; @@ -771,6 +845,22 @@ namespace Godot return vec; } + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector3"/> + /// with the components of the given <see cref="Vector3"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// Consider using <see cref="PosMod(Vector3)"/> instead + /// if you want to handle negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector3(10, -20, 30) % new Vector3(7, 8, 9)); // Prints "(3, -4, 3)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The remainder vector.</returns> public static Vector3 operator %(Vector3 vec, Vector3 divisorv) { vec.x %= divisorv.x; @@ -779,16 +869,43 @@ namespace Godot return vec; } + /// <summary> + /// Returns <see langword="true"/> if the vectors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are exactly equal.</returns> public static bool operator ==(Vector3 left, Vector3 right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the vectors are not equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are not equal.</returns> public static bool operator !=(Vector3 left, Vector3 right) { return !left.Equals(right); } + /// <summary> + /// Compares two <see cref="Vector3"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors, and then with the Z values. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than the right.</returns> public static bool operator <(Vector3 left, Vector3 right) { if (left.x == right.x) @@ -802,6 +919,17 @@ namespace Godot return left.x < right.x; } + /// <summary> + /// Compares two <see cref="Vector3"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors, and then with the Z values. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than the right.</returns> public static bool operator >(Vector3 left, Vector3 right) { if (left.x == right.x) @@ -815,6 +943,17 @@ namespace Godot return left.x > right.x; } + /// <summary> + /// Compares two <see cref="Vector3"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors, and then with the Z values. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> public static bool operator <=(Vector3 left, Vector3 right) { if (left.x == right.x) @@ -828,6 +967,17 @@ namespace Godot return left.x < right.x; } + /// <summary> + /// Compares two <see cref="Vector3"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors, and then with the Z values. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> public static bool operator >=(Vector3 left, Vector3 right) { if (left.x == right.x) @@ -842,10 +992,13 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this vector and <paramref name="obj"/> are equal. + /// Returns <see langword="true"/> if the vector is exactly equal + /// to the given object (<see paramref="obj"/>). + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the vector and the other object are equal.</returns> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { if (obj is Vector3) @@ -857,10 +1010,12 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are equal + /// Returns <see langword="true"/> if the vectors are exactly equal. + /// Note: Due to floating-point precision errors, consider using + /// <see cref="IsEqualApprox"/> instead, which is more reliable. /// </summary> - /// <param name="other">The other vector to compare.</param> - /// <returns>Whether or not the vectors are equal.</returns> + /// <param name="other">The other vector.</param> + /// <returns>Whether or not the vectors are exactly equal.</returns> public bool Equals(Vector3 other) { return x == other.x && y == other.y && z == other.z; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index 2a7771cdfc..474876fc91 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -347,6 +347,13 @@ namespace Godot this.z = Mathf.RoundToInt(v.z); } + /// <summary> + /// Adds each component of the <see cref="Vector3i"/> + /// with the components of the given <see cref="Vector3i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The added vector.</returns> public static Vector3i operator +(Vector3i left, Vector3i right) { left.x += right.x; @@ -355,6 +362,13 @@ namespace Godot return left; } + /// <summary> + /// Subtracts each component of the <see cref="Vector3i"/> + /// by the components of the given <see cref="Vector3i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The subtracted vector.</returns> public static Vector3i operator -(Vector3i left, Vector3i right) { left.x -= right.x; @@ -363,6 +377,14 @@ namespace Godot return left; } + /// <summary> + /// Returns the negative value of the <see cref="Vector3i"/>. + /// This is the same as writing <c>new Vector3i(-v.x, -v.y, -v.z)</c>. + /// This operation flips the direction of the vector while + /// keeping the same magnitude. + /// </summary> + /// <param name="vec">The vector to negate/flip.</param> + /// <returns>The negated/flipped vector.</returns> public static Vector3i operator -(Vector3i vec) { vec.x = -vec.x; @@ -371,6 +393,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector3i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The vector to multiply.</param> + /// <param name="scale">The scale to multiply by.</param> + /// <returns>The multiplied vector.</returns> public static Vector3i operator *(Vector3i vec, int scale) { vec.x *= scale; @@ -379,6 +408,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector3i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="scale">The scale to multiply by.</param> + /// <param name="vec">The vector to multiply.</param> + /// <returns>The multiplied vector.</returns> public static Vector3i operator *(int scale, Vector3i vec) { vec.x *= scale; @@ -387,6 +423,13 @@ namespace Godot return vec; } + /// <summary> + /// Multiplies each component of the <see cref="Vector3i"/> + /// by the components of the given <see cref="Vector3i"/>. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>The multiplied vector.</returns> public static Vector3i operator *(Vector3i left, Vector3i right) { left.x *= right.x; @@ -395,6 +438,13 @@ namespace Godot return left; } + /// <summary> + /// Multiplies each component of the <see cref="Vector3i"/> + /// by the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The divided vector.</returns> public static Vector3i operator /(Vector3i vec, int divisor) { vec.x /= divisor; @@ -403,6 +453,13 @@ namespace Godot return vec; } + /// <summary> + /// Divides each component of the <see cref="Vector3i"/> + /// by the components of the given <see cref="Vector3i"/>. + /// </summary> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The divided vector.</returns> public static Vector3i operator /(Vector3i vec, Vector3i divisorv) { vec.x /= divisorv.x; @@ -411,6 +468,22 @@ namespace Godot return vec; } + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector3i"/> + /// with the components of the given <see langword="int"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// Consider using <see cref="PosMod(int)"/> instead + /// if you want to handle negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector3i(10, -20, 30) % 7); // Prints "(3, -6, 2)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisor">The divisor value.</param> + /// <returns>The remainder vector.</returns> public static Vector3i operator %(Vector3i vec, int divisor) { vec.x %= divisor; @@ -419,6 +492,22 @@ namespace Godot return vec; } + /// <summary> + /// Gets the remainder of each component of the <see cref="Vector3i"/> + /// with the components of the given <see cref="Vector3i"/>. + /// This operation uses truncated division, which is often not desired + /// as it does not work well with negative numbers. + /// Consider using <see cref="PosMod(Vector3i)"/> instead + /// if you want to handle negative numbers. + /// </summary> + /// <example> + /// <code> + /// GD.Print(new Vector3i(10, -20, 30) % new Vector3i(7, 8, 9)); // Prints "(3, -4, 3)" + /// </code> + /// </example> + /// <param name="vec">The dividend vector.</param> + /// <param name="divisorv">The divisor vector.</param> + /// <returns>The remainder vector.</returns> public static Vector3i operator %(Vector3i vec, Vector3i divisorv) { vec.x %= divisorv.x; @@ -427,6 +516,13 @@ namespace Godot return vec; } + /// <summary> + /// Performs a bitwise AND operation with this <see cref="Vector3i"/> + /// and the given <see langword="int"/>. + /// </summary> + /// <param name="vec">The vector to AND with.</param> + /// <param name="and">The integer to AND with.</param> + /// <returns>The result of the bitwise AND.</returns> public static Vector3i operator &(Vector3i vec, int and) { vec.x &= and; @@ -435,6 +531,13 @@ namespace Godot return vec; } + /// <summary> + /// Performs a bitwise AND operation with this <see cref="Vector3i"/> + /// and the given <see cref="Vector3i"/>. + /// </summary> + /// <param name="vec">The left vector to AND with.</param> + /// <param name="andv">The right vector to AND with.</param> + /// <returns>The result of the bitwise AND.</returns> public static Vector3i operator &(Vector3i vec, Vector3i andv) { vec.x &= andv.x; @@ -443,65 +546,121 @@ namespace Godot return vec; } + /// <summary> + /// Returns <see langword="true"/> if the vectors are equal. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are equal.</returns> public static bool operator ==(Vector3i left, Vector3i right) { return left.Equals(right); } + /// <summary> + /// Returns <see langword="true"/> if the vectors are not equal. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the vectors are not equal.</returns> public static bool operator !=(Vector3i left, Vector3i right) { return !left.Equals(right); } + /// <summary> + /// Compares two <see cref="Vector3i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors, and then with the Z values. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than the right.</returns> public static bool operator <(Vector3i left, Vector3i right) { if (left.x == right.x) { if (left.y == right.y) + { return left.z < right.z; - else - return left.y < right.y; + } + return left.y < right.y; } - return left.x < right.x; } + /// <summary> + /// Compares two <see cref="Vector3i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors, and then with the Z values. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than the right.</returns> public static bool operator >(Vector3i left, Vector3i right) { if (left.x == right.x) { if (left.y == right.y) + { return left.z > right.z; - else - return left.y > right.y; + } + return left.y > right.y; } - return left.x > right.x; } + /// <summary> + /// Compares two <see cref="Vector3i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is less than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors, and then with the Z values. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is less than or equal to the right.</returns> public static bool operator <=(Vector3i left, Vector3i right) { if (left.x == right.x) { if (left.y == right.y) + { return left.z <= right.z; - else - return left.y < right.y; + } + return left.y < right.y; } - return left.x < right.x; } + /// <summary> + /// Compares two <see cref="Vector3i"/> vectors by first checking if + /// the X value of the <paramref name="left"/> vector is greater than + /// or equal to the X value of the <paramref name="right"/> vector. + /// If the X values are exactly equal, then it repeats this check + /// with the Y values of the two vectors, and then with the Z values. + /// This operator is useful for sorting vectors. + /// </summary> + /// <param name="left">The left vector.</param> + /// <param name="right">The right vector.</param> + /// <returns>Whether or not the left is greater than or equal to the right.</returns> public static bool operator >=(Vector3i left, Vector3i right) { if (left.x == right.x) { if (left.y == right.y) + { return left.z >= right.z; - else - return left.y > right.y; + } + return left.y > right.y; } - return left.x > right.x; } @@ -524,10 +683,11 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this vector and <paramref name="obj"/> are equal. + /// Returns <see langword="true"/> if the vector is equal + /// to the given object (<see paramref="obj"/>). /// </summary> - /// <param name="obj">The other object to compare.</param> - /// <returns>Whether or not the vector and the other object are equal.</returns> + /// <param name="obj">The object to compare with.</param> + /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { if (obj is Vector3i) @@ -539,9 +699,9 @@ namespace Godot } /// <summary> - /// Returns <see langword="true"/> if this vector and <paramref name="other"/> are equal + /// Returns <see langword="true"/> if the vectors are equal. /// </summary> - /// <param name="other">The other vector to compare.</param> + /// <param name="other">The other vector.</param> /// <returns>Whether or not the vectors are equal.</returns> public bool Equals(Vector3i other) { diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp index a2ff868f65..07ddf5d945 100644 --- a/modules/mono/glue/gd_glue.cpp +++ b/modules/mono/glue/gd_glue.cpp @@ -182,26 +182,30 @@ void godot_icall_GD_printt(MonoArray *p_what) { print_line(str); } -float godot_icall_GD_randf() { - return Math::randf(); +void godot_icall_GD_randomize() { + Math::randomize(); } uint32_t godot_icall_GD_randi() { return Math::rand(); } -void godot_icall_GD_randomize() { - Math::randomize(); +float godot_icall_GD_randf() { + return Math::randf(); } -double godot_icall_GD_randf_range(double from, double to) { +int32_t godot_icall_GD_randi_range(int32_t from, int32_t to) { return Math::random(from, to); } -int32_t godot_icall_GD_randi_range(int32_t from, int32_t to) { +double godot_icall_GD_randf_range(double from, double to) { return Math::random(from, to); } +double godot_icall_GD_randfn(double mean, double deviation) { + return Math::randfn(mean, deviation); +} + uint32_t godot_icall_GD_rand_seed(uint64_t seed, uint64_t *newSeed) { uint32_t ret = Math::rand_from_seed(&seed); *newSeed = seed; @@ -300,11 +304,12 @@ void godot_register_gd_icalls() { GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printraw", godot_icall_GD_printraw); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_prints", godot_icall_GD_prints); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printt", godot_icall_GD_printt); - GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf", godot_icall_GD_randf); - GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi", godot_icall_GD_randi); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randomize", godot_icall_GD_randomize); - GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf_range", godot_icall_GD_randf_range); + GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi", godot_icall_GD_randi); + GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf", godot_icall_GD_randf); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi_range", godot_icall_GD_randi_range); + GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf_range", godot_icall_GD_randf_range); + GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randfn", godot_icall_GD_randfn); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_rand_seed", godot_icall_GD_rand_seed); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_seed", godot_icall_GD_seed); GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_str", godot_icall_GD_str); diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index f3e83b26b9..52447bc59b 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -504,7 +504,7 @@ void GDMono::_init_godot_api_hashes() { } void GDMono::_init_exception_policy() { - PropertyInfo exc_policy_prop = PropertyInfo(Variant::INT, "mono/unhandled_exception_policy", PROPERTY_HINT_ENUM, + PropertyInfo exc_policy_prop = PropertyInfo(Variant::INT, "mono/runtime/unhandled_exception_policy", PROPERTY_HINT_ENUM, vformat("Terminate Application:%s,Log Error:%s", (int)POLICY_TERMINATE_APP, (int)POLICY_LOG_ERROR)); unhandled_exception_policy = (UnhandledExceptionPolicy)(int)GLOBAL_DEF(exc_policy_prop.name, (int)POLICY_TERMINATE_APP); ProjectSettings::get_singleton()->set_custom_property_info(exc_policy_prop.name, exc_policy_prop); diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index 8fd3a13e1f..05e040b518 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -52,7 +52,8 @@ #include "editor/editor_settings.h" #endif -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For csg, gridmap. + #ifdef MODULE_CSG_ENABLED #include "modules/csg/csg_shape.h" #endif diff --git a/modules/opensimplex/noise_texture.h b/modules/opensimplex/noise_texture.h index 6237b6460d..a0b2a86c41 100644 --- a/modules/opensimplex/noise_texture.h +++ b/modules/opensimplex/noise_texture.h @@ -35,9 +35,6 @@ #include "core/io/image.h" #include "core/object/ref_counted.h" -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "editor/property_editor.h" class NoiseTexture : public Texture2D { GDCLASS(NoiseTexture, Texture2D); diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 1a0b0e357d..1adaef4d84 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -38,6 +38,8 @@ #include "thirdparty/icu4c/icudata.gen.h" #endif +#include "modules/modules_enabled.gen.h" // For freetype, msdfgen. + #ifdef MODULE_MSDFGEN_ENABLED #include "core/ShapeDistanceFinder.h" #include "core/contour-combiners.h" diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index eb8316b200..5eaff67a6e 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -55,7 +55,7 @@ #include <unicode/ustring.h> #include <unicode/utypes.h> -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For freetype, msdfgen. #ifdef MODULE_FREETYPE_ENABLED #include <ft2build.h> diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 43a636e484..80ae10c005 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -33,6 +33,8 @@ #include "core/error/error_macros.h" #include "core/string/print_string.h" +#include "modules/modules_enabled.gen.h" // For freetype, msdfgen. + #ifdef MODULE_MSDFGEN_ENABLED #include "core/ShapeDistanceFinder.h" #include "core/contour-combiners.h" @@ -3265,7 +3267,9 @@ TextServerFallback::TextServerFallback() { }; TextServerFallback::~TextServerFallback() { +#ifdef MODULE_FREETYPE_ENABLED if (library != nullptr) { FT_Done_FreeType(library); } +#endif }; diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 2f495115e0..67b08d1eac 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -42,7 +42,7 @@ #include "core/templates/thread_work_pool.h" #include "scene/resources/texture.h" -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For freetype, msdfgen. #ifdef MODULE_FREETYPE_ENABLED #include <ft2build.h> diff --git a/modules/visual_script/SCsub b/modules/visual_script/SCsub index 16faea08d7..b91cceae09 100644 --- a/modules/visual_script/SCsub +++ b/modules/visual_script/SCsub @@ -6,3 +6,6 @@ Import("env_modules") env_vs = env_modules.Clone() env_vs.add_source_files(env.modules_sources, "*.cpp") + +if env["tools"]: + env_vs.add_source_files(env.modules_sources, "editor/*.cpp") diff --git a/modules/visual_script/doc_classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml index be6bf00e50..a452974014 100644 --- a/modules/visual_script/doc_classes/VisualScript.xml +++ b/modules/visual_script/doc_classes/VisualScript.xml @@ -9,7 +9,7 @@ You are most likely to use this class via the Visual Script editor or when writing plugins for it. </description> <tutorials> - <link title="VisualScript documentation index">https://docs.godotengine.org/en/latest/tutorials/scripting/visual_script/index.html</link> + <link title="VisualScript documentation index">$DOCS_URL/tutorials/scripting/visual_script/index.html</link> </tutorials> <methods> <method name="add_custom_signal"> diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml index 942d92311b..b3fd678379 100644 --- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml +++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml @@ -112,101 +112,107 @@ <constant name="MATH_RANDF" value="32" enum="BuiltinFunc"> Return a random floating-point value between 0 and 1. To obtain a random value between 0 to N, you can use it with multiplication. </constant> - <constant name="MATH_RANDF_RANGE" value="33" enum="BuiltinFunc"> + <constant name="MATH_RANDI_RANGE" value="33" enum="BuiltinFunc"> + Return a random 32-bit integer value between the two inputs. + </constant> + <constant name="MATH_RANDF_RANGE" value="34" enum="BuiltinFunc"> Return a random floating-point value between the two inputs. </constant> - <constant name="MATH_RANDI_RANGE" value="34" enum="BuiltinFunc"> - Return a random 32-bit integer value between the two inputs. + <constant name="MATH_RANDFN" value="35" enum="BuiltinFunc"> + Returns a normally-distributed pseudo-random number, using Box-Muller transform with the specified mean and a standard deviation. This is also called Gaussian distribution. </constant> - <constant name="MATH_SEED" value="35" enum="BuiltinFunc"> + <constant name="MATH_SEED" value="36" enum="BuiltinFunc"> Set the seed for the random number generator. </constant> - <constant name="MATH_RANDSEED" value="36" enum="BuiltinFunc"> + <constant name="MATH_RANDSEED" value="37" enum="BuiltinFunc"> Return a random value from the given seed, along with the new seed. </constant> - <constant name="MATH_DEG2RAD" value="37" enum="BuiltinFunc"> + <constant name="MATH_DEG2RAD" value="38" enum="BuiltinFunc"> Convert the input from degrees to radians. </constant> - <constant name="MATH_RAD2DEG" value="38" enum="BuiltinFunc"> + <constant name="MATH_RAD2DEG" value="39" enum="BuiltinFunc"> Convert the input from radians to degrees. </constant> - <constant name="MATH_LINEAR2DB" value="39" enum="BuiltinFunc"> + <constant name="MATH_LINEAR2DB" value="40" enum="BuiltinFunc"> Convert the input from linear volume to decibel volume. </constant> - <constant name="MATH_DB2LINEAR" value="40" enum="BuiltinFunc"> + <constant name="MATH_DB2LINEAR" value="41" enum="BuiltinFunc"> Convert the input from decibel volume to linear volume. </constant> - <constant name="MATH_WRAP" value="41" enum="BuiltinFunc"> + <constant name="MATH_WRAP" value="42" enum="BuiltinFunc"> + </constant> + <constant name="MATH_WRAPF" value="43" enum="BuiltinFunc"> </constant> - <constant name="MATH_WRAPF" value="42" enum="BuiltinFunc"> + <constant name="MATH_PINGPONG" value="44" enum="BuiltinFunc"> + Return the [code]value[/code] wrapped between [code]0[/code] and the [code]length[/code]. If the limit is reached, the next value the function returned is decreased to the [code]0[/code] side or increased to the [code]length[/code] side (like a triangle wave). If [code]length[/code] is less than zero, it becomes positive. </constant> - <constant name="LOGIC_MAX" value="43" enum="BuiltinFunc"> + <constant name="LOGIC_MAX" value="45" enum="BuiltinFunc"> Return the greater of the two numbers, also known as their maximum. </constant> - <constant name="LOGIC_MIN" value="44" enum="BuiltinFunc"> + <constant name="LOGIC_MIN" value="46" enum="BuiltinFunc"> Return the lesser of the two numbers, also known as their minimum. </constant> - <constant name="LOGIC_CLAMP" value="45" enum="BuiltinFunc"> + <constant name="LOGIC_CLAMP" value="47" enum="BuiltinFunc"> Return the input clamped inside the given range, ensuring the result is never outside it. Equivalent to [code]min(max(input, range_low), range_high)[/code]. </constant> - <constant name="LOGIC_NEAREST_PO2" value="46" enum="BuiltinFunc"> + <constant name="LOGIC_NEAREST_PO2" value="48" enum="BuiltinFunc"> Return the nearest power of 2 to the input. </constant> - <constant name="OBJ_WEAKREF" value="47" enum="BuiltinFunc"> + <constant name="OBJ_WEAKREF" value="49" enum="BuiltinFunc"> Create a [WeakRef] from the input. </constant> - <constant name="TYPE_CONVERT" value="48" enum="BuiltinFunc"> + <constant name="TYPE_CONVERT" value="50" enum="BuiltinFunc"> Convert between types. </constant> - <constant name="TYPE_OF" value="49" enum="BuiltinFunc"> + <constant name="TYPE_OF" value="51" enum="BuiltinFunc"> Return the type of the input as an integer. Check [enum Variant.Type] for the integers that might be returned. </constant> - <constant name="TYPE_EXISTS" value="50" enum="BuiltinFunc"> + <constant name="TYPE_EXISTS" value="52" enum="BuiltinFunc"> Checks if a type is registered in the [ClassDB]. </constant> - <constant name="TEXT_CHAR" value="51" enum="BuiltinFunc"> + <constant name="TEXT_CHAR" value="53" enum="BuiltinFunc"> Return a character with the given ascii value. </constant> - <constant name="TEXT_STR" value="52" enum="BuiltinFunc"> + <constant name="TEXT_STR" value="54" enum="BuiltinFunc"> Convert the input to a string. </constant> - <constant name="TEXT_PRINT" value="53" enum="BuiltinFunc"> + <constant name="TEXT_PRINT" value="55" enum="BuiltinFunc"> Print the given string to the output window. </constant> - <constant name="TEXT_PRINTERR" value="54" enum="BuiltinFunc"> + <constant name="TEXT_PRINTERR" value="56" enum="BuiltinFunc"> Print the given string to the standard error output. </constant> - <constant name="TEXT_PRINTRAW" value="55" enum="BuiltinFunc"> + <constant name="TEXT_PRINTRAW" value="57" enum="BuiltinFunc"> Print the given string to the standard output, without adding a newline. </constant> - <constant name="TEXT_PRINT_VERBOSE" value="56" enum="BuiltinFunc"> + <constant name="TEXT_PRINT_VERBOSE" value="58" enum="BuiltinFunc"> </constant> - <constant name="VAR_TO_STR" value="57" enum="BuiltinFunc"> + <constant name="VAR_TO_STR" value="59" enum="BuiltinFunc"> Serialize a [Variant] to a string. </constant> - <constant name="STR_TO_VAR" value="58" enum="BuiltinFunc"> + <constant name="STR_TO_VAR" value="60" enum="BuiltinFunc"> Deserialize a [Variant] from a string serialized using [constant VAR_TO_STR]. </constant> - <constant name="VAR_TO_BYTES" value="59" enum="BuiltinFunc"> + <constant name="VAR_TO_BYTES" value="61" enum="BuiltinFunc"> Serialize a [Variant] to a [PackedByteArray]. </constant> - <constant name="BYTES_TO_VAR" value="60" enum="BuiltinFunc"> + <constant name="BYTES_TO_VAR" value="62" enum="BuiltinFunc"> Deserialize a [Variant] from a [PackedByteArray] serialized using [constant VAR_TO_BYTES]. </constant> - <constant name="MATH_SMOOTHSTEP" value="61" enum="BuiltinFunc"> + <constant name="MATH_SMOOTHSTEP" value="63" enum="BuiltinFunc"> Return a number smoothly interpolated between the first two inputs, based on the third input. Similar to [constant MATH_LERP], but interpolates faster at the beginning and slower at the end. Using Hermite interpolation formula: [codeblock] var t = clamp((weight - from) / (to - from), 0.0, 1.0) return t * t * (3.0 - 2.0 * t) [/codeblock] </constant> - <constant name="MATH_POSMOD" value="62" enum="BuiltinFunc"> + <constant name="MATH_POSMOD" value="64" enum="BuiltinFunc"> </constant> - <constant name="MATH_LERP_ANGLE" value="63" enum="BuiltinFunc"> + <constant name="MATH_LERP_ANGLE" value="65" enum="BuiltinFunc"> </constant> - <constant name="TEXT_ORD" value="64" enum="BuiltinFunc"> + <constant name="TEXT_ORD" value="66" enum="BuiltinFunc"> </constant> - <constant name="FUNC_MAX" value="65" enum="BuiltinFunc"> + <constant name="FUNC_MAX" value="67" enum="BuiltinFunc"> Represents the size of the [enum BuiltinFunc] enum. </constant> </constants> diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index 7b4fbc67fc..2096487235 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -30,6 +30,10 @@ #include "visual_script_editor.h" +#include "../visual_script_expression.h" +#include "../visual_script_flow_control.h" +#include "../visual_script_func_nodes.h" +#include "../visual_script_nodes.h" #include "core/input/input.h" #include "core/object/class_db.h" #include "core/object/script_language.h" @@ -39,10 +43,6 @@ #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" #include "scene/main/window.h" -#include "visual_script_expression.h" -#include "visual_script_flow_control.h" -#include "visual_script_func_nodes.h" -#include "visual_script_nodes.h" #ifdef TOOLS_ENABLED class VisualScriptEditorSignalEdit : public Object { @@ -1172,9 +1172,9 @@ void VisualScriptEditor::_member_selected() { if (ti->get_parent() == members->get_root()->get_first_child()) { #ifdef OSX_ENABLED - bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_META); + bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::META); #else - bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); #endif if (held_ctrl) { ERR_FAIL_COND(!script->has_function(selected)); @@ -1952,7 +1952,7 @@ void VisualScriptEditor::input(const Ref<InputEvent> &p_event) { void VisualScriptEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> key = p_event; - if (key.is_valid() && key->is_pressed() && key->get_button_mask() == MOUSE_BUTTON_RIGHT) { + if (key.is_valid() && key->is_pressed() && key->get_button_mask() == MouseButton::RIGHT) { saved_position = graph->get_local_mouse_position(); Point2 gpos = Input::get_singleton()->get_mouse_position(); @@ -2049,7 +2049,7 @@ void VisualScriptEditor::_fn_name_box_input(const Ref<InputEvent> &p_event) { } Ref<InputEventKey> key = p_event; - if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ENTER) { + if (key.is_valid() && key->is_pressed() && key->get_keycode() == Key::ENTER) { function_name_edit->hide(); _rename_function(selected, function_name_box->get_text()); function_name_box->clear(); @@ -2108,7 +2108,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & String(d["type"]) == "nodes")) { if (String(d["type"]) == "obj_property") { #ifdef OSX_ENABLED - const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Getter. Hold Shift to drop a generic signature."), find_keycode_name(KEY_META))); + const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Getter. Hold Shift to drop a generic signature."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature.")); #endif @@ -2116,7 +2116,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & if (String(d["type"]) == "nodes") { #ifdef OSX_ENABLED - const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a simple reference to the node."), find_keycode_name(KEY_META))); + const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a simple reference to the node."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a simple reference to the node.")); #endif @@ -2124,7 +2124,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & if (String(d["type"]) == "visual_script_variable_drag") { #ifdef OSX_ENABLED - const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Variable Setter."), find_keycode_name(KEY_META))); + const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Variable Setter."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a Variable Setter.")); #endif @@ -2187,9 +2187,9 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da if (String(d["type"]) == "visual_script_variable_drag") { #ifdef OSX_ENABLED - bool use_set = Input::get_singleton()->is_key_pressed(KEY_META); + bool use_set = Input::get_singleton()->is_key_pressed(Key::META); #else - bool use_set = Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool use_set = Input::get_singleton()->is_key_pressed(Key::CTRL); #endif Vector2 pos = _get_pos_in_graph(p_point); @@ -2296,9 +2296,9 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da if (String(d["type"]) == "files") { #ifdef OSX_ENABLED - bool use_preload = Input::get_singleton()->is_key_pressed(KEY_META); + bool use_preload = Input::get_singleton()->is_key_pressed(Key::META); #else - bool use_preload = Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool use_preload = Input::get_singleton()->is_key_pressed(Key::CTRL); #endif Vector2 pos = _get_pos_in_graph(p_point); @@ -2359,9 +2359,9 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } #ifdef OSX_ENABLED - bool use_node = Input::get_singleton()->is_key_pressed(KEY_META); + bool use_node = Input::get_singleton()->is_key_pressed(Key::META); #else - bool use_node = Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool use_node = Input::get_singleton()->is_key_pressed(Key::CTRL); #endif Array nodes = d["nodes"]; @@ -2409,7 +2409,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da if (String(d["type"]) == "obj_property") { Node *sn = _find_script_node(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root(), script); - if (!sn && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!sn && !Input::get_singleton()->is_key_pressed(Key::SHIFT)) { EditorNode::get_singleton()->show_warning(vformat(TTR("Can't drop properties because script '%s' is not used in this scene.\nDrop holding 'Shift' to just copy the signature."), get_name())); return; } @@ -2424,12 +2424,12 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da Vector2 pos = _get_pos_in_graph(p_point); #ifdef OSX_ENABLED - bool use_get = Input::get_singleton()->is_key_pressed(KEY_META); + bool use_get = Input::get_singleton()->is_key_pressed(Key::META); #else - bool use_get = Input::get_singleton()->is_key_pressed(KEY_CTRL); + bool use_get = Input::get_singleton()->is_key_pressed(Key::CTRL); #endif - if (!node || Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!node || Input::get_singleton()->is_key_pressed(Key::SHIFT)) { if (use_get) { undo_redo->create_action(TTR("Add Getter Property")); } else { @@ -2587,18 +2587,21 @@ void VisualScriptEditor::reload_text() { String VisualScriptEditor::get_name() { String name; - if (!script->is_built_in()) { - name = script->get_path().get_file(); - if (is_unsaved()) { - if (script->get_path().is_empty()) { - name = TTR("[unsaved]"); - } - name += "(*)"; + name = script->get_path().get_file(); + if (name.is_empty()) { + // This appears for newly created built-in scripts before saving the scene. + name = TTR("[unsaved]"); + } else if (script->is_built_in()) { + const String &script_name = script->get_name(); + if (script_name != "") { + // If the built-in script has a custom resource name defined, + // display the built-in script name as follows: `ResourceName (scene_file.tscn)` + name = vformat("%s (%s)", script_name, name.get_slice("::", 0)); } - } else if (script->get_name() != "") { - name = script->get_name(); - } else { - name = script->get_class() + "(" + itos(script->get_instance_id()) + ")"; + } + + if (is_unsaved()) { + name += "(*)"; } return name; @@ -4551,11 +4554,11 @@ void VisualScriptEditor::free_clipboard() { static void register_editor_callback() { ScriptEditor::register_create_script_editor_function(create_editor); - ED_SHORTCUT("visual_script_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9); - ED_SHORTCUT("visual_script_editor/find_node_type", TTR("Find Node Type"), KEY_MASK_CMD + KEY_F); - ED_SHORTCUT("visual_script_editor/create_function", TTR("Make Function"), KEY_MASK_CMD + KEY_G); - ED_SHORTCUT("visual_script_editor/refresh_nodes", TTR("Refresh Graph"), KEY_MASK_CMD + KEY_R); - ED_SHORTCUT("visual_script_editor/edit_member", TTR("Edit Member"), KEY_MASK_CMD + KEY_E); + ED_SHORTCUT("visual_script_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), Key::F9); + ED_SHORTCUT("visual_script_editor/find_node_type", TTR("Find Node Type"), KeyModifierMask::CMD + Key::F); + ED_SHORTCUT("visual_script_editor/create_function", TTR("Make Function"), KeyModifierMask::CMD + Key::G); + ED_SHORTCUT("visual_script_editor/refresh_nodes", TTR("Refresh Graph"), KeyModifierMask::CMD + Key::R); + ED_SHORTCUT("visual_script_editor/edit_member", TTR("Edit Member"), KeyModifierMask::CMD + Key::E); } void VisualScriptEditor::register_editor() { diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index 9467c2dea4..fd1db2bc43 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -31,11 +31,11 @@ #ifndef VISUALSCRIPT_EDITOR_H #define VISUALSCRIPT_EDITOR_H +#include "../visual_script.h" #include "editor/create_dialog.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/property_editor.h" #include "scene/gui/graph_edit.h" -#include "visual_script.h" #include "visual_script_property_selector.h" class VisualScriptEditorSignalEdit; diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp index d8b88d6cd3..02307b712c 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/editor/visual_script_property_selector.cpp @@ -30,15 +30,15 @@ #include "visual_script_property_selector.h" +#include "../visual_script.h" +#include "../visual_script_builtin_funcs.h" +#include "../visual_script_flow_control.h" +#include "../visual_script_func_nodes.h" +#include "../visual_script_nodes.h" #include "core/os/keyboard.h" #include "editor/doc_tools.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" -#include "modules/visual_script/visual_script.h" -#include "modules/visual_script/visual_script_builtin_funcs.h" -#include "modules/visual_script/visual_script_flow_control.h" -#include "modules/visual_script/visual_script_func_nodes.h" -#include "modules/visual_script/visual_script_nodes.h" #include "scene/main/node.h" #include "scene/main/window.h" @@ -51,10 +51,10 @@ void VisualScriptPropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) { if (k.is_valid()) { switch (k->get_keycode()) { - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: { + case Key::UP: + case Key::DOWN: + case Key::PAGEUP: + case Key::PAGEDOWN: { search_options->gui_input(k); search_box->accept_event(); diff --git a/modules/visual_script/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h index 7a87f3d3ee..7a87f3d3ee 100644 --- a/modules/visual_script/visual_script_property_selector.h +++ b/modules/visual_script/editor/visual_script_property_selector.h diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 890861cf82..6f56fbbc70 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -34,7 +34,6 @@ #include "core/io/resource_loader.h" #include "visual_script.h" #include "visual_script_builtin_funcs.h" -#include "visual_script_editor.h" #include "visual_script_expression.h" #include "visual_script_flow_control.h" #include "visual_script_func_nodes.h" @@ -42,7 +41,9 @@ #include "visual_script_yield_nodes.h" VisualScriptLanguage *visual_script_language = nullptr; + #ifdef TOOLS_ENABLED +#include "editor/visual_script_editor.h" static VisualScriptCustomNodes *vs_custom_nodes_singleton = nullptr; #endif diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 7e01031128..e6cc25f6bd 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -71,8 +71,9 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "randomize", "randi", "randf", - "randf_range", "randi_range", + "randf_range", + "randfn", "seed", "rand_seed", "deg2rad", @@ -81,6 +82,7 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX "db2linear", "wrapi", "wrapf", + "pingpong", "max", "min", "clamp", @@ -190,11 +192,13 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) { case MATH_FMOD: case MATH_FPOSMOD: case MATH_POSMOD: + case MATH_PINGPONG: case MATH_POW: case MATH_EASE: case MATH_SNAPPED: - case MATH_RANDF_RANGE: case MATH_RANDI_RANGE: + case MATH_RANDF_RANGE: + case MATH_RANDFN: case LOGIC_MAX: case LOGIC_MIN: case TYPE_CONVERT: @@ -351,6 +355,13 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const case MATH_RANDI: case MATH_RANDF: { } break; + case MATH_RANDI_RANGE: { + if (p_idx == 0) { + return PropertyInfo(Variant::INT, "from"); + } else { + return PropertyInfo(Variant::INT, "to"); + } + } break; case MATH_RANDF_RANGE: { if (p_idx == 0) { return PropertyInfo(Variant::FLOAT, "from"); @@ -358,11 +369,11 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const return PropertyInfo(Variant::FLOAT, "to"); } } break; - case MATH_RANDI_RANGE: { + case MATH_RANDFN: { if (p_idx == 0) { - return PropertyInfo(Variant::INT, "from"); + return PropertyInfo(Variant::FLOAT, "mean"); } else { - return PropertyInfo(Variant::INT, "to"); + return PropertyInfo(Variant::FLOAT, "deviation"); } } break; case MATH_SEED: @@ -381,6 +392,13 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const case MATH_DB2LINEAR: { return PropertyInfo(Variant::FLOAT, "db"); } break; + case MATH_PINGPONG: { + if (p_idx == 0) { + return PropertyInfo(Variant::FLOAT, "value"); + } else { + return PropertyInfo(Variant::FLOAT, "length"); + } + } break; case MATH_WRAP: { if (p_idx == 0) { return PropertyInfo(Variant::INT, "value"); @@ -518,6 +536,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons t = Variant::INT; } break; case MATH_RANDF: + case MATH_RANDFN: case MATH_RANDF_RANGE: { t = Variant::FLOAT; } break; @@ -537,6 +556,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons case MATH_RAD2DEG: case MATH_LINEAR2DB: case MATH_WRAPF: + case MATH_PINGPONG: case MATH_DB2LINEAR: { t = Variant::FLOAT; } break; @@ -859,6 +879,11 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in VALIDATE_ARG_NUM(0); *r_return = Math::db2linear((double)*p_inputs[0]); } break; + case VisualScriptBuiltinFunc::MATH_PINGPONG: { + VALIDATE_ARG_NUM(0); + VALIDATE_ARG_NUM(1); + *r_return = Math::pingpong((double)*p_inputs[0], (double)*p_inputs[1]); + } break; case VisualScriptBuiltinFunc::MATH_WRAP: { VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); @@ -1196,8 +1221,9 @@ void VisualScriptBuiltinFunc::_bind_methods() { BIND_ENUM_CONSTANT(MATH_RANDOMIZE); BIND_ENUM_CONSTANT(MATH_RANDI); BIND_ENUM_CONSTANT(MATH_RANDF); - BIND_ENUM_CONSTANT(MATH_RANDF_RANGE); BIND_ENUM_CONSTANT(MATH_RANDI_RANGE); + BIND_ENUM_CONSTANT(MATH_RANDF_RANGE); + BIND_ENUM_CONSTANT(MATH_RANDFN); BIND_ENUM_CONSTANT(MATH_SEED); BIND_ENUM_CONSTANT(MATH_RANDSEED); BIND_ENUM_CONSTANT(MATH_DEG2RAD); @@ -1206,6 +1232,7 @@ void VisualScriptBuiltinFunc::_bind_methods() { BIND_ENUM_CONSTANT(MATH_DB2LINEAR); BIND_ENUM_CONSTANT(MATH_WRAP); BIND_ENUM_CONSTANT(MATH_WRAPF); + BIND_ENUM_CONSTANT(MATH_PINGPONG); BIND_ENUM_CONSTANT(LOGIC_MAX); BIND_ENUM_CONSTANT(LOGIC_MIN); BIND_ENUM_CONSTANT(LOGIC_CLAMP); @@ -1285,8 +1312,9 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randi", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDI>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF>); - VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf_range", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF_RANGE>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randi_range", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDI_RANGE>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf_range", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF_RANGE>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/randfn", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDFN>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/seed", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SEED>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/randseed", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDSEED>); @@ -1296,6 +1324,7 @@ void register_visual_script_builtin_func_node() { VisualScriptLanguage::singleton->add_register_func("functions/built_in/db2linear", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DB2LINEAR>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/wrapi", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_WRAP>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/wrapf", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_WRAPF>); + VisualScriptLanguage::singleton->add_register_func("functions/built_in/pingpong", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_PINGPONG>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/max", create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MAX>); VisualScriptLanguage::singleton->add_register_func("functions/built_in/min", create_builtin_func_node<VisualScriptBuiltinFunc::LOGIC_MIN>); diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index f9eb7e983f..f71a053f7d 100644 --- a/modules/visual_script/visual_script_builtin_funcs.h +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -71,8 +71,9 @@ public: MATH_RANDOMIZE, MATH_RANDI, MATH_RANDF, - MATH_RANDF_RANGE, MATH_RANDI_RANGE, + MATH_RANDF_RANGE, + MATH_RANDFN, MATH_SEED, MATH_RANDSEED, MATH_DEG2RAD, @@ -81,6 +82,7 @@ public: MATH_DB2LINEAR, MATH_WRAP, MATH_WRAPF, + MATH_PINGPONG, LOGIC_MAX, LOGIC_MIN, LOGIC_CLAMP, diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp index 33ee6cf359..be9f880103 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp @@ -57,7 +57,7 @@ String ResourceImporterOGGVorbis::get_resource_type() const { return "AudioStreamOGGVorbis"; } -bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { +bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const { return true; } @@ -69,7 +69,7 @@ String ResourceImporterOGGVorbis::get_preset_name(int p_idx) const { return String(); } -void ResourceImporterOGGVorbis::get_import_options(List<ImportOption> *r_options, int p_preset) const { +void ResourceImporterOGGVorbis::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); } diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h index acdc1a3d38..8565e0deb8 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.h +++ b/modules/vorbis/resource_importer_ogg_vorbis.h @@ -51,8 +51,8 @@ public: virtual String get_visible_name() const override; virtual int get_preset_count() const override; virtual String get_preset_name(int p_idx) const override; - virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; - virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; + virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp index e03375e8d9..dc259da886 100644 --- a/platform/android/android_input_handler.cpp +++ b/platform/android/android_input_handler.cpp @@ -45,7 +45,7 @@ void AndroidInputHandler::process_joy_event(AndroidInputHandler::JoypadEvent p_e Input::get_singleton()->joy_axis(p_event.device, (JoyAxis)p_event.index, value); break; case JOY_EVENT_HAT: - Input::get_singleton()->joy_hat(p_event.device, (HatMask)p_event.hat); + Input::get_singleton()->joy_hat(p_event.device, p_event.hat); break; default: return; @@ -82,37 +82,37 @@ void AndroidInputHandler::process_key_event(int p_keycode, int p_scancode, int p Ref<InputEventKey> ev; ev.instantiate(); int val = unicode; - int keycode = android_get_keysym(p_keycode); - int phy_keycode = android_get_keysym(p_scancode); + Key keycode = android_get_keysym(p_keycode); + Key phy_keycode = android_get_keysym(p_scancode); - if (keycode == KEY_SHIFT) { + if (keycode == Key::SHIFT) { shift_mem = p_pressed; } - if (keycode == KEY_ALT) { + if (keycode == Key::ALT) { alt_mem = p_pressed; } - if (keycode == KEY_CTRL) { + if (keycode == Key::CTRL) { control_mem = p_pressed; } - if (keycode == KEY_META) { + if (keycode == Key::META) { meta_mem = p_pressed; } - ev->set_keycode((Key)keycode); - ev->set_physical_keycode((Key)phy_keycode); + ev->set_keycode(keycode); + ev->set_physical_keycode(phy_keycode); ev->set_unicode(val); ev->set_pressed(p_pressed); _set_key_modifier_state(ev); if (val == '\n') { - ev->set_keycode(KEY_ENTER); + ev->set_keycode(Key::ENTER); } else if (val == 61448) { - ev->set_keycode(KEY_BACKSPACE); - ev->set_unicode(KEY_BACKSPACE); + ev->set_keycode(Key::BACKSPACE); + ev->set_unicode((char32_t)Key::BACKSPACE); } else if (val == 61453) { - ev->set_keycode(KEY_ENTER); - ev->set_unicode(KEY_ENTER); + ev->set_keycode(Key::ENTER); + ev->set_unicode((char32_t)Key::ENTER); } else if (p_keycode == 4) { if (DisplayServerAndroid *dsa = Object::cast_to<DisplayServerAndroid>(DisplayServer::get_singleton())) { dsa->send_window_event(DisplayServer::WINDOW_EVENT_GO_BACK_REQUEST, true); @@ -305,15 +305,15 @@ void AndroidInputHandler::process_mouse_event(int input_device, int event_action ev->set_pressed(true); buttons_state = event_buttons_mask; if (event_vertical_factor > 0) { - _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_UP, event_vertical_factor); + _wheel_button_click(event_buttons_mask, ev, MouseButton::WHEEL_UP, event_vertical_factor); } else if (event_vertical_factor < 0) { - _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_DOWN, -event_vertical_factor); + _wheel_button_click(event_buttons_mask, ev, MouseButton::WHEEL_DOWN, -event_vertical_factor); } if (event_horizontal_factor > 0) { - _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_RIGHT, event_horizontal_factor); + _wheel_button_click(event_buttons_mask, ev, MouseButton::WHEEL_RIGHT, event_horizontal_factor); } else if (event_horizontal_factor < 0) { - _wheel_button_click(event_buttons_mask, ev, MOUSE_BUTTON_WHEEL_LEFT, -event_horizontal_factor); + _wheel_button_click(event_buttons_mask, ev, MouseButton::WHEEL_LEFT, -event_horizontal_factor); } } break; } @@ -323,7 +323,7 @@ void AndroidInputHandler::_wheel_button_click(MouseButton event_buttons_mask, co Ref<InputEventMouseButton> evd = ev->duplicate(); _set_key_modifier_state(evd); evd->set_button_index(wheel_button); - evd->set_button_mask(MouseButton(event_buttons_mask ^ (1 << (wheel_button - 1)))); + evd->set_button_mask(MouseButton(event_buttons_mask ^ mouse_button_to_mask(wheel_button))); evd->set_factor(factor); Input::get_singleton()->parse_input_event(evd); Ref<InputEventMouseButton> evdd = evd->duplicate(); @@ -339,7 +339,7 @@ void AndroidInputHandler::process_double_tap(int event_android_button_mask, Poin _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_global_position(p_pos); - ev->set_pressed(event_button_mask != 0); + ev->set_pressed(event_button_mask != MouseButton::NONE); ev->set_button_index(_button_index_from_mask(event_button_mask)); ev->set_button_mask(event_button_mask); ev->set_double_click(true); @@ -348,37 +348,37 @@ void AndroidInputHandler::process_double_tap(int event_android_button_mask, Poin MouseButton AndroidInputHandler::_button_index_from_mask(MouseButton button_mask) { switch (button_mask) { - case MOUSE_BUTTON_MASK_LEFT: - return MOUSE_BUTTON_LEFT; - case MOUSE_BUTTON_MASK_RIGHT: - return MOUSE_BUTTON_RIGHT; - case MOUSE_BUTTON_MASK_MIDDLE: - return MOUSE_BUTTON_MIDDLE; - case MOUSE_BUTTON_MASK_XBUTTON1: - return MOUSE_BUTTON_XBUTTON1; - case MOUSE_BUTTON_MASK_XBUTTON2: - return MOUSE_BUTTON_XBUTTON2; + case MouseButton::MASK_LEFT: + return MouseButton::LEFT; + case MouseButton::MASK_RIGHT: + return MouseButton::RIGHT; + case MouseButton::MASK_MIDDLE: + return MouseButton::MIDDLE; + case MouseButton::MASK_XBUTTON1: + return MouseButton::MB_XBUTTON1; + case MouseButton::MASK_XBUTTON2: + return MouseButton::MB_XBUTTON2; default: - return MOUSE_BUTTON_NONE; + return MouseButton::NONE; } } MouseButton AndroidInputHandler::_android_button_mask_to_godot_button_mask(int android_button_mask) { - MouseButton godot_button_mask = MOUSE_BUTTON_NONE; + MouseButton godot_button_mask = MouseButton::NONE; if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) { - godot_button_mask |= MOUSE_BUTTON_MASK_LEFT; + godot_button_mask |= MouseButton::MASK_LEFT; } if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { - godot_button_mask |= MOUSE_BUTTON_MASK_RIGHT; + godot_button_mask |= MouseButton::MASK_RIGHT; } if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) { - godot_button_mask |= MOUSE_BUTTON_MASK_MIDDLE; + godot_button_mask |= MouseButton::MASK_MIDDLE; } if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) { - godot_button_mask |= MOUSE_BUTTON_MASK_XBUTTON1; + godot_button_mask |= MouseButton::MASK_XBUTTON1; } if (android_button_mask & AMOTION_EVENT_BUTTON_FORWARD) { - godot_button_mask |= MOUSE_BUTTON_MASK_XBUTTON2; + godot_button_mask |= MouseButton::MASK_XBUTTON2; } return godot_button_mask; diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h index 2918ca300b..e0b4196f14 100644 --- a/platform/android/android_input_handler.h +++ b/platform/android/android_input_handler.h @@ -53,10 +53,10 @@ public: struct JoypadEvent { int device = 0; int type = 0; - int index = 0; + int index = 0; // Can be either JoyAxis or JoyButton. bool pressed = false; float value = 0; - int hat = 0; + HatMask hat = HatMask::CENTER; }; private: @@ -65,7 +65,7 @@ private: bool control_mem = false; bool meta_mem = false; - MouseButton buttons_state = MOUSE_BUTTON_NONE; + MouseButton buttons_state = MouseButton::NONE; Vector<TouchPos> touch; Point2 hover_prev_pos; // needed to calculate the relative position on hover events diff --git a/platform/android/android_keys_utils.cpp b/platform/android/android_keys_utils.cpp index 5aa546c17b..0cea0589ce 100644 --- a/platform/android/android_keys_utils.cpp +++ b/platform/android/android_keys_utils.cpp @@ -30,12 +30,12 @@ #include "android_keys_utils.h" -unsigned int android_get_keysym(unsigned int p_code) { - for (int i = 0; _ak_to_keycode[i].keysym != KEY_UNKNOWN; i++) { +Key android_get_keysym(unsigned int p_code) { + for (int i = 0; _ak_to_keycode[i].keysym != Key::UNKNOWN; i++) { if (_ak_to_keycode[i].keycode == p_code) { return _ak_to_keycode[i].keysym; } } - return KEY_UNKNOWN; + return Key::UNKNOWN; } diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h index de6f48d33a..bac9bab6db 100644 --- a/platform/android/android_keys_utils.h +++ b/platform/android/android_keys_utils.h @@ -35,101 +35,101 @@ #include <core/os/keyboard.h> struct _WinTranslatePair { - unsigned int keysym = 0; + Key keysym = Key::NONE; unsigned int keycode = 0; }; static _WinTranslatePair _ak_to_keycode[] = { - { KEY_TAB, AKEYCODE_TAB }, - { KEY_ENTER, AKEYCODE_ENTER }, - { KEY_SHIFT, AKEYCODE_SHIFT_LEFT }, - { KEY_SHIFT, AKEYCODE_SHIFT_RIGHT }, - { KEY_ALT, AKEYCODE_ALT_LEFT }, - { KEY_ALT, AKEYCODE_ALT_RIGHT }, - { KEY_MENU, AKEYCODE_MENU }, - { KEY_PAUSE, AKEYCODE_MEDIA_PLAY_PAUSE }, - { KEY_ESCAPE, AKEYCODE_BACK }, - { KEY_SPACE, AKEYCODE_SPACE }, - { KEY_PAGEUP, AKEYCODE_PAGE_UP }, - { KEY_PAGEDOWN, AKEYCODE_PAGE_DOWN }, - { KEY_HOME, AKEYCODE_HOME }, //(0x24) - { KEY_LEFT, AKEYCODE_DPAD_LEFT }, - { KEY_UP, AKEYCODE_DPAD_UP }, - { KEY_RIGHT, AKEYCODE_DPAD_RIGHT }, - { KEY_DOWN, AKEYCODE_DPAD_DOWN }, - { KEY_PERIODCENTERED, AKEYCODE_DPAD_CENTER }, - { KEY_BACKSPACE, AKEYCODE_DEL }, - { KEY_0, AKEYCODE_0 }, ////0 key - { KEY_1, AKEYCODE_1 }, ////1 key - { KEY_2, AKEYCODE_2 }, ////2 key - { KEY_3, AKEYCODE_3 }, ////3 key - { KEY_4, AKEYCODE_4 }, ////4 key - { KEY_5, AKEYCODE_5 }, ////5 key - { KEY_6, AKEYCODE_6 }, ////6 key - { KEY_7, AKEYCODE_7 }, ////7 key - { KEY_8, AKEYCODE_8 }, ////8 key - { KEY_9, AKEYCODE_9 }, ////9 key - { KEY_A, AKEYCODE_A }, ////A key - { KEY_B, AKEYCODE_B }, ////B key - { KEY_C, AKEYCODE_C }, ////C key - { KEY_D, AKEYCODE_D }, ////D key - { KEY_E, AKEYCODE_E }, ////E key - { KEY_F, AKEYCODE_F }, ////F key - { KEY_G, AKEYCODE_G }, ////G key - { KEY_H, AKEYCODE_H }, ////H key - { KEY_I, AKEYCODE_I }, ////I key - { KEY_J, AKEYCODE_J }, ////J key - { KEY_K, AKEYCODE_K }, ////K key - { KEY_L, AKEYCODE_L }, ////L key - { KEY_M, AKEYCODE_M }, ////M key - { KEY_N, AKEYCODE_N }, ////N key - { KEY_O, AKEYCODE_O }, ////O key - { KEY_P, AKEYCODE_P }, ////P key - { KEY_Q, AKEYCODE_Q }, ////Q key - { KEY_R, AKEYCODE_R }, ////R key - { KEY_S, AKEYCODE_S }, ////S key - { KEY_T, AKEYCODE_T }, ////T key - { KEY_U, AKEYCODE_U }, ////U key - { KEY_V, AKEYCODE_V }, ////V key - { KEY_W, AKEYCODE_W }, ////W key - { KEY_X, AKEYCODE_X }, ////X key - { KEY_Y, AKEYCODE_Y }, ////Y key - { KEY_Z, AKEYCODE_Z }, ////Z key - { KEY_HOMEPAGE, AKEYCODE_EXPLORER }, - { KEY_LAUNCH0, AKEYCODE_BUTTON_A }, - { KEY_LAUNCH1, AKEYCODE_BUTTON_B }, - { KEY_LAUNCH2, AKEYCODE_BUTTON_C }, - { KEY_LAUNCH3, AKEYCODE_BUTTON_X }, - { KEY_LAUNCH4, AKEYCODE_BUTTON_Y }, - { KEY_LAUNCH5, AKEYCODE_BUTTON_Z }, - { KEY_LAUNCH6, AKEYCODE_BUTTON_L1 }, - { KEY_LAUNCH7, AKEYCODE_BUTTON_R1 }, - { KEY_LAUNCH8, AKEYCODE_BUTTON_L2 }, - { KEY_LAUNCH9, AKEYCODE_BUTTON_R2 }, - { KEY_LAUNCHA, AKEYCODE_BUTTON_THUMBL }, - { KEY_LAUNCHB, AKEYCODE_BUTTON_THUMBR }, - { KEY_LAUNCHC, AKEYCODE_BUTTON_START }, - { KEY_LAUNCHD, AKEYCODE_BUTTON_SELECT }, - { KEY_LAUNCHE, AKEYCODE_BUTTON_MODE }, - { KEY_VOLUMEMUTE, AKEYCODE_MUTE }, - { KEY_VOLUMEDOWN, AKEYCODE_VOLUME_DOWN }, - { KEY_VOLUMEUP, AKEYCODE_VOLUME_UP }, - { KEY_BACK, AKEYCODE_MEDIA_REWIND }, - { KEY_FORWARD, AKEYCODE_MEDIA_FAST_FORWARD }, - { KEY_MEDIANEXT, AKEYCODE_MEDIA_NEXT }, - { KEY_MEDIAPREVIOUS, AKEYCODE_MEDIA_PREVIOUS }, - { KEY_MEDIASTOP, AKEYCODE_MEDIA_STOP }, - { KEY_PLUS, AKEYCODE_PLUS }, - { KEY_EQUAL, AKEYCODE_EQUALS }, // the '+' key - { KEY_COMMA, AKEYCODE_COMMA }, // the ',' key - { KEY_MINUS, AKEYCODE_MINUS }, // the '-' key - { KEY_SLASH, AKEYCODE_SLASH }, // the '/?' key - { KEY_BACKSLASH, AKEYCODE_BACKSLASH }, - { KEY_BRACKETLEFT, AKEYCODE_LEFT_BRACKET }, - { KEY_BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET }, - { KEY_CTRL, AKEYCODE_CTRL_LEFT }, - { KEY_CTRL, AKEYCODE_CTRL_RIGHT }, - { KEY_UNKNOWN, 0 } + { Key::TAB, AKEYCODE_TAB }, + { Key::ENTER, AKEYCODE_ENTER }, + { Key::SHIFT, AKEYCODE_SHIFT_LEFT }, + { Key::SHIFT, AKEYCODE_SHIFT_RIGHT }, + { Key::ALT, AKEYCODE_ALT_LEFT }, + { Key::ALT, AKEYCODE_ALT_RIGHT }, + { Key::MENU, AKEYCODE_MENU }, + { Key::PAUSE, AKEYCODE_MEDIA_PLAY_PAUSE }, + { Key::ESCAPE, AKEYCODE_BACK }, + { Key::SPACE, AKEYCODE_SPACE }, + { Key::PAGEUP, AKEYCODE_PAGE_UP }, + { Key::PAGEDOWN, AKEYCODE_PAGE_DOWN }, + { Key::HOME, AKEYCODE_HOME }, //(0x24) + { Key::LEFT, AKEYCODE_DPAD_LEFT }, + { Key::UP, AKEYCODE_DPAD_UP }, + { Key::RIGHT, AKEYCODE_DPAD_RIGHT }, + { Key::DOWN, AKEYCODE_DPAD_DOWN }, + { Key::PERIODCENTERED, AKEYCODE_DPAD_CENTER }, + { Key::BACKSPACE, AKEYCODE_DEL }, + { Key::KEY_0, AKEYCODE_0 }, + { Key::KEY_1, AKEYCODE_1 }, + { Key::KEY_2, AKEYCODE_2 }, + { Key::KEY_3, AKEYCODE_3 }, + { Key::KEY_4, AKEYCODE_4 }, + { Key::KEY_5, AKEYCODE_5 }, + { Key::KEY_6, AKEYCODE_6 }, + { Key::KEY_7, AKEYCODE_7 }, + { Key::KEY_8, AKEYCODE_8 }, + { Key::KEY_9, AKEYCODE_9 }, + { Key::A, AKEYCODE_A }, + { Key::B, AKEYCODE_B }, + { Key::C, AKEYCODE_C }, + { Key::D, AKEYCODE_D }, + { Key::E, AKEYCODE_E }, + { Key::F, AKEYCODE_F }, + { Key::G, AKEYCODE_G }, + { Key::H, AKEYCODE_H }, + { Key::I, AKEYCODE_I }, + { Key::J, AKEYCODE_J }, + { Key::K, AKEYCODE_K }, + { Key::L, AKEYCODE_L }, + { Key::M, AKEYCODE_M }, + { Key::N, AKEYCODE_N }, + { Key::O, AKEYCODE_O }, + { Key::P, AKEYCODE_P }, + { Key::Q, AKEYCODE_Q }, + { Key::R, AKEYCODE_R }, + { Key::S, AKEYCODE_S }, + { Key::T, AKEYCODE_T }, + { Key::U, AKEYCODE_U }, + { Key::V, AKEYCODE_V }, + { Key::W, AKEYCODE_W }, + { Key::X, AKEYCODE_X }, + { Key::Y, AKEYCODE_Y }, + { Key::Z, AKEYCODE_Z }, + { Key::HOMEPAGE, AKEYCODE_EXPLORER }, + { Key::LAUNCH0, AKEYCODE_BUTTON_A }, + { Key::LAUNCH1, AKEYCODE_BUTTON_B }, + { Key::LAUNCH2, AKEYCODE_BUTTON_C }, + { Key::LAUNCH3, AKEYCODE_BUTTON_X }, + { Key::LAUNCH4, AKEYCODE_BUTTON_Y }, + { Key::LAUNCH5, AKEYCODE_BUTTON_Z }, + { Key::LAUNCH6, AKEYCODE_BUTTON_L1 }, + { Key::LAUNCH7, AKEYCODE_BUTTON_R1 }, + { Key::LAUNCH8, AKEYCODE_BUTTON_L2 }, + { Key::LAUNCH9, AKEYCODE_BUTTON_R2 }, + { Key::LAUNCHA, AKEYCODE_BUTTON_THUMBL }, + { Key::LAUNCHB, AKEYCODE_BUTTON_THUMBR }, + { Key::LAUNCHC, AKEYCODE_BUTTON_START }, + { Key::LAUNCHD, AKEYCODE_BUTTON_SELECT }, + { Key::LAUNCHE, AKEYCODE_BUTTON_MODE }, + { Key::VOLUMEMUTE, AKEYCODE_MUTE }, + { Key::VOLUMEDOWN, AKEYCODE_VOLUME_DOWN }, + { Key::VOLUMEUP, AKEYCODE_VOLUME_UP }, + { Key::BACK, AKEYCODE_MEDIA_REWIND }, + { Key::FORWARD, AKEYCODE_MEDIA_FAST_FORWARD }, + { Key::MEDIANEXT, AKEYCODE_MEDIA_NEXT }, + { Key::MEDIAPREVIOUS, AKEYCODE_MEDIA_PREVIOUS }, + { Key::MEDIASTOP, AKEYCODE_MEDIA_STOP }, + { Key::PLUS, AKEYCODE_PLUS }, + { Key::EQUAL, AKEYCODE_EQUALS }, // the '+' key + { Key::COMMA, AKEYCODE_COMMA }, // the ',' key + { Key::MINUS, AKEYCODE_MINUS }, // the '-' key + { Key::SLASH, AKEYCODE_SLASH }, // the '/?' key + { Key::BACKSLASH, AKEYCODE_BACKSLASH }, + { Key::BRACKETLEFT, AKEYCODE_LEFT_BRACKET }, + { Key::BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET }, + { Key::CTRL, AKEYCODE_CTRL_LEFT }, + { Key::CTRL, AKEYCODE_CTRL_RIGHT }, + { Key::UNKNOWN, 0 } }; /* TODO: map these android key: @@ -157,6 +157,6 @@ TODO: map these android key: AKEYCODE_SWITCH_CHARSET = 95, */ -unsigned int android_get_keysym(unsigned int p_code); +Key android_get_keysym(unsigned int p_code); #endif // ANDROID_KEYS_UTILS_H diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 4c45be5210..18e9e20948 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -1667,7 +1667,6 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_background_option, PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/depth_buffer_bits", PROPERTY_HINT_ENUM, "16 bits,24 bits [default],32 bits"), 1)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/opengl_debug"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0)); @@ -2209,12 +2208,6 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP command_line_strings.push_back("--xr_mode_regular"); } - int depth_buffer_bits_index = p_preset->get("graphics/depth_buffer_bits"); - if (depth_buffer_bits_index >= 0 && depth_buffer_bits_index <= 2) { - int depth_buffer_bits = 16 + depth_buffer_bits_index * 8; - command_line_strings.push_back(vformat("--use_depth=%d", depth_buffer_bits)); - } - bool immersive = p_preset->get("screen/immersive_mode"); if (immersive) { command_line_strings.push_back("--use_immersive"); diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index d872d5ed8a..b6476fa61a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -119,7 +119,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC private Button mWiFiSettingsButton; private XRMode xrMode = XRMode.REGULAR; - private int depth_buffer_bits = 24; private boolean use_immersive = false; private boolean use_debug_opengl = false; private boolean mStatePaused; @@ -266,8 +265,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC if (videoDriver.equals("vulkan")) { mRenderView = new GodotVulkanRenderView(activity, this); } else { - mRenderView = new GodotGLRenderView(activity, this, xrMode, depth_buffer_bits, - use_debug_opengl); + mRenderView = new GodotGLRenderView(activity, this, xrMode, use_debug_opengl); } View view = mRenderView.getView(); @@ -506,12 +504,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC xrMode = XRMode.REGULAR; } else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) { xrMode = XRMode.OVR; - } else if (command_line[i].startsWith("--use_depth=")) { - try { - depth_buffer_bits = Integer.parseInt(command_line[i].split("=")[1]); - } catch (Exception e) { - e.printStackTrace(); - } } else if (command_line[i].equals("--debug_opengl")) { use_debug_opengl = true; } else if (command_line[i].equals("--use_immersive")) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index 8b77302491..088b048502 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -78,10 +78,8 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView private final GodotRenderer godotRenderer; private PointerIcon pointerIcon; - public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, int p_depth_buffer_bits, - boolean p_use_debug_opengl) { + public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_debug_opengl) { super(context); - GLUtils.depth_buffer_bits = p_depth_buffer_bits; GLUtils.use_debug_opengl = p_use_debug_opengl; this.godot = godot; @@ -91,7 +89,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { pointerIcon = PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT); } - init(xrMode, false, 16, 0); + init(xrMode, false); } @Override @@ -172,7 +170,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView return pointerIcon; } - private void init(XRMode xrMode, boolean translucent, int depth, int stencil) { + private void init(XRMode xrMode, boolean translucent) { setPreserveEGLContextOnPause(true); setFocusableInTouchMode(true); switch (xrMode) { @@ -209,16 +207,9 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView * below. */ - RegularConfigChooser configChooser = - new RegularFallbackConfigChooser(8, 8, 8, 8, 16, stencil, - new RegularConfigChooser(5, 6, 5, 0, 16, stencil)); - if (GLUtils.depth_buffer_bits >= 24) { - configChooser = new RegularFallbackConfigChooser(8, 8, 8, 8, 24, stencil, configChooser); - if (GLUtils.depth_buffer_bits >= 32) { - configChooser = new RegularFallbackConfigChooser(8, 8, 8, 8, 32, stencil, configChooser); - } - } - setEGLConfigChooser(configChooser); + setEGLConfigChooser( + new RegularFallbackConfigChooser(8, 8, 8, 8, 24, 0, + new RegularConfigChooser(8, 8, 8, 8, 16, 0))); break; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/GLUtils.java b/platform/android/java/lib/src/org/godotengine/godot/utils/GLUtils.java index 0d581785ab..09820fad5f 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/GLUtils.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/GLUtils.java @@ -44,7 +44,6 @@ public class GLUtils { public static final boolean DEBUG = false; - public static int depth_buffer_bits; // No need to reiterate the default here public static boolean use_debug_opengl = false; private static final String[] ATTRIBUTES_NAMES = new String[] { diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index c7f19e4be2..3236512f5c 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -317,8 +317,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env // Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value) { - if (step.get() <= 0) + if (step.get() <= 0) { return; + } AndroidInputHandler::JoypadEvent jevent; jevent.device = p_device; @@ -331,24 +332,27 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, // Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jclass clazz, jint p_device, jint p_hat_x, jint p_hat_y) { - if (step.get() <= 0) + if (step.get() <= 0) { return; + } AndroidInputHandler::JoypadEvent jevent; jevent.device = p_device; jevent.type = AndroidInputHandler::JOY_EVENT_HAT; - int hat = 0; + HatMask hat = HatMask::CENTER; if (p_hat_x != 0) { - if (p_hat_x < 0) - hat |= HatMask::HAT_MASK_LEFT; - else - hat |= HatMask::HAT_MASK_RIGHT; + if (p_hat_x < 0) { + hat |= HatMask::LEFT; + } else { + hat |= HatMask::RIGHT; + } } if (p_hat_y != 0) { - if (p_hat_y < 0) - hat |= HatMask::HAT_MASK_UP; - else - hat |= HatMask::HAT_MASK_DOWN; + if (p_hat_y < 0) { + hat |= HatMask::UP; + } else { + hat |= HatMask::DOWN; + } } jevent.hat = hat; diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm index 7d13a08d39..b746c60d4e 100644 --- a/platform/iphone/display_server_iphone.mm +++ b/platform/iphone/display_server_iphone.mm @@ -261,7 +261,7 @@ void DisplayServerIPhone::key(Key p_key, bool p_pressed) { ev->set_pressed(p_pressed); ev->set_keycode(p_key); ev->set_physical_keycode(p_key); - ev->set_unicode(p_key); + ev->set_unicode((char32_t)p_key); perform_event(ev); }; diff --git a/platform/iphone/joypad_iphone.mm b/platform/iphone/joypad_iphone.mm index 45842b38aa..1bf5462d91 100644 --- a/platform/iphone/joypad_iphone.mm +++ b/platform/iphone/joypad_iphone.mm @@ -259,31 +259,31 @@ void JoypadIPhone::start_processing() { int joy_id = [self getJoyIdForController:controller]; if (element == gamepad.buttonA) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_A, + Input::get_singleton()->joy_button(joy_id, JoyButton::A, gamepad.buttonA.isPressed); } else if (element == gamepad.buttonB) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_B, + Input::get_singleton()->joy_button(joy_id, JoyButton::B, gamepad.buttonB.isPressed); } else if (element == gamepad.buttonX) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_X, + Input::get_singleton()->joy_button(joy_id, JoyButton::X, gamepad.buttonX.isPressed); } else if (element == gamepad.buttonY) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_Y, + Input::get_singleton()->joy_button(joy_id, JoyButton::Y, gamepad.buttonY.isPressed); } else if (element == gamepad.leftShoulder) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_LEFT_SHOULDER, + Input::get_singleton()->joy_button(joy_id, JoyButton::LEFT_SHOULDER, gamepad.leftShoulder.isPressed); } else if (element == gamepad.rightShoulder) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_RIGHT_SHOULDER, + Input::get_singleton()->joy_button(joy_id, JoyButton::RIGHT_SHOULDER, gamepad.rightShoulder.isPressed); } else if (element == gamepad.dpad) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_DPAD_UP, + Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_UP, gamepad.dpad.up.isPressed); - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_DPAD_DOWN, + Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_DOWN, gamepad.dpad.down.isPressed); - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_DPAD_LEFT, + Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_LEFT, gamepad.dpad.left.isPressed); - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_DPAD_RIGHT, + Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_RIGHT, gamepad.dpad.right.isPressed); }; @@ -291,20 +291,20 @@ void JoypadIPhone::start_processing() { jx.min = -1; if (element == gamepad.leftThumbstick) { jx.value = gamepad.leftThumbstick.xAxis.value; - Input::get_singleton()->joy_axis(joy_id, JOY_AXIS_LEFT_X, jx); + Input::get_singleton()->joy_axis(joy_id, JoyAxis::LEFT_X, jx); jx.value = -gamepad.leftThumbstick.yAxis.value; - Input::get_singleton()->joy_axis(joy_id, JOY_AXIS_LEFT_Y, jx); + Input::get_singleton()->joy_axis(joy_id, JoyAxis::LEFT_Y, jx); } else if (element == gamepad.rightThumbstick) { jx.value = gamepad.rightThumbstick.xAxis.value; - Input::get_singleton()->joy_axis(joy_id, JOY_AXIS_RIGHT_X, jx); + Input::get_singleton()->joy_axis(joy_id, JoyAxis::RIGHT_X, jx); jx.value = -gamepad.rightThumbstick.yAxis.value; - Input::get_singleton()->joy_axis(joy_id, JOY_AXIS_RIGHT_Y, jx); + Input::get_singleton()->joy_axis(joy_id, JoyAxis::RIGHT_Y, jx); } else if (element == gamepad.leftTrigger) { jx.value = gamepad.leftTrigger.value; - Input::get_singleton()->joy_axis(joy_id, JOY_AXIS_TRIGGER_LEFT, jx); + Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_LEFT, jx); } else if (element == gamepad.rightTrigger) { jx.value = gamepad.rightTrigger.value; - Input::get_singleton()->joy_axis(joy_id, JOY_AXIS_TRIGGER_RIGHT, jx); + Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, jx); }; }; } else if (controller.microGamepad != nil) { @@ -319,18 +319,18 @@ void JoypadIPhone::start_processing() { int joy_id = [self getJoyIdForController:controller]; if (element == gamepad.buttonA) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_A, + Input::get_singleton()->joy_button(joy_id, JoyButton::A, gamepad.buttonA.isPressed); } else if (element == gamepad.buttonX) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_X, + Input::get_singleton()->joy_button(joy_id, JoyButton::X, gamepad.buttonX.isPressed); } else if (element == gamepad.dpad) { - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_DPAD_UP, + Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_UP, gamepad.dpad.up.isPressed); - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_DPAD_DOWN, + Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_DOWN, gamepad.dpad.down.isPressed); - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_DPAD_LEFT, gamepad.dpad.left.isPressed); - Input::get_singleton()->joy_button(joy_id, JOY_BUTTON_DPAD_RIGHT, gamepad.dpad.right.isPressed); + Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_LEFT, gamepad.dpad.left.isPressed); + Input::get_singleton()->joy_button(joy_id, JoyButton::DPAD_RIGHT, gamepad.dpad.right.isPressed); }; }; } diff --git a/platform/iphone/keyboard_input_view.mm b/platform/iphone/keyboard_input_view.mm index e2bd0acff4..b11d04181e 100644 --- a/platform/iphone/keyboard_input_view.mm +++ b/platform/iphone/keyboard_input_view.mm @@ -115,8 +115,8 @@ - (void)deleteText:(NSInteger)charactersToDelete { for (int i = 0; i < charactersToDelete; i++) { - DisplayServerIPhone::get_singleton()->key(KEY_BACKSPACE, true); - DisplayServerIPhone::get_singleton()->key(KEY_BACKSPACE, false); + DisplayServerIPhone::get_singleton()->key(Key::BACKSPACE, true); + DisplayServerIPhone::get_singleton()->key(Key::BACKSPACE, false); } } @@ -129,10 +129,10 @@ switch (character) { case 10: - character = KEY_ENTER; + character = (int)Key::ENTER; break; case 8198: - character = KEY_SPACE; + character = (int)Key::SPACE; break; default: break; diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index c7d68019a1..d12e1aeee8 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -151,19 +151,19 @@ int DisplayServerJavaScript::mouse_button_callback(int p_pressed, int p_button, switch (p_button) { case DOM_BUTTON_LEFT: - ev->set_button_index(MOUSE_BUTTON_LEFT); + ev->set_button_index(MouseButton::LEFT); break; case DOM_BUTTON_MIDDLE: - ev->set_button_index(MOUSE_BUTTON_MIDDLE); + ev->set_button_index(MouseButton::MIDDLE); break; case DOM_BUTTON_RIGHT: - ev->set_button_index(MOUSE_BUTTON_RIGHT); + ev->set_button_index(MouseButton::RIGHT); break; case DOM_BUTTON_XBUTTON1: - ev->set_button_index(MOUSE_BUTTON_XBUTTON1); + ev->set_button_index(MouseButton::MB_XBUTTON1); break; case DOM_BUTTON_XBUTTON2: - ev->set_button_index(MOUSE_BUTTON_XBUTTON2); + ev->set_button_index(MouseButton::MB_XBUTTON2); break; default: return false; @@ -176,7 +176,7 @@ int DisplayServerJavaScript::mouse_button_callback(int p_pressed, int p_button, if (diff < 400 && Point2(ds->last_click_pos).distance_to(ev->get_position()) < 5) { ds->last_click_ms = 0; ds->last_click_pos = Point2(-100, -100); - ds->last_click_button_index = -1; + ds->last_click_button_index = MouseButton::NONE; ev->set_double_click(true); } @@ -190,11 +190,11 @@ int DisplayServerJavaScript::mouse_button_callback(int p_pressed, int p_button, } } - int mask = Input::get_singleton()->get_mouse_button_mask(); - int button_flag = 1 << (ev->get_button_index() - 1); + MouseButton mask = Input::get_singleton()->get_mouse_button_mask(); + MouseButton button_flag = mouse_button_to_mask(ev->get_button_index()); if (ev->is_pressed()) { mask |= button_flag; - } else if (mask & button_flag) { + } else if ((mask & button_flag) != MouseButton::NONE) { mask &= ~button_flag; } else { // Received release event, but press was outside the canvas, so ignore. @@ -215,11 +215,12 @@ int DisplayServerJavaScript::mouse_button_callback(int p_pressed, int p_button, } void DisplayServerJavaScript::mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers) { - int input_mask = Input::get_singleton()->get_mouse_button_mask(); + MouseButton input_mask = Input::get_singleton()->get_mouse_button_mask(); // For motion outside the canvas, only read mouse movement if dragging // started inside the canvas; imitating desktop app behaviour. - if (!get_singleton()->cursor_inside_canvas && !input_mask) + if (!get_singleton()->cursor_inside_canvas && input_mask == MouseButton::NONE) { return; + } Ref<InputEventMouseMotion> ev; ev.instantiate(); @@ -412,19 +413,19 @@ int DisplayServerJavaScript::mouse_wheel_callback(double p_delta_x, double p_del ev->set_position(input->get_mouse_position()); ev->set_global_position(ev->get_position()); - ev->set_shift_pressed(input->is_key_pressed(KEY_SHIFT)); - ev->set_alt_pressed(input->is_key_pressed(KEY_ALT)); - ev->set_ctrl_pressed(input->is_key_pressed(KEY_CTRL)); - ev->set_meta_pressed(input->is_key_pressed(KEY_META)); + ev->set_shift_pressed(input->is_key_pressed(Key::SHIFT)); + ev->set_alt_pressed(input->is_key_pressed(Key::ALT)); + ev->set_ctrl_pressed(input->is_key_pressed(Key::CTRL)); + ev->set_meta_pressed(input->is_key_pressed(Key::META)); if (p_delta_y < 0) { - ev->set_button_index(MOUSE_BUTTON_WHEEL_UP); + ev->set_button_index(MouseButton::WHEEL_UP); } else if (p_delta_y > 0) { - ev->set_button_index(MOUSE_BUTTON_WHEEL_DOWN); + ev->set_button_index(MouseButton::WHEEL_DOWN); } else if (p_delta_x > 0) { - ev->set_button_index(MOUSE_BUTTON_WHEEL_LEFT); + ev->set_button_index(MouseButton::WHEEL_LEFT); } else if (p_delta_x < 0) { - ev->set_button_index(MOUSE_BUTTON_WHEEL_RIGHT); + ev->set_button_index(MouseButton::WHEEL_RIGHT); } else { return false; } @@ -432,7 +433,7 @@ int DisplayServerJavaScript::mouse_wheel_callback(double p_delta_x, double p_del // Different browsers give wildly different delta values, and we can't // interpret deltaMode, so use default value for wheel events' factor. - int button_flag = 1 << (ev->get_button_index() - 1); + MouseButton button_flag = mouse_button_to_mask(ev->get_button_index()); ev->set_pressed(true); ev->set_button_mask(input->get_mouse_button_mask() | button_flag); @@ -509,12 +510,12 @@ void DisplayServerJavaScript::vk_input_text_callback(const char *p_text, int p_c k.instantiate(); k->set_pressed(true); k->set_echo(false); - k->set_keycode(KEY_RIGHT); + k->set_keycode(Key::RIGHT); input->parse_input_event(k); k.instantiate(); k->set_pressed(false); k->set_echo(false); - k->set_keycode(KEY_RIGHT); + k->set_keycode(Key::RIGHT); input->parse_input_event(k); } } @@ -557,12 +558,12 @@ void DisplayServerJavaScript::process_joypads() { for (int b = 0; b < s_btns_num; b++) { float value = s_btns[b]; // Buttons 6 and 7 in the standard mapping need to be - // axis to be handled as JOY_AXIS_TRIGGER by Godot. + // axis to be handled as JoyAxis::TRIGGER by Godot. if (s_standard && (b == 6 || b == 7)) { Input::JoyAxisValue joy_axis; joy_axis.min = 0; joy_axis.value = value; - JoyAxis a = b == 6 ? JOY_AXIS_TRIGGER_LEFT : JOY_AXIS_TRIGGER_RIGHT; + JoyAxis a = b == 6 ? JoyAxis::TRIGGER_LEFT : JoyAxis::TRIGGER_RIGHT; input->joy_axis(idx, a, joy_axis); } else { input->joy_button(idx, (JoyButton)b, value); diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h index 1aa600c421..80ce772a79 100644 --- a/platform/javascript/display_server_javascript.h +++ b/platform/javascript/display_server_javascript.h @@ -67,7 +67,7 @@ private: CursorShape cursor_shape = CURSOR_ARROW; Point2i last_click_pos = Point2(-100, -100); // TODO check this again. uint64_t last_click_ms = 0; - int last_click_button_index = -1; + MouseButton last_click_button_index = MouseButton::NONE; bool swap_cancel_ok = false; diff --git a/platform/javascript/dom_keys.inc b/platform/javascript/dom_keys.inc index 0e62776923..31589f3f40 100644 --- a/platform/javascript/dom_keys.inc +++ b/platform/javascript/dom_keys.inc @@ -34,7 +34,7 @@ Key dom_code2godot_scancode(EM_UTF8 const p_code[32], EM_UTF8 const p_key[32], bool p_physical) { #define DOM2GODOT(p_str, p_godot_code) \ if (memcmp((const void *)p_str, (void *)p_code, strlen(p_str) + 1) == 0) { \ - return KEY_##p_godot_code; \ + return Key::p_godot_code; \ } // Numpad section. @@ -105,16 +105,16 @@ Key dom_code2godot_scancode(EM_UTF8 const p_code[32], EM_UTF8 const p_key[32], b DOM2GODOT("BracketLeft", BRACKETLEFT); DOM2GODOT("BracketRight", BRACKETRIGHT); DOM2GODOT("Comma", COMMA); - DOM2GODOT("Digit0", 0); - DOM2GODOT("Digit1", 1); - DOM2GODOT("Digit2", 2); - DOM2GODOT("Digit3", 3); - DOM2GODOT("Digit4", 4); - DOM2GODOT("Digit5", 5); - DOM2GODOT("Digit6", 6); - DOM2GODOT("Digit7", 7); - DOM2GODOT("Digit8", 8); - DOM2GODOT("Digit9", 9); + DOM2GODOT("Digit0", KEY_0); + DOM2GODOT("Digit1", KEY_1); + DOM2GODOT("Digit2", KEY_2); + DOM2GODOT("Digit3", KEY_3); + DOM2GODOT("Digit4", KEY_4); + DOM2GODOT("Digit5", KEY_5); + DOM2GODOT("Digit6", KEY_6); + DOM2GODOT("Digit7", KEY_7); + DOM2GODOT("Digit8", KEY_8); + DOM2GODOT("Digit9", KEY_9); DOM2GODOT("Equal", EQUAL); DOM2GODOT("IntlBackslash", BACKSLASH); //DOM2GODOT("IntlRo", UNKNOWN); @@ -170,7 +170,7 @@ Key dom_code2godot_scancode(EM_UTF8 const p_code[32], EM_UTF8 const p_key[32], b DOM2GODOT("Tab", TAB); // ControlPad section. - DOM2GODOT("Delete", DELETE); + DOM2GODOT("Delete", KEY_DELETE); DOM2GODOT("End", END); DOM2GODOT("Help", HELP); DOM2GODOT("Home", HOME); @@ -227,6 +227,6 @@ Key dom_code2godot_scancode(EM_UTF8 const p_code[32], EM_UTF8 const p_key[32], b DOM2GODOT("AudioVolumeMute", VOLUMEMUTE); DOM2GODOT("AudioVolumeUp", VOLUMEUP); //DOM2GODOT("WakeUp", UNKNOWN); - return KEY_UNKNOWN; + return Key::UNKNOWN; #undef DOM2GODOT } diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 4431bd5f1b..5da9a96a90 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -36,7 +36,7 @@ #include "main/main.h" #include "platform/javascript/display_server_javascript.h" -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For websocket. #ifdef MODULE_WEBSOCKET_ENABLED #include "modules/websocket/remote_debugger_peer_websocket.h" #endif diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp index 0e98af71fa..9b24b24cb4 100644 --- a/platform/linuxbsd/crash_handler_linuxbsd.cpp +++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp @@ -115,7 +115,7 @@ static void handle_crash(int sig) { int ret; Error err = OS::get_singleton()->execute(String("addr2line"), args, &output, &ret); if (err == OK) { - output.erase(output.length() - 1, 1); + output = output.substr(0, output.length() - 1); } fprintf(stderr, "[%ld] %s (%s)\n", (long int)i, fname, output.utf8().get_data()); diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 9349d378d0..2a62780410 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -2408,9 +2408,9 @@ String DisplayServerX11::keyboard_get_layout_name(int p_index) const { } Key DisplayServerX11::keyboard_get_keycode_from_physical(Key p_keycode) const { - unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK; - unsigned int keycode_no_mod = p_keycode & KEY_CODE_MASK; - unsigned int xkeycode = KeyMappingX11::get_xlibcode((Key)keycode_no_mod); + Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; + Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK; + unsigned int xkeycode = KeyMappingX11::get_xlibcode(keycode_no_mod); KeySym xkeysym = XkbKeycodeToKeysym(x11_display, xkeycode, 0, 0); if (xkeysym >= 'a' && xkeysym <= 'z') { xkeysym -= ('a' - 'A'); @@ -2419,7 +2419,7 @@ Key DisplayServerX11::keyboard_get_keycode_from_physical(Key p_keycode) const { Key key = KeyMappingX11::get_keycode(xkeysym); // If not found, fallback to QWERTY. // This should match the behavior of the event pump - if (key == KEY_NONE) { + if (key == Key::NONE) { return p_keycode; } return (Key)(key | modifiers); @@ -2493,12 +2493,12 @@ void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<Inp } MouseButton DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) { - MouseButton mask = MouseButton(1 << (p_x11_button - 1)); + MouseButton mask = mouse_button_to_mask(p_x11_button); if (p_x11_type == ButtonPress) { last_button_state |= mask; } else { - last_button_state &= MouseButton(~mask); + last_button_state &= ~mask; } return last_button_state; @@ -2565,9 +2565,9 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, if (status == XLookupChars) { bool keypress = xkeyevent->type == KeyPress; Key keycode = KeyMappingX11::get_keycode(keysym_keycode); - unsigned int physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode); + Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode); - if (keycode >= 'a' && keycode <= 'z') { + if (keycode >= Key::A + 32 && keycode <= Key::Z + 32) { keycode -= 'a' - 'A'; } @@ -2576,11 +2576,11 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, for (int i = 0; i < tmp.length(); i++) { Ref<InputEventKey> k; k.instantiate(); - if (physical_keycode == 0 && keycode == 0 && tmp[i] == 0) { + if (physical_keycode == Key::NONE && keycode == Key::NONE && tmp[i] == 0) { continue; } - if (keycode == 0) { + if (keycode == Key::NONE) { keycode = (Key)physical_keycode; } @@ -2597,10 +2597,10 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, k->set_echo(false); - if (k->get_keycode() == KEY_BACKTAB) { + if (k->get_keycode() == Key::BACKTAB) { //make it consistent across platforms. - k->set_keycode(KEY_TAB); - k->set_physical_keycode(KEY_TAB); + k->set_keycode(Key::TAB); + k->set_physical_keycode(Key::TAB); k->set_shift_pressed(true); } @@ -2629,7 +2629,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, // keysym, so it works in all platforms the same. Key keycode = KeyMappingX11::get_keycode(keysym_keycode); - unsigned int physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode); + Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode); /* Phase 3, obtain a unicode character from the keysym */ @@ -2649,11 +2649,11 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, bool keypress = xkeyevent->type == KeyPress; - if (physical_keycode == 0 && keycode == KEY_NONE && unicode == 0) { + if (physical_keycode == Key::NONE && keycode == Key::NONE && unicode == 0) { return; } - if (keycode == KEY_NONE) { + if (keycode == Key::NONE) { keycode = (Key)physical_keycode; } @@ -2716,7 +2716,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, k->set_pressed(keypress); - if (keycode >= 'a' && keycode <= 'z') { + if (keycode >= Key::A + 32 && keycode <= Key::Z + 32) { keycode -= int('a' - 'A'); } @@ -2725,23 +2725,23 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, k->set_unicode(unicode); k->set_echo(p_echo); - if (k->get_keycode() == KEY_BACKTAB) { + if (k->get_keycode() == Key::BACKTAB) { //make it consistent across platforms. - k->set_keycode(KEY_TAB); - k->set_physical_keycode(KEY_TAB); + k->set_keycode(Key::TAB); + k->set_physical_keycode(Key::TAB); k->set_shift_pressed(true); } //don't set mod state if modifier keys are released by themselves //else event.is_action() will not work correctly here if (!k->is_pressed()) { - if (k->get_keycode() == KEY_SHIFT) { + if (k->get_keycode() == Key::SHIFT) { k->set_shift_pressed(false); - } else if (k->get_keycode() == KEY_CTRL) { + } else if (k->get_keycode() == Key::CTRL) { k->set_ctrl_pressed(false); - } else if (k->get_keycode() == KEY_ALT) { + } else if (k->get_keycode() == Key::ALT) { k->set_alt_pressed(false); - } else if (k->get_keycode() == KEY_META) { + } else if (k->get_keycode() == Key::META) { k->set_meta_pressed(false); } } @@ -3469,10 +3469,10 @@ void DisplayServerX11::process_events() { mb->set_window_id(window_id); _get_key_modifier_state(event.xbutton.state, mb); mb->set_button_index((MouseButton)event.xbutton.button); - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { - mb->set_button_index(MOUSE_BUTTON_MIDDLE); - } else if (mb->get_button_index() == MOUSE_BUTTON_MIDDLE) { - mb->set_button_index(MOUSE_BUTTON_RIGHT); + if (mb->get_button_index() == MouseButton::RIGHT) { + mb->set_button_index(MouseButton::MIDDLE); + } else if (mb->get_button_index() == MouseButton::MIDDLE) { + mb->set_button_index(MouseButton::RIGHT); } mb->set_button_mask(_get_mouse_button_state(mb->get_button_index(), event.xbutton.type)); mb->set_position(Vector2(event.xbutton.x, event.xbutton.y)); @@ -3498,11 +3498,11 @@ void DisplayServerX11::process_events() { if (diff < 400 && Vector2(last_click_pos).distance_to(Vector2(event.xbutton.x, event.xbutton.y)) < 5) { last_click_ms = 0; last_click_pos = Point2i(-100, -100); - last_click_button_index = -1; + last_click_button_index = MouseButton::NONE; mb->set_double_click(true); } - } else if (mb->get_button_index() < 4 || mb->get_button_index() > 7) { + } else if (mb->get_button_index() < MouseButton::WHEEL_UP || mb->get_button_index() > MouseButton::WHEEL_RIGHT) { last_click_button_index = mb->get_button_index(); } @@ -3635,12 +3635,12 @@ void DisplayServerX11::process_events() { if (xi.pressure_supported) { mm->set_pressure(xi.pressure); } else { - mm->set_pressure((mouse_get_button_state() & MOUSE_BUTTON_MASK_LEFT) ? 1.0f : 0.0f); + mm->set_pressure(bool(mouse_get_button_state() & MouseButton::MASK_LEFT) ? 1.0f : 0.0f); } mm->set_tilt(xi.tilt); _get_key_modifier_state(event.xmotion.state, mm); - mm->set_button_mask(mouse_get_button_state()); + mm->set_button_mask((MouseButton)mouse_get_button_state()); mm->set_position(pos); mm->set_global_position(pos); Input::get_singleton()->set_mouse_position(pos); @@ -4251,7 +4251,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode xmbstring = nullptr; last_click_ms = 0; - last_click_button_index = -1; + last_click_button_index = MouseButton::NONE; last_click_pos = Point2i(-100, -100); last_timestamp = 0; diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 869ff386c5..3587d587d6 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -173,8 +173,8 @@ class DisplayServerX11 : public DisplayServer { bool last_mouse_pos_valid; Point2i last_click_pos; uint64_t last_click_ms; - int last_click_button_index; - MouseButton last_button_state = MOUSE_BUTTON_NONE; + MouseButton last_click_button_index = MouseButton::NONE; + MouseButton last_button_state = MouseButton::NONE; bool app_focused = false; uint64_t time_since_no_focus = 0; diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index 8b6dbc4c20..1c6afabfab 100644 --- a/platform/linuxbsd/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -59,7 +59,7 @@ JoypadLinux::Joypad::~Joypad() { } void JoypadLinux::Joypad::reset() { - dpad = 0; + dpad = HatMask::CENTER; fd = -1; Input::JoyAxisValue jx; @@ -484,12 +484,12 @@ void JoypadLinux::process_joypads() { case ABS_HAT0X: if (ev.value != 0) { if (ev.value < 0) { - joy->dpad = (HatMask)((joy->dpad | HatMask::HAT_MASK_LEFT) & ~HatMask::HAT_MASK_RIGHT); + joy->dpad = (HatMask)((joy->dpad | HatMask::LEFT) & ~HatMask::RIGHT); } else { - joy->dpad = (HatMask)((joy->dpad | HatMask::HAT_MASK_RIGHT) & ~HatMask::HAT_MASK_LEFT); + joy->dpad = (HatMask)((joy->dpad | HatMask::RIGHT) & ~HatMask::LEFT); } } else { - joy->dpad &= ~(HatMask::HAT_MASK_LEFT | HatMask::HAT_MASK_RIGHT); + joy->dpad &= ~(HatMask::LEFT | HatMask::RIGHT); } input->joy_hat(i, (HatMask)joy->dpad); @@ -498,12 +498,12 @@ void JoypadLinux::process_joypads() { case ABS_HAT0Y: if (ev.value != 0) { if (ev.value < 0) { - joy->dpad = (HatMask)((joy->dpad | HatMask::HAT_MASK_UP) & ~HatMask::HAT_MASK_DOWN); + joy->dpad = (HatMask)((joy->dpad | HatMask::UP) & ~HatMask::DOWN); } else { - joy->dpad = (HatMask)((joy->dpad | HatMask::HAT_MASK_DOWN) & ~HatMask::HAT_MASK_UP); + joy->dpad = (HatMask)((joy->dpad | HatMask::DOWN) & ~HatMask::UP); } } else { - joy->dpad &= ~(HatMask::HAT_MASK_UP | HatMask::HAT_MASK_DOWN); + joy->dpad &= ~(HatMask::UP | HatMask::DOWN); } input->joy_hat(i, (HatMask)joy->dpad); diff --git a/platform/linuxbsd/joypad_linux.h b/platform/linuxbsd/joypad_linux.h index 177d7a51ce..12b9046d64 100644 --- a/platform/linuxbsd/joypad_linux.h +++ b/platform/linuxbsd/joypad_linux.h @@ -56,7 +56,7 @@ private: Input::JoyAxisValue curr_axis[MAX_ABS]; int key_map[MAX_KEY]; int abs_map[MAX_ABS]; - int dpad = 0; + HatMask dpad = HatMask::CENTER; int fd = -1; String devpath; diff --git a/platform/linuxbsd/key_mapping_x11.cpp b/platform/linuxbsd/key_mapping_x11.cpp index 829feda40a..16c2392859 100644 --- a/platform/linuxbsd/key_mapping_x11.cpp +++ b/platform/linuxbsd/key_mapping_x11.cpp @@ -40,266 +40,266 @@ struct _XTranslatePair { static _XTranslatePair _xkeysym_to_keycode[] = { // misc keys - { XK_Escape, KEY_ESCAPE }, - { XK_Tab, KEY_TAB }, - { XK_ISO_Left_Tab, KEY_BACKTAB }, - { XK_BackSpace, KEY_BACKSPACE }, - { XK_Return, KEY_ENTER }, - { XK_Insert, KEY_INSERT }, - { XK_Delete, KEY_DELETE }, - { XK_Clear, KEY_DELETE }, - { XK_Pause, KEY_PAUSE }, - { XK_Print, KEY_PRINT }, - { XK_Home, KEY_HOME }, - { XK_End, KEY_END }, - { XK_Left, KEY_LEFT }, - { XK_Up, KEY_UP }, - { XK_Right, KEY_RIGHT }, - { XK_Down, KEY_DOWN }, - { XK_Prior, KEY_PAGEUP }, - { XK_Next, KEY_PAGEDOWN }, - { XK_Shift_L, KEY_SHIFT }, - { XK_Shift_R, KEY_SHIFT }, - { XK_Shift_Lock, KEY_SHIFT }, - { XK_Control_L, KEY_CTRL }, - { XK_Control_R, KEY_CTRL }, - { XK_Meta_L, KEY_META }, - { XK_Meta_R, KEY_META }, - { XK_Alt_L, KEY_ALT }, - { XK_Alt_R, KEY_ALT }, - { XK_Caps_Lock, KEY_CAPSLOCK }, - { XK_Num_Lock, KEY_NUMLOCK }, - { XK_Scroll_Lock, KEY_SCROLLLOCK }, - { XK_Super_L, KEY_SUPER_L }, - { XK_Super_R, KEY_SUPER_R }, - { XK_Menu, KEY_MENU }, - { XK_Hyper_L, KEY_HYPER_L }, - { XK_Hyper_R, KEY_HYPER_R }, - { XK_Help, KEY_HELP }, - { XK_KP_Space, KEY_SPACE }, - { XK_KP_Tab, KEY_TAB }, - { XK_KP_Enter, KEY_KP_ENTER }, - { XK_Home, KEY_HOME }, - { XK_Left, KEY_LEFT }, - { XK_Up, KEY_UP }, - { XK_Right, KEY_RIGHT }, - { XK_Down, KEY_DOWN }, - { XK_Prior, KEY_PAGEUP }, - { XK_Next, KEY_PAGEDOWN }, - { XK_End, KEY_END }, - { XK_Begin, KEY_CLEAR }, - { XK_Insert, KEY_INSERT }, - { XK_Delete, KEY_DELETE }, - //{ XK_KP_Equal, KEY_EQUAL }, - //{ XK_KP_Separator, KEY_COMMA }, - { XK_KP_Decimal, KEY_KP_PERIOD }, - { XK_KP_Delete, KEY_KP_PERIOD }, - { XK_KP_Multiply, KEY_KP_MULTIPLY }, - { XK_KP_Divide, KEY_KP_DIVIDE }, - { XK_KP_Subtract, KEY_KP_SUBTRACT }, - { XK_KP_Add, KEY_KP_ADD }, - { XK_KP_0, KEY_KP_0 }, - { XK_KP_1, KEY_KP_1 }, - { XK_KP_2, KEY_KP_2 }, - { XK_KP_3, KEY_KP_3 }, - { XK_KP_4, KEY_KP_4 }, - { XK_KP_5, KEY_KP_5 }, - { XK_KP_6, KEY_KP_6 }, - { XK_KP_7, KEY_KP_7 }, - { XK_KP_8, KEY_KP_8 }, - { XK_KP_9, KEY_KP_9 }, + { XK_Escape, Key::ESCAPE }, + { XK_Tab, Key::TAB }, + { XK_ISO_Left_Tab, Key::BACKTAB }, + { XK_BackSpace, Key::BACKSPACE }, + { XK_Return, Key::ENTER }, + { XK_Insert, Key::INSERT }, + { XK_Delete, Key::KEY_DELETE }, + { XK_Clear, Key::KEY_DELETE }, + { XK_Pause, Key::PAUSE }, + { XK_Print, Key::PRINT }, + { XK_Home, Key::HOME }, + { XK_End, Key::END }, + { XK_Left, Key::LEFT }, + { XK_Up, Key::UP }, + { XK_Right, Key::RIGHT }, + { XK_Down, Key::DOWN }, + { XK_Prior, Key::PAGEUP }, + { XK_Next, Key::PAGEDOWN }, + { XK_Shift_L, Key::SHIFT }, + { XK_Shift_R, Key::SHIFT }, + { XK_Shift_Lock, Key::SHIFT }, + { XK_Control_L, Key::CTRL }, + { XK_Control_R, Key::CTRL }, + { XK_Meta_L, Key::META }, + { XK_Meta_R, Key::META }, + { XK_Alt_L, Key::ALT }, + { XK_Alt_R, Key::ALT }, + { XK_Caps_Lock, Key::CAPSLOCK }, + { XK_Num_Lock, Key::NUMLOCK }, + { XK_Scroll_Lock, Key::SCROLLLOCK }, + { XK_Super_L, Key::SUPER_L }, + { XK_Super_R, Key::SUPER_R }, + { XK_Menu, Key::MENU }, + { XK_Hyper_L, Key::HYPER_L }, + { XK_Hyper_R, Key::HYPER_R }, + { XK_Help, Key::HELP }, + { XK_KP_Space, Key::SPACE }, + { XK_KP_Tab, Key::TAB }, + { XK_KP_Enter, Key::KP_ENTER }, + { XK_Home, Key::HOME }, + { XK_Left, Key::LEFT }, + { XK_Up, Key::UP }, + { XK_Right, Key::RIGHT }, + { XK_Down, Key::DOWN }, + { XK_Prior, Key::PAGEUP }, + { XK_Next, Key::PAGEDOWN }, + { XK_End, Key::END }, + { XK_Begin, Key::CLEAR }, + { XK_Insert, Key::INSERT }, + { XK_Delete, Key::KEY_DELETE }, + //{ XK_KP_Equal, Key::EQUAL }, + //{ XK_KP_Separator, Key::COMMA }, + { XK_KP_Decimal, Key::KP_PERIOD }, + { XK_KP_Delete, Key::KP_PERIOD }, + { XK_KP_Multiply, Key::KP_MULTIPLY }, + { XK_KP_Divide, Key::KP_DIVIDE }, + { XK_KP_Subtract, Key::KP_SUBTRACT }, + { XK_KP_Add, Key::KP_ADD }, + { XK_KP_0, Key::KP_0 }, + { XK_KP_1, Key::KP_1 }, + { XK_KP_2, Key::KP_2 }, + { XK_KP_3, Key::KP_3 }, + { XK_KP_4, Key::KP_4 }, + { XK_KP_5, Key::KP_5 }, + { XK_KP_6, Key::KP_6 }, + { XK_KP_7, Key::KP_7 }, + { XK_KP_8, Key::KP_8 }, + { XK_KP_9, Key::KP_9 }, // same but with numlock - { XK_KP_Insert, KEY_KP_0 }, - { XK_KP_End, KEY_KP_1 }, - { XK_KP_Down, KEY_KP_2 }, - { XK_KP_Page_Down, KEY_KP_3 }, - { XK_KP_Left, KEY_KP_4 }, - { XK_KP_Begin, KEY_KP_5 }, - { XK_KP_Right, KEY_KP_6 }, - { XK_KP_Home, KEY_KP_7 }, - { XK_KP_Up, KEY_KP_8 }, - { XK_KP_Page_Up, KEY_KP_9 }, - { XK_F1, KEY_F1 }, - { XK_F2, KEY_F2 }, - { XK_F3, KEY_F3 }, - { XK_F4, KEY_F4 }, - { XK_F5, KEY_F5 }, - { XK_F6, KEY_F6 }, - { XK_F7, KEY_F7 }, - { XK_F8, KEY_F8 }, - { XK_F9, KEY_F9 }, - { XK_F10, KEY_F10 }, - { XK_F11, KEY_F11 }, - { XK_F12, KEY_F12 }, - { XK_F13, KEY_F13 }, - { XK_F14, KEY_F14 }, - { XK_F15, KEY_F15 }, - { XK_F16, KEY_F16 }, + { XK_KP_Insert, Key::KP_0 }, + { XK_KP_End, Key::KP_1 }, + { XK_KP_Down, Key::KP_2 }, + { XK_KP_Page_Down, Key::KP_3 }, + { XK_KP_Left, Key::KP_4 }, + { XK_KP_Begin, Key::KP_5 }, + { XK_KP_Right, Key::KP_6 }, + { XK_KP_Home, Key::KP_7 }, + { XK_KP_Up, Key::KP_8 }, + { XK_KP_Page_Up, Key::KP_9 }, + { XK_F1, Key::F1 }, + { XK_F2, Key::F2 }, + { XK_F3, Key::F3 }, + { XK_F4, Key::F4 }, + { XK_F5, Key::F5 }, + { XK_F6, Key::F6 }, + { XK_F7, Key::F7 }, + { XK_F8, Key::F8 }, + { XK_F9, Key::F9 }, + { XK_F10, Key::F10 }, + { XK_F11, Key::F11 }, + { XK_F12, Key::F12 }, + { XK_F13, Key::F13 }, + { XK_F14, Key::F14 }, + { XK_F15, Key::F15 }, + { XK_F16, Key::F16 }, // media keys - { XF86XK_Back, KEY_BACK }, - { XF86XK_Forward, KEY_FORWARD }, - { XF86XK_Stop, KEY_STOP }, - { XF86XK_Refresh, KEY_REFRESH }, - { XF86XK_Favorites, KEY_FAVORITES }, - { XF86XK_AudioMedia, KEY_LAUNCHMEDIA }, - { XF86XK_OpenURL, KEY_OPENURL }, - { XF86XK_HomePage, KEY_HOMEPAGE }, - { XF86XK_Search, KEY_SEARCH }, - { XF86XK_AudioLowerVolume, KEY_VOLUMEDOWN }, - { XF86XK_AudioMute, KEY_VOLUMEMUTE }, - { XF86XK_AudioRaiseVolume, KEY_VOLUMEUP }, - { XF86XK_AudioPlay, KEY_MEDIAPLAY }, - { XF86XK_AudioStop, KEY_MEDIASTOP }, - { XF86XK_AudioPrev, KEY_MEDIAPREVIOUS }, - { XF86XK_AudioNext, KEY_MEDIANEXT }, - { XF86XK_AudioRecord, KEY_MEDIARECORD }, + { XF86XK_Back, Key::BACK }, + { XF86XK_Forward, Key::FORWARD }, + { XF86XK_Stop, Key::STOP }, + { XF86XK_Refresh, Key::REFRESH }, + { XF86XK_Favorites, Key::FAVORITES }, + { XF86XK_AudioMedia, Key::LAUNCHMEDIA }, + { XF86XK_OpenURL, Key::OPENURL }, + { XF86XK_HomePage, Key::HOMEPAGE }, + { XF86XK_Search, Key::SEARCH }, + { XF86XK_AudioLowerVolume, Key::VOLUMEDOWN }, + { XF86XK_AudioMute, Key::VOLUMEMUTE }, + { XF86XK_AudioRaiseVolume, Key::VOLUMEUP }, + { XF86XK_AudioPlay, Key::MEDIAPLAY }, + { XF86XK_AudioStop, Key::MEDIASTOP }, + { XF86XK_AudioPrev, Key::MEDIAPREVIOUS }, + { XF86XK_AudioNext, Key::MEDIANEXT }, + { XF86XK_AudioRecord, Key::MEDIARECORD }, // launch keys - { XF86XK_Mail, KEY_LAUNCHMAIL }, - { XF86XK_MyComputer, KEY_LAUNCH0 }, - { XF86XK_Calculator, KEY_LAUNCH1 }, - { XF86XK_Standby, KEY_STANDBY }, + { XF86XK_Mail, Key::LAUNCHMAIL }, + { XF86XK_MyComputer, Key::LAUNCH0 }, + { XF86XK_Calculator, Key::LAUNCH1 }, + { XF86XK_Standby, Key::STANDBY }, - { XF86XK_Launch0, KEY_LAUNCH2 }, - { XF86XK_Launch1, KEY_LAUNCH3 }, - { XF86XK_Launch2, KEY_LAUNCH4 }, - { XF86XK_Launch3, KEY_LAUNCH5 }, - { XF86XK_Launch4, KEY_LAUNCH6 }, - { XF86XK_Launch5, KEY_LAUNCH7 }, - { XF86XK_Launch6, KEY_LAUNCH8 }, - { XF86XK_Launch7, KEY_LAUNCH9 }, - { XF86XK_Launch8, KEY_LAUNCHA }, - { XF86XK_Launch9, KEY_LAUNCHB }, - { XF86XK_LaunchA, KEY_LAUNCHC }, - { XF86XK_LaunchB, KEY_LAUNCHD }, - { XF86XK_LaunchC, KEY_LAUNCHE }, - { XF86XK_LaunchD, KEY_LAUNCHF }, + { XF86XK_Launch0, Key::LAUNCH2 }, + { XF86XK_Launch1, Key::LAUNCH3 }, + { XF86XK_Launch2, Key::LAUNCH4 }, + { XF86XK_Launch3, Key::LAUNCH5 }, + { XF86XK_Launch4, Key::LAUNCH6 }, + { XF86XK_Launch5, Key::LAUNCH7 }, + { XF86XK_Launch6, Key::LAUNCH8 }, + { XF86XK_Launch7, Key::LAUNCH9 }, + { XF86XK_Launch8, Key::LAUNCHA }, + { XF86XK_Launch9, Key::LAUNCHB }, + { XF86XK_LaunchA, Key::LAUNCHC }, + { XF86XK_LaunchB, Key::LAUNCHD }, + { XF86XK_LaunchC, Key::LAUNCHE }, + { XF86XK_LaunchD, Key::LAUNCHF }, - { 0, KEY_NONE } + { 0, Key::NONE } }; struct _TranslatePair { - unsigned int keysym; + Key keysym; unsigned int keycode; }; static _TranslatePair _scancode_to_keycode[] = { - { KEY_ESCAPE, 0x09 }, - { KEY_1, 0x0A }, - { KEY_2, 0x0B }, - { KEY_3, 0x0C }, - { KEY_4, 0x0D }, - { KEY_5, 0x0E }, - { KEY_6, 0x0F }, - { KEY_7, 0x10 }, - { KEY_8, 0x11 }, - { KEY_9, 0x12 }, - { KEY_0, 0x13 }, - { KEY_MINUS, 0x14 }, - { KEY_EQUAL, 0x15 }, - { KEY_BACKSPACE, 0x16 }, - { KEY_TAB, 0x17 }, - { KEY_Q, 0x18 }, - { KEY_W, 0x19 }, - { KEY_E, 0x1A }, - { KEY_R, 0x1B }, - { KEY_T, 0x1C }, - { KEY_Y, 0x1D }, - { KEY_U, 0x1E }, - { KEY_I, 0x1F }, - { KEY_O, 0x20 }, - { KEY_P, 0x21 }, - { KEY_BRACELEFT, 0x22 }, - { KEY_BRACERIGHT, 0x23 }, - { KEY_ENTER, 0x24 }, - { KEY_CTRL, 0x25 }, - { KEY_A, 0x26 }, - { KEY_S, 0x27 }, - { KEY_D, 0x28 }, - { KEY_F, 0x29 }, - { KEY_G, 0x2A }, - { KEY_H, 0x2B }, - { KEY_J, 0x2C }, - { KEY_K, 0x2D }, - { KEY_L, 0x2E }, - { KEY_SEMICOLON, 0x2F }, - { KEY_APOSTROPHE, 0x30 }, - { KEY_QUOTELEFT, 0x31 }, - { KEY_SHIFT, 0x32 }, - { KEY_BACKSLASH, 0x33 }, - { KEY_Z, 0x34 }, - { KEY_X, 0x35 }, - { KEY_C, 0x36 }, - { KEY_V, 0x37 }, - { KEY_B, 0x38 }, - { KEY_N, 0x39 }, - { KEY_M, 0x3A }, - { KEY_COMMA, 0x3B }, - { KEY_PERIOD, 0x3C }, - { KEY_SLASH, 0x3D }, - { KEY_SHIFT, 0x3E }, - { KEY_KP_MULTIPLY, 0x3F }, - { KEY_ALT, 0x40 }, - { KEY_SPACE, 0x41 }, - { KEY_CAPSLOCK, 0x42 }, - { KEY_F1, 0x43 }, - { KEY_F2, 0x44 }, - { KEY_F3, 0x45 }, - { KEY_F4, 0x46 }, - { KEY_F5, 0x47 }, - { KEY_F6, 0x48 }, - { KEY_F7, 0x49 }, - { KEY_F8, 0x4A }, - { KEY_F9, 0x4B }, - { KEY_F10, 0x4C }, - { KEY_NUMLOCK, 0x4D }, - { KEY_SCROLLLOCK, 0x4E }, - { KEY_KP_7, 0x4F }, - { KEY_KP_8, 0x50 }, - { KEY_KP_9, 0x51 }, - { KEY_KP_SUBTRACT, 0x52 }, - { KEY_KP_4, 0x53 }, - { KEY_KP_5, 0x54 }, - { KEY_KP_6, 0x55 }, - { KEY_KP_ADD, 0x56 }, - { KEY_KP_1, 0x57 }, - { KEY_KP_2, 0x58 }, - { KEY_KP_3, 0x59 }, - { KEY_KP_0, 0x5A }, - { KEY_KP_PERIOD, 0x5B }, - //{ KEY_???, 0x5E }, //NON US BACKSLASH - { KEY_F11, 0x5F }, - { KEY_F12, 0x60 }, - { KEY_KP_ENTER, 0x68 }, - { KEY_CTRL, 0x69 }, - { KEY_KP_DIVIDE, 0x6A }, - { KEY_PRINT, 0x6B }, - { KEY_ALT, 0x6C }, - { KEY_ENTER, 0x6D }, - { KEY_HOME, 0x6E }, - { KEY_UP, 0x6F }, - { KEY_PAGEUP, 0x70 }, - { KEY_LEFT, 0x71 }, - { KEY_RIGHT, 0x72 }, - { KEY_END, 0x73 }, - { KEY_DOWN, 0x74 }, - { KEY_PAGEDOWN, 0x75 }, - { KEY_INSERT, 0x76 }, - { KEY_DELETE, 0x77 }, - { KEY_VOLUMEMUTE, 0x79 }, - { KEY_VOLUMEDOWN, 0x7A }, - { KEY_VOLUMEUP, 0x7B }, - { KEY_PAUSE, 0x7F }, - { KEY_SUPER_L, 0x85 }, - { KEY_SUPER_R, 0x86 }, - { KEY_MENU, 0x87 }, - { KEY_UNKNOWN, 0 } + { Key::ESCAPE, 0x09 }, + { Key::KEY_1, 0x0A }, + { Key::KEY_2, 0x0B }, + { Key::KEY_3, 0x0C }, + { Key::KEY_4, 0x0D }, + { Key::KEY_5, 0x0E }, + { Key::KEY_6, 0x0F }, + { Key::KEY_7, 0x10 }, + { Key::KEY_8, 0x11 }, + { Key::KEY_9, 0x12 }, + { Key::KEY_0, 0x13 }, + { Key::MINUS, 0x14 }, + { Key::EQUAL, 0x15 }, + { Key::BACKSPACE, 0x16 }, + { Key::TAB, 0x17 }, + { Key::Q, 0x18 }, + { Key::W, 0x19 }, + { Key::E, 0x1A }, + { Key::R, 0x1B }, + { Key::T, 0x1C }, + { Key::Y, 0x1D }, + { Key::U, 0x1E }, + { Key::I, 0x1F }, + { Key::O, 0x20 }, + { Key::P, 0x21 }, + { Key::BRACELEFT, 0x22 }, + { Key::BRACERIGHT, 0x23 }, + { Key::ENTER, 0x24 }, + { Key::CTRL, 0x25 }, + { Key::A, 0x26 }, + { Key::S, 0x27 }, + { Key::D, 0x28 }, + { Key::F, 0x29 }, + { Key::G, 0x2A }, + { Key::H, 0x2B }, + { Key::J, 0x2C }, + { Key::K, 0x2D }, + { Key::L, 0x2E }, + { Key::SEMICOLON, 0x2F }, + { Key::APOSTROPHE, 0x30 }, + { Key::QUOTELEFT, 0x31 }, + { Key::SHIFT, 0x32 }, + { Key::BACKSLASH, 0x33 }, + { Key::Z, 0x34 }, + { Key::X, 0x35 }, + { Key::C, 0x36 }, + { Key::V, 0x37 }, + { Key::B, 0x38 }, + { Key::N, 0x39 }, + { Key::M, 0x3A }, + { Key::COMMA, 0x3B }, + { Key::PERIOD, 0x3C }, + { Key::SLASH, 0x3D }, + { Key::SHIFT, 0x3E }, + { Key::KP_MULTIPLY, 0x3F }, + { Key::ALT, 0x40 }, + { Key::SPACE, 0x41 }, + { Key::CAPSLOCK, 0x42 }, + { Key::F1, 0x43 }, + { Key::F2, 0x44 }, + { Key::F3, 0x45 }, + { Key::F4, 0x46 }, + { Key::F5, 0x47 }, + { Key::F6, 0x48 }, + { Key::F7, 0x49 }, + { Key::F8, 0x4A }, + { Key::F9, 0x4B }, + { Key::F10, 0x4C }, + { Key::NUMLOCK, 0x4D }, + { Key::SCROLLLOCK, 0x4E }, + { Key::KP_7, 0x4F }, + { Key::KP_8, 0x50 }, + { Key::KP_9, 0x51 }, + { Key::KP_SUBTRACT, 0x52 }, + { Key::KP_4, 0x53 }, + { Key::KP_5, 0x54 }, + { Key::KP_6, 0x55 }, + { Key::KP_ADD, 0x56 }, + { Key::KP_1, 0x57 }, + { Key::KP_2, 0x58 }, + { Key::KP_3, 0x59 }, + { Key::KP_0, 0x5A }, + { Key::KP_PERIOD, 0x5B }, + //{ Key::???, 0x5E }, //NON US BACKSLASH + { Key::F11, 0x5F }, + { Key::F12, 0x60 }, + { Key::KP_ENTER, 0x68 }, + { Key::CTRL, 0x69 }, + { Key::KP_DIVIDE, 0x6A }, + { Key::PRINT, 0x6B }, + { Key::ALT, 0x6C }, + { Key::ENTER, 0x6D }, + { Key::HOME, 0x6E }, + { Key::UP, 0x6F }, + { Key::PAGEUP, 0x70 }, + { Key::LEFT, 0x71 }, + { Key::RIGHT, 0x72 }, + { Key::END, 0x73 }, + { Key::DOWN, 0x74 }, + { Key::PAGEDOWN, 0x75 }, + { Key::INSERT, 0x76 }, + { Key::KEY_DELETE, 0x77 }, + { Key::VOLUMEMUTE, 0x79 }, + { Key::VOLUMEDOWN, 0x7A }, + { Key::VOLUMEUP, 0x7B }, + { Key::PAUSE, 0x7F }, + { Key::SUPER_L, 0x85 }, + { Key::SUPER_R, 0x86 }, + { Key::MENU, 0x87 }, + { Key::UNKNOWN, 0 } }; -unsigned int KeyMappingX11::get_scancode(unsigned int p_code) { - unsigned int keycode = KEY_UNKNOWN; - for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) { +Key KeyMappingX11::get_scancode(unsigned int p_code) { + Key keycode = Key::UNKNOWN; + for (int i = 0; _scancode_to_keycode[i].keysym != Key::UNKNOWN; i++) { if (_scancode_to_keycode[i].keycode == p_code) { keycode = _scancode_to_keycode[i].keysym; break; @@ -309,9 +309,9 @@ unsigned int KeyMappingX11::get_scancode(unsigned int p_code) { return keycode; } -unsigned int KeyMappingX11::get_xlibcode(unsigned int p_keysym) { +unsigned int KeyMappingX11::get_xlibcode(Key p_keysym) { unsigned int code = 0; - for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) { + for (int i = 0; _scancode_to_keycode[i].keysym != Key::UNKNOWN; i++) { if (_scancode_to_keycode[i].keysym == p_keysym) { code = _scancode_to_keycode[i].keycode; break; @@ -335,13 +335,13 @@ Key KeyMappingX11::get_keycode(KeySym p_keysym) { } } - return KEY_NONE; + return Key::NONE; } KeySym KeyMappingX11::get_keysym(Key p_code) { // kinda bruteforce.. could optimize. - if (p_code < 0x100) { // Latin 1, maps 1-1 + if (p_code < Key::END_LATIN1) { // Latin 1, maps 1-1 return (KeySym)p_code; } @@ -352,7 +352,7 @@ KeySym KeyMappingX11::get_keysym(Key p_code) { } } - return (KeySym)KEY_NONE; + return (KeySym)Key::NONE; } /***** UNICODE CONVERSION ******/ diff --git a/platform/linuxbsd/key_mapping_x11.h b/platform/linuxbsd/key_mapping_x11.h index d4f1554671..5f61197abe 100644 --- a/platform/linuxbsd/key_mapping_x11.h +++ b/platform/linuxbsd/key_mapping_x11.h @@ -45,11 +45,11 @@ class KeyMappingX11 { public: static Key get_keycode(KeySym p_keysym); - static unsigned int get_xlibcode(unsigned int p_keysym); - static unsigned int get_scancode(unsigned int p_code); + static unsigned int get_xlibcode(Key p_keysym); + static Key get_scancode(unsigned int p_code); static KeySym get_keysym(Key p_code); static unsigned int get_unicode_from_keysym(KeySym p_keysym); static KeySym get_keysym_from_unicode(unsigned int p_unicode); }; -#endif +#endif // KEY_MAPPING_X11_H diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm index 31228b10b4..57bca7a5b9 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/osx/crash_handler_osx.mm @@ -134,8 +134,13 @@ static void handle_crash(int sig) { args.push_back("-o"); args.push_back(_execpath); +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) args.push_back("-arch"); args.push_back("x86_64"); +#elif defined(__aarch64__) + args.push_back("-arch"); + args.push_back("arm64"); +#endif args.push_back("-l"); snprintf(str, 1024, "%p", load_addr); args.push_back(str); @@ -146,7 +151,7 @@ static void handle_crash(int sig) { String out = ""; Error err = OS::get_singleton()->execute(String("atos"), args, &out, &ret); if (err == OK && out.substr(0, 2) != "0x") { - out.erase(out.length() - 1, 1); + out = out.substr(0, out.length() - 1); output = out; } } diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 6bd79c7d4f..f5c7731395 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -82,7 +82,7 @@ def configure(env): env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15"]) env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15"]) else: - print("Building for macOS 10.12+, platform x86-64.") + print("Building for macOS 10.12+, platform x86_64.") env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"]) env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"]) diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index c45b470078..3cc0b10c5b 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -84,8 +84,8 @@ public: bool pressed = false; bool echo = false; bool raw = false; - Key keycode = KEY_NONE; - uint32_t physical_keycode = 0; + Key keycode = Key::NONE; + Key physical_keycode = Key::NONE; uint32_t unicode = 0; }; @@ -172,7 +172,7 @@ public: MouseMode mouse_mode; Point2i last_mouse_pos; - MouseButton last_button_state = MOUSE_BUTTON_NONE; + MouseButton last_button_state = MouseButton::NONE; bool window_focused; bool drop_events; diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 03301af0af..fec5c98a99 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -579,8 +579,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; ke.pressed = true; ke.echo = false; ke.raw = false; // IME input event - ke.keycode = KEY_NONE; - ke.physical_keycode = 0; + ke.keycode = Key::NONE; + ke.physical_keycode = Key::NONE; ke.unicode = codepoint; _push_to_key_event_buffer(ke); @@ -680,7 +680,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M mb->set_position(pos); mb->set_global_position(pos); mb->set_button_mask(DS_OSX->last_button_state); - if (index == MOUSE_BUTTON_LEFT && pressed) { + if (index == MouseButton::LEFT && pressed) { mb->set_double_click([event clickCount] == 2); } @@ -693,10 +693,10 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M if (([event modifierFlags] & NSEventModifierFlagControl)) { wd.mouse_down_control = true; - _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, true); + _mouseDownEvent(window_id, event, MouseButton::RIGHT, MouseButton::MASK_RIGHT, true); } else { wd.mouse_down_control = false; - _mouseDownEvent(window_id, event, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT, true); + _mouseDownEvent(window_id, event, MouseButton::LEFT, MouseButton::MASK_LEFT, true); } } @@ -709,9 +709,9 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; if (wd.mouse_down_control) { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, false); + _mouseDownEvent(window_id, event, MouseButton::RIGHT, MouseButton::MASK_RIGHT, false); } else { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT, false); + _mouseDownEvent(window_id, event, MouseButton::LEFT, MouseButton::MASK_LEFT, false); } } @@ -797,7 +797,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M } - (void)rightMouseDown:(NSEvent *)event { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, true); + _mouseDownEvent(window_id, event, MouseButton::RIGHT, MouseButton::MASK_RIGHT, true); } - (void)rightMouseDragged:(NSEvent *)event { @@ -805,16 +805,16 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M } - (void)rightMouseUp:(NSEvent *)event { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, false); + _mouseDownEvent(window_id, event, MouseButton::RIGHT, MouseButton::MASK_RIGHT, false); } - (void)otherMouseDown:(NSEvent *)event { if ((int)[event buttonNumber] == 2) { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_MASK_MIDDLE, true); + _mouseDownEvent(window_id, event, MouseButton::MIDDLE, MouseButton::MASK_MIDDLE, true); } else if ((int)[event buttonNumber] == 3) { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_MASK_XBUTTON1, true); + _mouseDownEvent(window_id, event, MouseButton::MB_XBUTTON1, MouseButton::MASK_XBUTTON1, true); } else if ((int)[event buttonNumber] == 4) { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON2, MOUSE_BUTTON_MASK_XBUTTON2, true); + _mouseDownEvent(window_id, event, MouseButton::MB_XBUTTON2, MouseButton::MASK_XBUTTON2, true); } else { return; } @@ -826,11 +826,11 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M - (void)otherMouseUp:(NSEvent *)event { if ((int)[event buttonNumber] == 2) { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_MASK_MIDDLE, false); + _mouseDownEvent(window_id, event, MouseButton::MIDDLE, MouseButton::MASK_MIDDLE, false); } else if ((int)[event buttonNumber] == 3) { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_MASK_XBUTTON1, false); + _mouseDownEvent(window_id, event, MouseButton::MB_XBUTTON1, MouseButton::MASK_XBUTTON1, false); } else if ((int)[event buttonNumber] == 4) { - _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON2, MOUSE_BUTTON_MASK_XBUTTON2, false); + _mouseDownEvent(window_id, event, MouseButton::MB_XBUTTON2, MouseButton::MASK_XBUTTON2, false); } else { return; } @@ -922,140 +922,140 @@ static bool isNumpadKey(unsigned int key) { // Keyboard symbol translation table static const Key _osx_to_godot_table[128] = { - /* 00 */ KEY_A, - /* 01 */ KEY_S, - /* 02 */ KEY_D, - /* 03 */ KEY_F, - /* 04 */ KEY_H, - /* 05 */ KEY_G, - /* 06 */ KEY_Z, - /* 07 */ KEY_X, - /* 08 */ KEY_C, - /* 09 */ KEY_V, - /* 0a */ KEY_SECTION, /* ISO Section */ - /* 0b */ KEY_B, - /* 0c */ KEY_Q, - /* 0d */ KEY_W, - /* 0e */ KEY_E, - /* 0f */ KEY_R, - /* 10 */ KEY_Y, - /* 11 */ KEY_T, - /* 12 */ KEY_1, - /* 13 */ KEY_2, - /* 14 */ KEY_3, - /* 15 */ KEY_4, - /* 16 */ KEY_6, - /* 17 */ KEY_5, - /* 18 */ KEY_EQUAL, - /* 19 */ KEY_9, - /* 1a */ KEY_7, - /* 1b */ KEY_MINUS, - /* 1c */ KEY_8, - /* 1d */ KEY_0, - /* 1e */ KEY_BRACERIGHT, - /* 1f */ KEY_O, - /* 20 */ KEY_U, - /* 21 */ KEY_BRACELEFT, - /* 22 */ KEY_I, - /* 23 */ KEY_P, - /* 24 */ KEY_ENTER, - /* 25 */ KEY_L, - /* 26 */ KEY_J, - /* 27 */ KEY_APOSTROPHE, - /* 28 */ KEY_K, - /* 29 */ KEY_SEMICOLON, - /* 2a */ KEY_BACKSLASH, - /* 2b */ KEY_COMMA, - /* 2c */ KEY_SLASH, - /* 2d */ KEY_N, - /* 2e */ KEY_M, - /* 2f */ KEY_PERIOD, - /* 30 */ KEY_TAB, - /* 31 */ KEY_SPACE, - /* 32 */ KEY_QUOTELEFT, - /* 33 */ KEY_BACKSPACE, - /* 34 */ KEY_UNKNOWN, - /* 35 */ KEY_ESCAPE, - /* 36 */ KEY_META, - /* 37 */ KEY_META, - /* 38 */ KEY_SHIFT, - /* 39 */ KEY_CAPSLOCK, - /* 3a */ KEY_ALT, - /* 3b */ KEY_CTRL, - /* 3c */ KEY_SHIFT, - /* 3d */ KEY_ALT, - /* 3e */ KEY_CTRL, - /* 3f */ KEY_UNKNOWN, /* Function */ - /* 40 */ KEY_UNKNOWN, /* F17 */ - /* 41 */ KEY_KP_PERIOD, - /* 42 */ KEY_UNKNOWN, - /* 43 */ KEY_KP_MULTIPLY, - /* 44 */ KEY_UNKNOWN, - /* 45 */ KEY_KP_ADD, - /* 46 */ KEY_UNKNOWN, - /* 47 */ KEY_NUMLOCK, /* Really KeypadClear... */ - /* 48 */ KEY_VOLUMEUP, /* VolumeUp */ - /* 49 */ KEY_VOLUMEDOWN, /* VolumeDown */ - /* 4a */ KEY_VOLUMEMUTE, /* Mute */ - /* 4b */ KEY_KP_DIVIDE, - /* 4c */ KEY_KP_ENTER, - /* 4d */ KEY_UNKNOWN, - /* 4e */ KEY_KP_SUBTRACT, - /* 4f */ KEY_UNKNOWN, /* F18 */ - /* 50 */ KEY_UNKNOWN, /* F19 */ - /* 51 */ KEY_EQUAL, /* KeypadEqual */ - /* 52 */ KEY_KP_0, - /* 53 */ KEY_KP_1, - /* 54 */ KEY_KP_2, - /* 55 */ KEY_KP_3, - /* 56 */ KEY_KP_4, - /* 57 */ KEY_KP_5, - /* 58 */ KEY_KP_6, - /* 59 */ KEY_KP_7, - /* 5a */ KEY_UNKNOWN, /* F20 */ - /* 5b */ KEY_KP_8, - /* 5c */ KEY_KP_9, - /* 5d */ KEY_YEN, /* JIS Yen */ - /* 5e */ KEY_UNDERSCORE, /* JIS Underscore */ - /* 5f */ KEY_COMMA, /* JIS KeypadComma */ - /* 60 */ KEY_F5, - /* 61 */ KEY_F6, - /* 62 */ KEY_F7, - /* 63 */ KEY_F3, - /* 64 */ KEY_F8, - /* 65 */ KEY_F9, - /* 66 */ KEY_UNKNOWN, /* JIS Eisu */ - /* 67 */ KEY_F11, - /* 68 */ KEY_UNKNOWN, /* JIS Kana */ - /* 69 */ KEY_F13, - /* 6a */ KEY_F16, - /* 6b */ KEY_F14, - /* 6c */ KEY_UNKNOWN, - /* 6d */ KEY_F10, - /* 6e */ KEY_MENU, - /* 6f */ KEY_F12, - /* 70 */ KEY_UNKNOWN, - /* 71 */ KEY_F15, - /* 72 */ KEY_INSERT, /* Really Help... */ - /* 73 */ KEY_HOME, - /* 74 */ KEY_PAGEUP, - /* 75 */ KEY_DELETE, - /* 76 */ KEY_F4, - /* 77 */ KEY_END, - /* 78 */ KEY_F2, - /* 79 */ KEY_PAGEDOWN, - /* 7a */ KEY_F1, - /* 7b */ KEY_LEFT, - /* 7c */ KEY_RIGHT, - /* 7d */ KEY_DOWN, - /* 7e */ KEY_UP, - /* 7f */ KEY_UNKNOWN, + /* 00 */ Key::A, + /* 01 */ Key::S, + /* 02 */ Key::D, + /* 03 */ Key::F, + /* 04 */ Key::H, + /* 05 */ Key::G, + /* 06 */ Key::Z, + /* 07 */ Key::X, + /* 08 */ Key::C, + /* 09 */ Key::V, + /* 0a */ Key::SECTION, /* ISO Section */ + /* 0b */ Key::B, + /* 0c */ Key::Q, + /* 0d */ Key::W, + /* 0e */ Key::E, + /* 0f */ Key::R, + /* 10 */ Key::Y, + /* 11 */ Key::T, + /* 12 */ Key::KEY_1, + /* 13 */ Key::KEY_2, + /* 14 */ Key::KEY_3, + /* 15 */ Key::KEY_4, + /* 16 */ Key::KEY_6, + /* 17 */ Key::KEY_5, + /* 18 */ Key::EQUAL, + /* 19 */ Key::KEY_9, + /* 1a */ Key::KEY_7, + /* 1b */ Key::MINUS, + /* 1c */ Key::KEY_8, + /* 1d */ Key::KEY_0, + /* 1e */ Key::BRACERIGHT, + /* 1f */ Key::O, + /* 20 */ Key::U, + /* 21 */ Key::BRACELEFT, + /* 22 */ Key::I, + /* 23 */ Key::P, + /* 24 */ Key::ENTER, + /* 25 */ Key::L, + /* 26 */ Key::J, + /* 27 */ Key::APOSTROPHE, + /* 28 */ Key::K, + /* 29 */ Key::SEMICOLON, + /* 2a */ Key::BACKSLASH, + /* 2b */ Key::COMMA, + /* 2c */ Key::SLASH, + /* 2d */ Key::N, + /* 2e */ Key::M, + /* 2f */ Key::PERIOD, + /* 30 */ Key::TAB, + /* 31 */ Key::SPACE, + /* 32 */ Key::QUOTELEFT, + /* 33 */ Key::BACKSPACE, + /* 34 */ Key::UNKNOWN, + /* 35 */ Key::ESCAPE, + /* 36 */ Key::META, + /* 37 */ Key::META, + /* 38 */ Key::SHIFT, + /* 39 */ Key::CAPSLOCK, + /* 3a */ Key::ALT, + /* 3b */ Key::CTRL, + /* 3c */ Key::SHIFT, + /* 3d */ Key::ALT, + /* 3e */ Key::CTRL, + /* 3f */ Key::UNKNOWN, /* Function */ + /* 40 */ Key::UNKNOWN, /* F17 */ + /* 41 */ Key::KP_PERIOD, + /* 42 */ Key::UNKNOWN, + /* 43 */ Key::KP_MULTIPLY, + /* 44 */ Key::UNKNOWN, + /* 45 */ Key::KP_ADD, + /* 46 */ Key::UNKNOWN, + /* 47 */ Key::NUMLOCK, /* Really KeypadClear... */ + /* 48 */ Key::VOLUMEUP, /* VolumeUp */ + /* 49 */ Key::VOLUMEDOWN, /* VolumeDown */ + /* 4a */ Key::VOLUMEMUTE, /* Mute */ + /* 4b */ Key::KP_DIVIDE, + /* 4c */ Key::KP_ENTER, + /* 4d */ Key::UNKNOWN, + /* 4e */ Key::KP_SUBTRACT, + /* 4f */ Key::UNKNOWN, /* F18 */ + /* 50 */ Key::UNKNOWN, /* F19 */ + /* 51 */ Key::EQUAL, /* KeypadEqual */ + /* 52 */ Key::KP_0, + /* 53 */ Key::KP_1, + /* 54 */ Key::KP_2, + /* 55 */ Key::KP_3, + /* 56 */ Key::KP_4, + /* 57 */ Key::KP_5, + /* 58 */ Key::KP_6, + /* 59 */ Key::KP_7, + /* 5a */ Key::UNKNOWN, /* F20 */ + /* 5b */ Key::KP_8, + /* 5c */ Key::KP_9, + /* 5d */ Key::YEN, /* JIS Yen */ + /* 5e */ Key::UNDERSCORE, /* JIS Underscore */ + /* 5f */ Key::COMMA, /* JIS KeypadComma */ + /* 60 */ Key::F5, + /* 61 */ Key::F6, + /* 62 */ Key::F7, + /* 63 */ Key::F3, + /* 64 */ Key::F8, + /* 65 */ Key::F9, + /* 66 */ Key::UNKNOWN, /* JIS Eisu */ + /* 67 */ Key::F11, + /* 68 */ Key::UNKNOWN, /* JIS Kana */ + /* 69 */ Key::F13, + /* 6a */ Key::F16, + /* 6b */ Key::F14, + /* 6c */ Key::UNKNOWN, + /* 6d */ Key::F10, + /* 6e */ Key::MENU, + /* 6f */ Key::F12, + /* 70 */ Key::UNKNOWN, + /* 71 */ Key::F15, + /* 72 */ Key::INSERT, /* Really Help... */ + /* 73 */ Key::HOME, + /* 74 */ Key::PAGEUP, + /* 75 */ Key::KEY_DELETE, + /* 76 */ Key::F4, + /* 77 */ Key::END, + /* 78 */ Key::F2, + /* 79 */ Key::PAGEDOWN, + /* 7a */ Key::F1, + /* 7b */ Key::LEFT, + /* 7c */ Key::RIGHT, + /* 7d */ Key::DOWN, + /* 7e */ Key::UP, + /* 7f */ Key::UNKNOWN, }; // Translates a OS X keycode to a Godot keycode static Key translateKey(unsigned int key) { if (key >= 128) { - return KEY_UNKNOWN; + return Key::UNKNOWN; } return _osx_to_godot_table[key]; @@ -1077,61 +1077,61 @@ struct _KeyCodeMap { }; static const _KeyCodeMap _keycodes[55] = { - { '`', KEY_QUOTELEFT }, - { '~', KEY_ASCIITILDE }, - { '0', KEY_0 }, - { '1', KEY_1 }, - { '2', KEY_2 }, - { '3', KEY_3 }, - { '4', KEY_4 }, - { '5', KEY_5 }, - { '6', KEY_6 }, - { '7', KEY_7 }, - { '8', KEY_8 }, - { '9', KEY_9 }, - { '-', KEY_MINUS }, - { '_', KEY_UNDERSCORE }, - { '=', KEY_EQUAL }, - { '+', KEY_PLUS }, - { 'q', KEY_Q }, - { 'w', KEY_W }, - { 'e', KEY_E }, - { 'r', KEY_R }, - { 't', KEY_T }, - { 'y', KEY_Y }, - { 'u', KEY_U }, - { 'i', KEY_I }, - { 'o', KEY_O }, - { 'p', KEY_P }, - { '[', KEY_BRACELEFT }, - { ']', KEY_BRACERIGHT }, - { '{', KEY_BRACELEFT }, - { '}', KEY_BRACERIGHT }, - { 'a', KEY_A }, - { 's', KEY_S }, - { 'd', KEY_D }, - { 'f', KEY_F }, - { 'g', KEY_G }, - { 'h', KEY_H }, - { 'j', KEY_J }, - { 'k', KEY_K }, - { 'l', KEY_L }, - { ';', KEY_SEMICOLON }, - { ':', KEY_COLON }, - { '\'', KEY_APOSTROPHE }, - { '\"', KEY_QUOTEDBL }, - { '\\', KEY_BACKSLASH }, - { '#', KEY_NUMBERSIGN }, - { 'z', KEY_Z }, - { 'x', KEY_X }, - { 'c', KEY_C }, - { 'v', KEY_V }, - { 'b', KEY_B }, - { 'n', KEY_N }, - { 'm', KEY_M }, - { ',', KEY_COMMA }, - { '.', KEY_PERIOD }, - { '/', KEY_SLASH } + { '`', Key::QUOTELEFT }, + { '~', Key::ASCIITILDE }, + { '0', Key::KEY_0 }, + { '1', Key::KEY_1 }, + { '2', Key::KEY_2 }, + { '3', Key::KEY_3 }, + { '4', Key::KEY_4 }, + { '5', Key::KEY_5 }, + { '6', Key::KEY_6 }, + { '7', Key::KEY_7 }, + { '8', Key::KEY_8 }, + { '9', Key::KEY_9 }, + { '-', Key::MINUS }, + { '_', Key::UNDERSCORE }, + { '=', Key::EQUAL }, + { '+', Key::PLUS }, + { 'q', Key::Q }, + { 'w', Key::W }, + { 'e', Key::E }, + { 'r', Key::R }, + { 't', Key::T }, + { 'y', Key::Y }, + { 'u', Key::U }, + { 'i', Key::I }, + { 'o', Key::O }, + { 'p', Key::P }, + { '[', Key::BRACELEFT }, + { ']', Key::BRACERIGHT }, + { '{', Key::BRACELEFT }, + { '}', Key::BRACERIGHT }, + { 'a', Key::A }, + { 's', Key::S }, + { 'd', Key::D }, + { 'f', Key::F }, + { 'g', Key::G }, + { 'h', Key::H }, + { 'j', Key::J }, + { 'k', Key::K }, + { 'l', Key::L }, + { ';', Key::SEMICOLON }, + { ':', Key::COLON }, + { '\'', Key::APOSTROPHE }, + { '\"', Key::QUOTEDBL }, + { '\\', Key::BACKSLASH }, + { '#', Key::NUMBERSIGN }, + { 'z', Key::Z }, + { 'x', Key::X }, + { 'c', Key::C }, + { 'v', Key::V }, + { 'b', Key::B }, + { 'n', Key::N }, + { 'm', Key::M }, + { ',', Key::COMMA }, + { '.', Key::PERIOD }, + { '/', Key::SLASH } }; static Key remapKey(unsigned int key, unsigned int state) { @@ -1345,7 +1345,7 @@ inline void sendScrollEvent(DisplayServer::WindowID window_id, MouseButton butto ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; - MouseButton mask = MouseButton(1 << (button - 1)); + MouseButton mask = mouse_button_to_mask(button); Ref<InputEventMouseButton> sc; sc.instantiate(); @@ -1418,10 +1418,10 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy sendPanEvent(window_id, deltaX, deltaY, [event modifierFlags]); } else { if (fabs(deltaX)) { - sendScrollEvent(window_id, 0 > deltaX ? MOUSE_BUTTON_WHEEL_RIGHT : MOUSE_BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]); + sendScrollEvent(window_id, 0 > deltaX ? MouseButton::WHEEL_RIGHT : MouseButton::WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]); } if (fabs(deltaY)) { - sendScrollEvent(window_id, 0 < deltaY ? MOUSE_BUTTON_WHEEL_UP : MOUSE_BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]); + sendScrollEvent(window_id, 0 < deltaY ? MouseButton::WHEEL_UP : MouseButton::WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]); } } } @@ -1920,6 +1920,7 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { return; } + WindowData &wd = windows[MAIN_WINDOW_ID]; if (p_mode == MOUSE_MODE_CAPTURED) { // Apple Docs state that the display parameter is not used. // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." @@ -1928,7 +1929,7 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { CGDisplayHideCursor(kCGDirectMainDisplay); } CGAssociateMouseAndMouseCursorPosition(false); - WindowData &wd = windows[MAIN_WINDOW_ID]; + [wd.window_object setMovable:NO]; const NSRect contentRect = [wd.window_view frame]; NSRect pointInWindowRect = NSMakeRect(contentRect.size.width / 2, contentRect.size.height / 2, 0, 0); NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin; @@ -1938,17 +1939,21 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { CGDisplayHideCursor(kCGDirectMainDisplay); } + [wd.window_object setMovable:YES]; CGAssociateMouseAndMouseCursorPosition(true); } else if (p_mode == MOUSE_MODE_CONFINED) { CGDisplayShowCursor(kCGDirectMainDisplay); + [wd.window_object setMovable:NO]; CGAssociateMouseAndMouseCursorPosition(false); } else if (p_mode == MOUSE_MODE_CONFINED_HIDDEN) { if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { CGDisplayHideCursor(kCGDirectMainDisplay); } + [wd.window_object setMovable:NO]; CGAssociateMouseAndMouseCursorPosition(false); } else { // MOUSE_MODE_VISIBLE CGDisplayShowCursor(kCGDirectMainDisplay); + [wd.window_object setMovable:YES]; CGAssociateMouseAndMouseCursorPosition(true); } @@ -3200,12 +3205,12 @@ String DisplayServerOSX::keyboard_get_layout_name(int p_index) const { } Key DisplayServerOSX::keyboard_get_keycode_from_physical(Key p_keycode) const { - if (p_keycode == KEY_PAUSE) { + if (p_keycode == Key::PAUSE) { return p_keycode; } - unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK; - unsigned int keycode_no_mod = p_keycode & KEY_CODE_MASK; + Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; + Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK; unsigned int osx_keycode = unmapKey((Key)keycode_no_mod); return (Key)(remapKey(osx_keycode, 0) | modifiers); } @@ -3263,8 +3268,8 @@ void DisplayServerOSX::_send_event(NSEvent *p_event) { _get_key_modifier_state([p_event modifierFlags], k); k->set_window_id(DisplayServerOSX::INVALID_WINDOW_ID); k->set_pressed(true); - k->set_keycode(KEY_PERIOD); - k->set_physical_keycode(KEY_PERIOD); + k->set_keycode(Key::PERIOD); + k->set_physical_keycode(Key::PERIOD); k->set_echo([p_event isARepeat]); Input::get_singleton()->parse_input_event(k); @@ -3291,20 +3296,20 @@ void DisplayServerOSX::_process_key_events() { _push_input(k); } else { // IME input - if ((i == 0 && ke.keycode == 0) || (i > 0 && key_event_buffer[i - 1].keycode == 0)) { + if ((i == 0 && ke.keycode == Key::NONE) || (i > 0 && key_event_buffer[i - 1].keycode == Key::NONE)) { k.instantiate(); k->set_window_id(ke.window_id); _get_key_modifier_state(ke.osx_state, k); k->set_pressed(ke.pressed); k->set_echo(ke.echo); - k->set_keycode(KEY_NONE); - k->set_physical_keycode(KEY_NONE); + k->set_keycode(Key::NONE); + k->set_physical_keycode(Key::NONE); k->set_unicode(ke.unicode); _push_input(k); } - if (ke.keycode != 0) { + if (ke.keycode != Key::NONE) { k.instantiate(); k->set_window_id(ke.window_id); @@ -3314,7 +3319,7 @@ void DisplayServerOSX::_process_key_events() { k->set_keycode(ke.keycode); k->set_physical_keycode((Key)ke.physical_keycode); - if (i + 1 < key_event_pos && key_event_buffer[i + 1].keycode == 0) { + if (i + 1 < key_event_pos && key_event_buffer[i + 1].keycode == Key::NONE) { k->set_unicode(key_event_buffer[i + 1].unicode); } diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp index 46ed651384..d4ba7879f1 100644 --- a/platform/osx/joypad_osx.cpp +++ b/platform/osx/joypad_osx.cpp @@ -397,10 +397,10 @@ bool joypad::check_ff_features() { return false; } -static int process_hat_value(int p_min, int p_max, int p_value, bool p_offset_hat) { +static HatMask process_hat_value(int p_min, int p_max, int p_value, bool p_offset_hat) { int range = (p_max - p_min + 1); int value = p_value - p_min; - int hat_value = HatMask::HAT_MASK_CENTER; + HatMask hat_value = HatMask::CENTER; if (range == 4) { value *= 2; } @@ -410,31 +410,31 @@ static int process_hat_value(int p_min, int p_max, int p_value, bool p_offset_ha switch (value) { case 0: - hat_value = (HatMask)HatMask::HAT_MASK_UP; + hat_value = HatMask::UP; break; case 1: - hat_value = (HatMask)(HatMask::HAT_MASK_UP | HatMask::HAT_MASK_RIGHT); + hat_value = (HatMask::UP | HatMask::RIGHT); break; case 2: - hat_value = (HatMask)HatMask::HAT_MASK_RIGHT; + hat_value = HatMask::RIGHT; break; case 3: - hat_value = (HatMask)(HatMask::HAT_MASK_DOWN | HatMask::HAT_MASK_RIGHT); + hat_value = (HatMask::DOWN | HatMask::RIGHT); break; case 4: - hat_value = (HatMask)HatMask::HAT_MASK_DOWN; + hat_value = HatMask::DOWN; break; case 5: - hat_value = (HatMask)(HatMask::HAT_MASK_DOWN | HatMask::HAT_MASK_LEFT); + hat_value = (HatMask::DOWN | HatMask::LEFT); break; case 6: - hat_value = (HatMask)HatMask::HAT_MASK_LEFT; + hat_value = HatMask::LEFT; break; case 7: - hat_value = (HatMask)(HatMask::HAT_MASK_UP | HatMask::HAT_MASK_LEFT); + hat_value = (HatMask::UP | HatMask::LEFT); break; default: - hat_value = (HatMask)HatMask::HAT_MASK_CENTER; + hat_value = HatMask::CENTER; break; } return hat_value; @@ -480,8 +480,8 @@ void JoypadOSX::process_joypads() { for (int j = 0; j < joy.hat_elements.size(); j++) { rec_element &elem = joy.hat_elements.write[j]; int value = joy.get_hid_element_state(&elem); - int hat_value = process_hat_value(elem.min, elem.max, value, joy.offset_hat); - input->joy_hat(joy.id, (HatMask)hat_value); + HatMask hat_value = process_hat_value(elem.min, elem.max, value, joy.offset_hat); + input->joy_hat(joy.id, hat_value); } if (joy.ffservice) { diff --git a/platform/uwp/joypad_uwp.cpp b/platform/uwp/joypad_uwp.cpp index b419fb4fae..f8eb4fc96d 100644 --- a/platform/uwp/joypad_uwp.cpp +++ b/platform/uwp/joypad_uwp.cpp @@ -58,12 +58,12 @@ void JoypadUWP::process_controllers() { button_mask *= 2; } - input->joy_axis(joy.id, JOY_AXIS_LEFT_X, axis_correct(reading.LeftThumbstickX)); - input->joy_axis(joy.id, JOY_AXIS_LEFT_Y, axis_correct(reading.LeftThumbstickY, true)); - input->joy_axis(joy.id, JOY_AXIS_RIGHT_X, axis_correct(reading.RightThumbstickX)); - input->joy_axis(joy.id, JOY_AXIS_RIGHT_Y, axis_correct(reading.RightThumbstickY, true)); - input->joy_axis(joy.id, JOY_AXIS_TRIGGER_LEFT, axis_correct(reading.LeftTrigger, false, true)); - input->joy_axis(joy.id, JOY_AXIS_TRIGGER_RIGHT, axis_correct(reading.RightTrigger, false, true)); + input->joy_axis(joy.id, JoyAxis::LEFT_X, axis_correct(reading.LeftThumbstickX)); + input->joy_axis(joy.id, JoyAxis::LEFT_Y, axis_correct(reading.LeftThumbstickY, true)); + input->joy_axis(joy.id, JoyAxis::RIGHT_X, axis_correct(reading.RightThumbstickX)); + input->joy_axis(joy.id, JoyAxis::RIGHT_Y, axis_correct(reading.RightThumbstickY, true)); + input->joy_axis(joy.id, JoyAxis::TRIGGER_LEFT, axis_correct(reading.LeftTrigger, false, true)); + input->joy_axis(joy.id, JoyAxis::TRIGGER_RIGHT, axis_correct(reading.RightTrigger, false, true)); uint64_t timestamp = input->get_joy_vibration_timestamp(joy.id); if (timestamp > joy.ff_timestamp) { diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 74a9e96b2c..0b4d6b73b6 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -59,7 +59,7 @@ public: bool alt = false, shift = false, control = false; MessageType type = KEY_EVENT_MESSAGE; bool pressed = false; - Key keycode = KEY_NONE; + Key keycode = Key::NONE; unsigned int physical_keycode = 0; unsigned int unicode = 0; bool echo = false; @@ -107,7 +107,7 @@ private: bool control_mem; bool meta_mem; bool force_quit; - MouseButton last_button_state = MOUSE_BUTTON_NONE; + MouseButton last_button_state = MouseButton::NONE; CursorShape cursor_shape; diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 22fbbeb74f..20deb35089 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -226,9 +226,10 @@ def configure_msvc(env, manual_msvc_config): env.AppendUnique(CCFLAGS=["/MD"]) env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"]) - # Force to use Unicode encoding - env.AppendUnique(CCFLAGS=["/utf-8"]) + env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding. + env.AppendUnique(CCFLAGS=["/bigobj"]) # Allow big objects, no drawbacks. env.AppendUnique(CXXFLAGS=["/TP"]) # assume all sources are C++ + if manual_msvc_config: # should be automatic if SCons found it if os.getenv("WindowsSdkDir") is not None: env.Prepend(CPPPATH=[os.getenv("WindowsSdkDir") + "/Include"]) @@ -421,6 +422,7 @@ def configure_mingw(env): ## Compile flags env.Append(CCFLAGS=["-mwindows"]) + env.Append(CCFLAGS=["-Wa,-mbig-obj"]) # Allow big objects, no drawbacks. env.Append(CPPDEFINES=["WINDOWS_ENABLED", "WASAPI_ENABLED", "WINMIDI_ENABLED"]) env.Append(CPPDEFINES=[("WINVER", env["target_win_version"]), ("_WIN32_WINNT", env["target_win_version"])]) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index e2c9951692..9fe15366f4 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -42,6 +42,11 @@ #include "drivers/gles3/rasterizer_gles3.h" #endif +#if defined(__GNUC__) +// Workaround GCC warning from -Wcast-function-type. +#define GetProcAddress (void *)GetProcAddress +#endif + static String format_error_message(DWORD id) { LPWSTR messageBuffer = nullptr; size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, @@ -1495,13 +1500,13 @@ String DisplayServerWindows::keyboard_get_layout_language(int p_index) const { } Key DisplayServerWindows::keyboard_get_keycode_from_physical(Key p_keycode) const { - unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK; - Key keycode_no_mod = (Key)(p_keycode & KEY_CODE_MASK); + Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; + Key keycode_no_mod = (Key)(p_keycode & KeyModifierMask::CODE_MASK); - if (keycode_no_mod == KEY_PRINT || - keycode_no_mod == KEY_KP_ADD || - keycode_no_mod == KEY_KP_5 || - (keycode_no_mod >= KEY_0 && keycode_no_mod <= KEY_9)) { + if (keycode_no_mod == Key::PRINT || + keycode_no_mod == Key::KP_ADD || + keycode_no_mod == Key::KP_5 || + (keycode_no_mod >= Key::KEY_0 && keycode_no_mod <= Key::KEY_9)) { return p_keycode; } @@ -1521,10 +1526,10 @@ Key DisplayServerWindows::keyboard_get_keycode_from_physical(Key p_keycode) cons // we limit these to ASCII to fix some layouts, including Arabic ones if (char_code >= 32 && char_code <= 127) { // Godot uses 'braces' instead of 'brackets' - if (char_code == KEY_BRACKETLEFT || char_code == KEY_BRACKETRIGHT) { + if (char_code == (unsigned int)Key::BRACKETLEFT || char_code == (unsigned int)Key::BRACKETRIGHT) { char_code += 32; } - return (Key)(char_code | modifiers); + return (Key)(char_code | (unsigned int)modifiers); } return (Key)(KeyMappingWindows::get_keysym(vk) | modifiers); @@ -2461,41 +2466,41 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA switch (uMsg) { case WM_LBUTTONDOWN: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_LEFT); + mb->set_button_index(MouseButton::LEFT); } break; case WM_LBUTTONUP: { mb->set_pressed(false); - mb->set_button_index(MOUSE_BUTTON_LEFT); + mb->set_button_index(MouseButton::LEFT); } break; case WM_MBUTTONDOWN: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_MIDDLE); + mb->set_button_index(MouseButton::MIDDLE); } break; case WM_MBUTTONUP: { mb->set_pressed(false); - mb->set_button_index(MOUSE_BUTTON_MIDDLE); + mb->set_button_index(MouseButton::MIDDLE); } break; case WM_RBUTTONDOWN: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_RIGHT); + mb->set_button_index(MouseButton::RIGHT); } break; case WM_RBUTTONUP: { mb->set_pressed(false); - mb->set_button_index(MOUSE_BUTTON_RIGHT); + mb->set_button_index(MouseButton::RIGHT); } break; case WM_LBUTTONDBLCLK: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_LEFT); + mb->set_button_index(MouseButton::LEFT); mb->set_double_click(true); } break; case WM_RBUTTONDBLCLK: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_RIGHT); + mb->set_button_index(MouseButton::RIGHT); mb->set_double_click(true); } break; case WM_MBUTTONDBLCLK: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_MIDDLE); + mb->set_button_index(MouseButton::MIDDLE); mb->set_double_click(true); } break; case WM_MOUSEWHEEL: { @@ -2506,9 +2511,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } if (motion > 0) { - mb->set_button_index(MOUSE_BUTTON_WHEEL_UP); + mb->set_button_index(MouseButton::WHEEL_UP); } else { - mb->set_button_index(MOUSE_BUTTON_WHEEL_DOWN); + mb->set_button_index(MouseButton::WHEEL_DOWN); } mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); } break; @@ -2520,34 +2525,34 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } if (motion < 0) { - mb->set_button_index(MOUSE_BUTTON_WHEEL_LEFT); + mb->set_button_index(MouseButton::WHEEL_LEFT); } else { - mb->set_button_index(MOUSE_BUTTON_WHEEL_RIGHT); + mb->set_button_index(MouseButton::WHEEL_RIGHT); } mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); } break; case WM_XBUTTONDOWN: { mb->set_pressed(true); if (HIWORD(wParam) == XBUTTON1) { - mb->set_button_index(MOUSE_BUTTON_XBUTTON1); + mb->set_button_index(MouseButton::MB_XBUTTON1); } else { - mb->set_button_index(MOUSE_BUTTON_XBUTTON2); + mb->set_button_index(MouseButton::MB_XBUTTON2); } } break; case WM_XBUTTONUP: { mb->set_pressed(false); if (HIWORD(wParam) == XBUTTON1) { - mb->set_button_index(MOUSE_BUTTON_XBUTTON1); + mb->set_button_index(MouseButton::MB_XBUTTON1); } else { - mb->set_button_index(MOUSE_BUTTON_XBUTTON2); + mb->set_button_index(MouseButton::MB_XBUTTON2); } } break; case WM_XBUTTONDBLCLK: { mb->set_pressed(true); if (HIWORD(wParam) == XBUTTON1) { - mb->set_button_index(MOUSE_BUTTON_XBUTTON1); + mb->set_button_index(MouseButton::MB_XBUTTON1); } else { - mb->set_button_index(MOUSE_BUTTON_XBUTTON2); + mb->set_button_index(MouseButton::MB_XBUTTON2); } mb->set_double_click(true); } break; @@ -2561,9 +2566,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mb->set_alt_pressed(alt_mem); // mb->is_alt_pressed()=(wParam&MK_MENU)!=0; if (mb->is_pressed()) { - last_button_state |= MouseButton(1 << (mb->get_button_index() - 1)); + last_button_state |= mouse_button_to_mask(mb->get_button_index()); } else { - last_button_state &= (MouseButton) ~(1 << (mb->get_button_index() - 1)); + last_button_state &= ~mouse_button_to_mask(mb->get_button_index()); } mb->set_button_mask(last_button_state); @@ -2599,11 +2604,11 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mb->set_global_position(mb->get_position()); Input::get_singleton()->parse_input_event(mb); - if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) { + if (mb->is_pressed() && mb->get_button_index() >= MouseButton::WHEEL_UP && mb->get_button_index() <= MouseButton::WHEEL_RIGHT) { // Send release for mouse wheel. Ref<InputEventMouseButton> mbd = mb->duplicate(); mbd->set_window_id(window_id); - last_button_state &= (MouseButton) ~(1 << (mbd->get_button_index() - 1)); + last_button_state &= ~mouse_button_to_mask(mbd->get_button_index()); mbd->set_button_mask(last_button_state); mbd->set_pressed(false); Input::get_singleton()->parse_input_event(mbd); @@ -2953,7 +2958,7 @@ void DisplayServerWindows::_process_key_events() { if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) { // Special case for Numpad Enter key. - k->set_keycode(KEY_KP_ENTER); + k->set_keycode(Key::KP_ENTER); } else { k->set_keycode((Key)KeyMappingWindows::get_keysym(ke.wParam)); } diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 8e2c346d5b..a59f8ebb44 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -410,7 +410,7 @@ class DisplayServerWindows : public DisplayServer { bool shift_mem = false; bool control_mem = false; bool meta_mem = false; - MouseButton last_button_state = MOUSE_BUTTON_NONE; + MouseButton last_button_state = MouseButton::NONE; bool use_raw_input = false; bool drop_events = false; bool in_dispatch_input_event = false; diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp index 98205d6282..1ce8b0b040 100644 --- a/platform/windows/gl_manager_windows.cpp +++ b/platform/windows/gl_manager_windows.cpp @@ -197,9 +197,6 @@ Error GLManager_Windows::window_create(DisplayServer::WindowID p_window_id, HWND return FAILED; } - // the display could be invalid .. check NYI - GLDisplay &gl_display = _displays[win.gldisplay_id]; - // make current window_make_current(_windows.size() - 1); diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp index 94da63e49d..1d3761ee83 100644 --- a/platform/windows/joypad_windows.cpp +++ b/platform/windows/joypad_windows.cpp @@ -334,12 +334,12 @@ void JoypadWindows::process_joypads() { button_mask = button_mask * 2; } - input->joy_axis(joy.id, JOY_AXIS_LEFT_X, axis_correct(joy.state.Gamepad.sThumbLX, true)); - input->joy_axis(joy.id, JOY_AXIS_LEFT_Y, axis_correct(joy.state.Gamepad.sThumbLY, true, false, true)); - input->joy_axis(joy.id, JOY_AXIS_RIGHT_X, axis_correct(joy.state.Gamepad.sThumbRX, true)); - input->joy_axis(joy.id, JOY_AXIS_RIGHT_Y, axis_correct(joy.state.Gamepad.sThumbRY, true, false, true)); - input->joy_axis(joy.id, JOY_AXIS_TRIGGER_LEFT, axis_correct(joy.state.Gamepad.bLeftTrigger, true, true)); - input->joy_axis(joy.id, JOY_AXIS_TRIGGER_RIGHT, axis_correct(joy.state.Gamepad.bRightTrigger, true, true)); + input->joy_axis(joy.id, JoyAxis::LEFT_X, axis_correct(joy.state.Gamepad.sThumbLX, true)); + input->joy_axis(joy.id, JoyAxis::LEFT_Y, axis_correct(joy.state.Gamepad.sThumbLY, true, false, true)); + input->joy_axis(joy.id, JoyAxis::RIGHT_X, axis_correct(joy.state.Gamepad.sThumbRX, true)); + input->joy_axis(joy.id, JoyAxis::RIGHT_Y, axis_correct(joy.state.Gamepad.sThumbRY, true, false, true)); + input->joy_axis(joy.id, JoyAxis::TRIGGER_LEFT, axis_correct(joy.state.Gamepad.bLeftTrigger, true, true)); + input->joy_axis(joy.id, JoyAxis::TRIGGER_RIGHT, axis_correct(joy.state.Gamepad.bRightTrigger, true, true)); joy.last_packet = joy.state.dwPacketNumber; } uint64_t timestamp = input->get_joy_vibration_timestamp(joy.id); @@ -417,31 +417,31 @@ void JoypadWindows::post_hat(int p_device, DWORD p_dpad) { // BOOL POVCentered = (LOWORD(dwPOV) == 0xFFFF);" // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee416628(v%3Dvs.85)#remarks if (LOWORD(p_dpad) == 0xFFFF) { - dpad_val = (HatMask)HatMask::HAT_MASK_CENTER; + dpad_val = (HatMask)HatMask::CENTER; } if (p_dpad == 0) { - dpad_val = (HatMask)HatMask::HAT_MASK_UP; + dpad_val = (HatMask)HatMask::UP; } else if (p_dpad == 4500) { - dpad_val = (HatMask)(HatMask::HAT_MASK_UP | HatMask::HAT_MASK_RIGHT); + dpad_val = (HatMask)(HatMask::UP | HatMask::RIGHT); } else if (p_dpad == 9000) { - dpad_val = (HatMask)HatMask::HAT_MASK_RIGHT; + dpad_val = (HatMask)HatMask::RIGHT; } else if (p_dpad == 13500) { - dpad_val = (HatMask)(HatMask::HAT_MASK_RIGHT | HatMask::HAT_MASK_DOWN); + dpad_val = (HatMask)(HatMask::RIGHT | HatMask::DOWN); } else if (p_dpad == 18000) { - dpad_val = (HatMask)HatMask::HAT_MASK_DOWN; + dpad_val = (HatMask)HatMask::DOWN; } else if (p_dpad == 22500) { - dpad_val = (HatMask)(HatMask::HAT_MASK_DOWN | HatMask::HAT_MASK_LEFT); + dpad_val = (HatMask)(HatMask::DOWN | HatMask::LEFT); } else if (p_dpad == 27000) { - dpad_val = (HatMask)HatMask::HAT_MASK_LEFT; + dpad_val = (HatMask)HatMask::LEFT; } else if (p_dpad == 31500) { - dpad_val = (HatMask)(HatMask::HAT_MASK_LEFT | HatMask::HAT_MASK_UP); + dpad_val = (HatMask)(HatMask::LEFT | HatMask::UP); } input->joy_hat(p_device, dpad_val); }; diff --git a/platform/windows/key_mapping_windows.cpp b/platform/windows/key_mapping_windows.cpp index b9cf8151fc..65ee5dd46b 100644 --- a/platform/windows/key_mapping_windows.cpp +++ b/platform/windows/key_mapping_windows.cpp @@ -33,200 +33,200 @@ #include <stdio.h> struct _WinTranslatePair { - unsigned int keysym; + Key keysym; unsigned int keycode; }; static _WinTranslatePair _vk_to_keycode[] = { - { KEY_BACKSPACE, VK_BACK }, // (0x08) // backspace - { KEY_TAB, VK_TAB }, //(0x09) + { Key::BACKSPACE, VK_BACK }, // (0x08) // backspace + { Key::TAB, VK_TAB }, //(0x09) //VK_CLEAR (0x0C) - { KEY_ENTER, VK_RETURN }, //(0x0D) + { Key::ENTER, VK_RETURN }, //(0x0D) - { KEY_SHIFT, VK_SHIFT }, //(0x10) + { Key::SHIFT, VK_SHIFT }, //(0x10) - { KEY_CTRL, VK_CONTROL }, //(0x11) + { Key::CTRL, VK_CONTROL }, //(0x11) - { KEY_ALT, VK_MENU }, //(0x12) + { Key::ALT, VK_MENU }, //(0x12) - { KEY_PAUSE, VK_PAUSE }, //(0x13) + { Key::PAUSE, VK_PAUSE }, //(0x13) - { KEY_CAPSLOCK, VK_CAPITAL }, //(0x14) + { Key::CAPSLOCK, VK_CAPITAL }, //(0x14) - { KEY_ESCAPE, VK_ESCAPE }, //(0x1B) + { Key::ESCAPE, VK_ESCAPE }, //(0x1B) - { KEY_SPACE, VK_SPACE }, //(0x20) + { Key::SPACE, VK_SPACE }, //(0x20) - { KEY_PAGEUP, VK_PRIOR }, //(0x21) + { Key::PAGEUP, VK_PRIOR }, //(0x21) - { KEY_PAGEDOWN, VK_NEXT }, //(0x22) + { Key::PAGEDOWN, VK_NEXT }, //(0x22) - { KEY_END, VK_END }, //(0x23) + { Key::END, VK_END }, //(0x23) - { KEY_HOME, VK_HOME }, //(0x24) + { Key::HOME, VK_HOME }, //(0x24) - { KEY_LEFT, VK_LEFT }, //(0x25) + { Key::LEFT, VK_LEFT }, //(0x25) - { KEY_UP, VK_UP }, //(0x26) + { Key::UP, VK_UP }, //(0x26) - { KEY_RIGHT, VK_RIGHT }, //(0x27) + { Key::RIGHT, VK_RIGHT }, //(0x27) - { KEY_DOWN, VK_DOWN }, // (0x28) + { Key::DOWN, VK_DOWN }, // (0x28) //VK_SELECT (0x29) - { KEY_PRINT, VK_PRINT }, // (0x2A) + { Key::PRINT, VK_PRINT }, // (0x2A) //VK_EXECUTE (0x2B) - { KEY_PRINT, VK_SNAPSHOT }, // (0x2C) - - { KEY_INSERT, VK_INSERT }, // (0x2D) - - { KEY_DELETE, VK_DELETE }, // (0x2E) - - { KEY_HELP, VK_HELP }, // (0x2F) - - { KEY_0, (0x30) }, ////0 key - { KEY_1, (0x31) }, ////1 key - { KEY_2, (0x32) }, ////2 key - { KEY_3, (0x33) }, ////3 key - { KEY_4, (0x34) }, ////4 key - { KEY_5, (0x35) }, ////5 key - { KEY_6, (0x36) }, ////6 key - { KEY_7, (0x37) }, ////7 key - { KEY_8, (0x38) }, ////8 key - { KEY_9, (0x39) }, ////9 key - { KEY_A, (0x41) }, ////A key - { KEY_B, (0x42) }, ////B key - { KEY_C, (0x43) }, ////C key - { KEY_D, (0x44) }, ////D key - { KEY_E, (0x45) }, ////E key - { KEY_F, (0x46) }, ////F key - { KEY_G, (0x47) }, ////G key - { KEY_H, (0x48) }, ////H key - { KEY_I, (0x49) }, ////I key - { KEY_J, (0x4A) }, ////J key - { KEY_K, (0x4B) }, ////K key - { KEY_L, (0x4C) }, ////L key - { KEY_M, (0x4D) }, ////M key - { KEY_N, (0x4E) }, ////N key - { KEY_O, (0x4F) }, ////O key - { KEY_P, (0x50) }, ////P key - { KEY_Q, (0x51) }, ////Q key - { KEY_R, (0x52) }, ////R key - { KEY_S, (0x53) }, ////S key - { KEY_T, (0x54) }, ////T key - { KEY_U, (0x55) }, ////U key - { KEY_V, (0x56) }, ////V key - { KEY_W, (0x57) }, ////W key - { KEY_X, (0x58) }, ////X key - { KEY_Y, (0x59) }, ////Y key - { KEY_Z, (0x5A) }, ////Z key - - { KEY_MASK_META, VK_LWIN }, //(0x5B) - { KEY_MASK_META, VK_RWIN }, //(0x5C) - { KEY_MENU, VK_APPS }, //(0x5D) - { KEY_STANDBY, VK_SLEEP }, //(0x5F) - { KEY_KP_0, VK_NUMPAD0 }, //(0x60) - { KEY_KP_1, VK_NUMPAD1 }, //(0x61) - { KEY_KP_2, VK_NUMPAD2 }, //(0x62) - { KEY_KP_3, VK_NUMPAD3 }, //(0x63) - { KEY_KP_4, VK_NUMPAD4 }, //(0x64) - { KEY_KP_5, VK_NUMPAD5 }, //(0x65) - { KEY_KP_6, VK_NUMPAD6 }, //(0x66) - { KEY_KP_7, VK_NUMPAD7 }, //(0x67) - { KEY_KP_8, VK_NUMPAD8 }, //(0x68) - { KEY_KP_9, VK_NUMPAD9 }, //(0x69) - { KEY_KP_MULTIPLY, VK_MULTIPLY }, // (0x6A) - { KEY_KP_ADD, VK_ADD }, // (0x6B) + { Key::PRINT, VK_SNAPSHOT }, // (0x2C) + + { Key::INSERT, VK_INSERT }, // (0x2D) + + { Key::KEY_DELETE, VK_DELETE }, // (0x2E) + + { Key::HELP, VK_HELP }, // (0x2F) + + { Key::KEY_0, (0x30) }, ////0 key + { Key::KEY_1, (0x31) }, ////1 key + { Key::KEY_2, (0x32) }, ////2 key + { Key::KEY_3, (0x33) }, ////3 key + { Key::KEY_4, (0x34) }, ////4 key + { Key::KEY_5, (0x35) }, ////5 key + { Key::KEY_6, (0x36) }, ////6 key + { Key::KEY_7, (0x37) }, ////7 key + { Key::KEY_8, (0x38) }, ////8 key + { Key::KEY_9, (0x39) }, ////9 key + { Key::A, (0x41) }, ////A key + { Key::B, (0x42) }, ////B key + { Key::C, (0x43) }, ////C key + { Key::D, (0x44) }, ////D key + { Key::E, (0x45) }, ////E key + { Key::F, (0x46) }, ////F key + { Key::G, (0x47) }, ////G key + { Key::H, (0x48) }, ////H key + { Key::I, (0x49) }, ////I key + { Key::J, (0x4A) }, ////J key + { Key::K, (0x4B) }, ////K key + { Key::L, (0x4C) }, ////L key + { Key::M, (0x4D) }, ////M key + { Key::N, (0x4E) }, ////N key + { Key::O, (0x4F) }, ////O key + { Key::P, (0x50) }, ////P key + { Key::Q, (0x51) }, ////Q key + { Key::R, (0x52) }, ////R key + { Key::S, (0x53) }, ////S key + { Key::T, (0x54) }, ////T key + { Key::U, (0x55) }, ////U key + { Key::V, (0x56) }, ////V key + { Key::W, (0x57) }, ////W key + { Key::X, (0x58) }, ////X key + { Key::Y, (0x59) }, ////Y key + { Key::Z, (0x5A) }, ////Z key + + { (Key)KeyModifierMask::META, VK_LWIN }, //(0x5B) + { (Key)KeyModifierMask::META, VK_RWIN }, //(0x5C) + { Key::MENU, VK_APPS }, //(0x5D) + { Key::STANDBY, VK_SLEEP }, //(0x5F) + { Key::KP_0, VK_NUMPAD0 }, //(0x60) + { Key::KP_1, VK_NUMPAD1 }, //(0x61) + { Key::KP_2, VK_NUMPAD2 }, //(0x62) + { Key::KP_3, VK_NUMPAD3 }, //(0x63) + { Key::KP_4, VK_NUMPAD4 }, //(0x64) + { Key::KP_5, VK_NUMPAD5 }, //(0x65) + { Key::KP_6, VK_NUMPAD6 }, //(0x66) + { Key::KP_7, VK_NUMPAD7 }, //(0x67) + { Key::KP_8, VK_NUMPAD8 }, //(0x68) + { Key::KP_9, VK_NUMPAD9 }, //(0x69) + { Key::KP_MULTIPLY, VK_MULTIPLY }, // (0x6A) + { Key::KP_ADD, VK_ADD }, // (0x6B) //VK_SEPARATOR (0x6C) - { KEY_KP_SUBTRACT, VK_SUBTRACT }, // (0x6D) - { KEY_KP_PERIOD, VK_DECIMAL }, // (0x6E) - { KEY_KP_DIVIDE, VK_DIVIDE }, // (0x6F) - { KEY_F1, VK_F1 }, // (0x70) - { KEY_F2, VK_F2 }, // (0x71) - { KEY_F3, VK_F3 }, // (0x72) - { KEY_F4, VK_F4 }, // (0x73) - { KEY_F5, VK_F5 }, // (0x74) - { KEY_F6, VK_F6 }, // (0x75) - { KEY_F7, VK_F7 }, // (0x76) - { KEY_F8, VK_F8 }, // (0x77) - { KEY_F9, VK_F9 }, // (0x78) - { KEY_F10, VK_F10 }, // (0x79) - { KEY_F11, VK_F11 }, // (0x7A) - { KEY_F12, VK_F12 }, // (0x7B) - { KEY_F13, VK_F13 }, // (0x7C) - { KEY_F14, VK_F14 }, // (0x7D) - { KEY_F15, VK_F15 }, // (0x7E) - { KEY_F16, VK_F16 }, // (0x7F) - { KEY_NUMLOCK, VK_NUMLOCK }, // (0x90) - { KEY_SCROLLLOCK, VK_SCROLL }, // (0x91) - { KEY_SHIFT, VK_LSHIFT }, // (0xA0) - { KEY_SHIFT, VK_RSHIFT }, // (0xA1) - { KEY_CTRL, VK_LCONTROL }, // (0xA2) - { KEY_CTRL, VK_RCONTROL }, // (0xA3) - { KEY_MENU, VK_LMENU }, // (0xA4) - { KEY_MENU, VK_RMENU }, // (0xA5) + { Key::KP_SUBTRACT, VK_SUBTRACT }, // (0x6D) + { Key::KP_PERIOD, VK_DECIMAL }, // (0x6E) + { Key::KP_DIVIDE, VK_DIVIDE }, // (0x6F) + { Key::F1, VK_F1 }, // (0x70) + { Key::F2, VK_F2 }, // (0x71) + { Key::F3, VK_F3 }, // (0x72) + { Key::F4, VK_F4 }, // (0x73) + { Key::F5, VK_F5 }, // (0x74) + { Key::F6, VK_F6 }, // (0x75) + { Key::F7, VK_F7 }, // (0x76) + { Key::F8, VK_F8 }, // (0x77) + { Key::F9, VK_F9 }, // (0x78) + { Key::F10, VK_F10 }, // (0x79) + { Key::F11, VK_F11 }, // (0x7A) + { Key::F12, VK_F12 }, // (0x7B) + { Key::F13, VK_F13 }, // (0x7C) + { Key::F14, VK_F14 }, // (0x7D) + { Key::F15, VK_F15 }, // (0x7E) + { Key::F16, VK_F16 }, // (0x7F) + { Key::NUMLOCK, VK_NUMLOCK }, // (0x90) + { Key::SCROLLLOCK, VK_SCROLL }, // (0x91) + { Key::SHIFT, VK_LSHIFT }, // (0xA0) + { Key::SHIFT, VK_RSHIFT }, // (0xA1) + { Key::CTRL, VK_LCONTROL }, // (0xA2) + { Key::CTRL, VK_RCONTROL }, // (0xA3) + { Key::MENU, VK_LMENU }, // (0xA4) + { Key::MENU, VK_RMENU }, // (0xA5) - { KEY_BACK, VK_BROWSER_BACK }, // (0xA6) + { Key::BACK, VK_BROWSER_BACK }, // (0xA6) - { KEY_FORWARD, VK_BROWSER_FORWARD }, // (0xA7) + { Key::FORWARD, VK_BROWSER_FORWARD }, // (0xA7) - { KEY_REFRESH, VK_BROWSER_REFRESH }, // (0xA8) + { Key::REFRESH, VK_BROWSER_REFRESH }, // (0xA8) - { KEY_STOP, VK_BROWSER_STOP }, // (0xA9) + { Key::STOP, VK_BROWSER_STOP }, // (0xA9) - { KEY_SEARCH, VK_BROWSER_SEARCH }, // (0xAA) + { Key::SEARCH, VK_BROWSER_SEARCH }, // (0xAA) - { KEY_FAVORITES, VK_BROWSER_FAVORITES }, // (0xAB) + { Key::FAVORITES, VK_BROWSER_FAVORITES }, // (0xAB) - { KEY_HOMEPAGE, VK_BROWSER_HOME }, // (0xAC) + { Key::HOMEPAGE, VK_BROWSER_HOME }, // (0xAC) - { KEY_VOLUMEMUTE, VK_VOLUME_MUTE }, // (0xAD) + { Key::VOLUMEMUTE, VK_VOLUME_MUTE }, // (0xAD) - { KEY_VOLUMEDOWN, VK_VOLUME_DOWN }, // (0xAE) + { Key::VOLUMEDOWN, VK_VOLUME_DOWN }, // (0xAE) - { KEY_VOLUMEUP, VK_VOLUME_UP }, // (0xAF) + { Key::VOLUMEUP, VK_VOLUME_UP }, // (0xAF) - { KEY_MEDIANEXT, VK_MEDIA_NEXT_TRACK }, // (0xB0) + { Key::MEDIANEXT, VK_MEDIA_NEXT_TRACK }, // (0xB0) - { KEY_MEDIAPREVIOUS, VK_MEDIA_PREV_TRACK }, // (0xB1) + { Key::MEDIAPREVIOUS, VK_MEDIA_PREV_TRACK }, // (0xB1) - { KEY_MEDIASTOP, VK_MEDIA_STOP }, // (0xB2) + { Key::MEDIASTOP, VK_MEDIA_STOP }, // (0xB2) //VK_MEDIA_PLAY_PAUSE (0xB3) - { KEY_LAUNCHMAIL, VK_LAUNCH_MAIL }, // (0xB4) + { Key::LAUNCHMAIL, VK_LAUNCH_MAIL }, // (0xB4) - { KEY_LAUNCHMEDIA, VK_LAUNCH_MEDIA_SELECT }, // (0xB5) + { Key::LAUNCHMEDIA, VK_LAUNCH_MEDIA_SELECT }, // (0xB5) - { KEY_LAUNCH0, VK_LAUNCH_APP1 }, // (0xB6) + { Key::LAUNCH0, VK_LAUNCH_APP1 }, // (0xB6) - { KEY_LAUNCH1, VK_LAUNCH_APP2 }, // (0xB7) + { Key::LAUNCH1, VK_LAUNCH_APP2 }, // (0xB7) - { KEY_SEMICOLON, VK_OEM_1 }, // (0xBA) + { Key::SEMICOLON, VK_OEM_1 }, // (0xBA) - { KEY_EQUAL, VK_OEM_PLUS }, // (0xBB) // Windows 2000/XP: For any country/region, the '+' key - { KEY_COMMA, VK_OEM_COMMA }, // (0xBC) // Windows 2000/XP: For any country/region, the ',' key - { KEY_MINUS, VK_OEM_MINUS }, // (0xBD) // Windows 2000/XP: For any country/region, the '-' key - { KEY_PERIOD, VK_OEM_PERIOD }, // (0xBE) // Windows 2000/XP: For any country/region, the '.' key - { KEY_SLASH, VK_OEM_2 }, // (0xBF) //Windows 2000/XP: For the US standard keyboard, the '/?' key + { Key::EQUAL, VK_OEM_PLUS }, // (0xBB) // Windows 2000/XP: For any country/region, the '+' key + { Key::COMMA, VK_OEM_COMMA }, // (0xBC) // Windows 2000/XP: For any country/region, the ',' key + { Key::MINUS, VK_OEM_MINUS }, // (0xBD) // Windows 2000/XP: For any country/region, the '-' key + { Key::PERIOD, VK_OEM_PERIOD }, // (0xBE) // Windows 2000/XP: For any country/region, the '.' key + { Key::SLASH, VK_OEM_2 }, // (0xBF) //Windows 2000/XP: For the US standard keyboard, the '/?' key - { KEY_QUOTELEFT, VK_OEM_3 }, // (0xC0) - { KEY_BRACELEFT, VK_OEM_4 }, // (0xDB) - { KEY_BACKSLASH, VK_OEM_5 }, // (0xDC) - { KEY_BRACERIGHT, VK_OEM_6 }, // (0xDD) - { KEY_APOSTROPHE, VK_OEM_7 }, // (0xDE) + { Key::QUOTELEFT, VK_OEM_3 }, // (0xC0) + { Key::BRACELEFT, VK_OEM_4 }, // (0xDB) + { Key::BACKSLASH, VK_OEM_5 }, // (0xDC) + { Key::BRACERIGHT, VK_OEM_6 }, // (0xDD) + { Key::APOSTROPHE, VK_OEM_7 }, // (0xDE) /* {VK_OEM_8 (0xDF) {VK_OEM_102 (0xE2) // Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard */ - //{ KEY_PLAY, VK_PLAY},// (0xFA) + //{ Key::PLAY, VK_PLAY},// (0xFA) - { KEY_UNKNOWN, 0 } + { Key::UNKNOWN, 0 } }; /* @@ -237,104 +237,104 @@ VK_OEM_CLEAR (0xFE) */ static _WinTranslatePair _scancode_to_keycode[] = { - { KEY_ESCAPE, 0x01 }, - { KEY_1, 0x02 }, - { KEY_2, 0x03 }, - { KEY_3, 0x04 }, - { KEY_4, 0x05 }, - { KEY_5, 0x06 }, - { KEY_6, 0x07 }, - { KEY_7, 0x08 }, - { KEY_8, 0x09 }, - { KEY_9, 0x0A }, - { KEY_0, 0x0B }, - { KEY_MINUS, 0x0C }, - { KEY_EQUAL, 0x0D }, - { KEY_BACKSPACE, 0x0E }, - { KEY_TAB, 0x0F }, - { KEY_Q, 0x10 }, - { KEY_W, 0x11 }, - { KEY_E, 0x12 }, - { KEY_R, 0x13 }, - { KEY_T, 0x14 }, - { KEY_Y, 0x15 }, - { KEY_U, 0x16 }, - { KEY_I, 0x17 }, - { KEY_O, 0x18 }, - { KEY_P, 0x19 }, - { KEY_BRACELEFT, 0x1A }, - { KEY_BRACERIGHT, 0x1B }, - { KEY_ENTER, 0x1C }, - { KEY_CTRL, 0x1D }, - { KEY_A, 0x1E }, - { KEY_S, 0x1F }, - { KEY_D, 0x20 }, - { KEY_F, 0x21 }, - { KEY_G, 0x22 }, - { KEY_H, 0x23 }, - { KEY_J, 0x24 }, - { KEY_K, 0x25 }, - { KEY_L, 0x26 }, - { KEY_SEMICOLON, 0x27 }, - { KEY_APOSTROPHE, 0x28 }, - { KEY_QUOTELEFT, 0x29 }, - { KEY_SHIFT, 0x2A }, - { KEY_BACKSLASH, 0x2B }, - { KEY_Z, 0x2C }, - { KEY_X, 0x2D }, - { KEY_C, 0x2E }, - { KEY_V, 0x2F }, - { KEY_B, 0x30 }, - { KEY_N, 0x31 }, - { KEY_M, 0x32 }, - { KEY_COMMA, 0x33 }, - { KEY_PERIOD, 0x34 }, - { KEY_SLASH, 0x35 }, - { KEY_SHIFT, 0x36 }, - { KEY_PRINT, 0x37 }, - { KEY_ALT, 0x38 }, - { KEY_SPACE, 0x39 }, - { KEY_CAPSLOCK, 0x3A }, - { KEY_F1, 0x3B }, - { KEY_F2, 0x3C }, - { KEY_F3, 0x3D }, - { KEY_F4, 0x3E }, - { KEY_F5, 0x3F }, - { KEY_F6, 0x40 }, - { KEY_F7, 0x41 }, - { KEY_F8, 0x42 }, - { KEY_F9, 0x43 }, - { KEY_F10, 0x44 }, - { KEY_NUMLOCK, 0x45 }, - { KEY_SCROLLLOCK, 0x46 }, - { KEY_HOME, 0x47 }, - { KEY_UP, 0x48 }, - { KEY_PAGEUP, 0x49 }, - { KEY_KP_SUBTRACT, 0x4A }, - { KEY_LEFT, 0x4B }, - { KEY_KP_5, 0x4C }, - { KEY_RIGHT, 0x4D }, - { KEY_KP_ADD, 0x4E }, - { KEY_END, 0x4F }, - { KEY_DOWN, 0x50 }, - { KEY_PAGEDOWN, 0x51 }, - { KEY_INSERT, 0x52 }, - { KEY_DELETE, 0x53 }, - //{ KEY_???, 0x56 }, //NON US BACKSLASH - { KEY_F11, 0x57 }, - { KEY_F12, 0x58 }, - { KEY_META, 0x5B }, - { KEY_META, 0x5C }, - { KEY_MENU, 0x5D }, - { KEY_F13, 0x64 }, - { KEY_F14, 0x65 }, - { KEY_F15, 0x66 }, - { KEY_F16, 0x67 }, - { KEY_UNKNOWN, 0 } + { Key::ESCAPE, 0x01 }, + { Key::KEY_1, 0x02 }, + { Key::KEY_2, 0x03 }, + { Key::KEY_3, 0x04 }, + { Key::KEY_4, 0x05 }, + { Key::KEY_5, 0x06 }, + { Key::KEY_6, 0x07 }, + { Key::KEY_7, 0x08 }, + { Key::KEY_8, 0x09 }, + { Key::KEY_9, 0x0A }, + { Key::KEY_0, 0x0B }, + { Key::MINUS, 0x0C }, + { Key::EQUAL, 0x0D }, + { Key::BACKSPACE, 0x0E }, + { Key::TAB, 0x0F }, + { Key::Q, 0x10 }, + { Key::W, 0x11 }, + { Key::E, 0x12 }, + { Key::R, 0x13 }, + { Key::T, 0x14 }, + { Key::Y, 0x15 }, + { Key::U, 0x16 }, + { Key::I, 0x17 }, + { Key::O, 0x18 }, + { Key::P, 0x19 }, + { Key::BRACELEFT, 0x1A }, + { Key::BRACERIGHT, 0x1B }, + { Key::ENTER, 0x1C }, + { Key::CTRL, 0x1D }, + { Key::A, 0x1E }, + { Key::S, 0x1F }, + { Key::D, 0x20 }, + { Key::F, 0x21 }, + { Key::G, 0x22 }, + { Key::H, 0x23 }, + { Key::J, 0x24 }, + { Key::K, 0x25 }, + { Key::L, 0x26 }, + { Key::SEMICOLON, 0x27 }, + { Key::APOSTROPHE, 0x28 }, + { Key::QUOTELEFT, 0x29 }, + { Key::SHIFT, 0x2A }, + { Key::BACKSLASH, 0x2B }, + { Key::Z, 0x2C }, + { Key::X, 0x2D }, + { Key::C, 0x2E }, + { Key::V, 0x2F }, + { Key::B, 0x30 }, + { Key::N, 0x31 }, + { Key::M, 0x32 }, + { Key::COMMA, 0x33 }, + { Key::PERIOD, 0x34 }, + { Key::SLASH, 0x35 }, + { Key::SHIFT, 0x36 }, + { Key::PRINT, 0x37 }, + { Key::ALT, 0x38 }, + { Key::SPACE, 0x39 }, + { Key::CAPSLOCK, 0x3A }, + { Key::F1, 0x3B }, + { Key::F2, 0x3C }, + { Key::F3, 0x3D }, + { Key::F4, 0x3E }, + { Key::F5, 0x3F }, + { Key::F6, 0x40 }, + { Key::F7, 0x41 }, + { Key::F8, 0x42 }, + { Key::F9, 0x43 }, + { Key::F10, 0x44 }, + { Key::NUMLOCK, 0x45 }, + { Key::SCROLLLOCK, 0x46 }, + { Key::HOME, 0x47 }, + { Key::UP, 0x48 }, + { Key::PAGEUP, 0x49 }, + { Key::KP_SUBTRACT, 0x4A }, + { Key::LEFT, 0x4B }, + { Key::KP_5, 0x4C }, + { Key::RIGHT, 0x4D }, + { Key::KP_ADD, 0x4E }, + { Key::END, 0x4F }, + { Key::DOWN, 0x50 }, + { Key::PAGEDOWN, 0x51 }, + { Key::INSERT, 0x52 }, + { Key::KEY_DELETE, 0x53 }, + //{ Key::???, 0x56 }, //NON US BACKSLASH + { Key::F11, 0x57 }, + { Key::F12, 0x58 }, + { Key::META, 0x5B }, + { Key::META, 0x5C }, + { Key::MENU, 0x5D }, + { Key::F13, 0x64 }, + { Key::F14, 0x65 }, + { Key::F15, 0x66 }, + { Key::F16, 0x67 }, + { Key::UNKNOWN, 0 } }; -unsigned int KeyMappingWindows::get_keysym(unsigned int p_code) { - for (int i = 0; _vk_to_keycode[i].keysym != KEY_UNKNOWN; i++) { +Key KeyMappingWindows::get_keysym(unsigned int p_code) { + for (int i = 0; _vk_to_keycode[i].keysym != Key::UNKNOWN; i++) { if (_vk_to_keycode[i].keycode == p_code) { //printf("outcode: %x\n",_vk_to_keycode[i].keysym); @@ -342,11 +342,11 @@ unsigned int KeyMappingWindows::get_keysym(unsigned int p_code) { } } - return KEY_UNKNOWN; + return Key::UNKNOWN; } unsigned int KeyMappingWindows::get_scancode(Key p_keycode) { - for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) { + for (int i = 0; _scancode_to_keycode[i].keysym != Key::UNKNOWN; i++) { if (_scancode_to_keycode[i].keysym == p_keycode) { return _scancode_to_keycode[i].keycode; } @@ -355,9 +355,9 @@ unsigned int KeyMappingWindows::get_scancode(Key p_keycode) { return 0; } -unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended) { - unsigned int keycode = KEY_UNKNOWN; - for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) { +Key KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended) { + Key keycode = Key::UNKNOWN; + for (int i = 0; _scancode_to_keycode[i].keysym != Key::UNKNOWN; i++) { if (_scancode_to_keycode[i].keycode == p_code) { keycode = _scancode_to_keycode[i].keysym; break; @@ -366,55 +366,55 @@ unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended if (p_extended) { switch (keycode) { - case KEY_ENTER: { - keycode = KEY_KP_ENTER; + case Key::ENTER: { + keycode = Key::KP_ENTER; } break; - case KEY_SLASH: { - keycode = KEY_KP_DIVIDE; + case Key::SLASH: { + keycode = Key::KP_DIVIDE; } break; - case KEY_CAPSLOCK: { - keycode = KEY_KP_ADD; + case Key::CAPSLOCK: { + keycode = Key::KP_ADD; } break; default: break; } } else { switch (keycode) { - case KEY_NUMLOCK: { - keycode = KEY_PAUSE; + case Key::NUMLOCK: { + keycode = Key::PAUSE; } break; - case KEY_HOME: { - keycode = KEY_KP_7; + case Key::HOME: { + keycode = Key::KP_7; } break; - case KEY_UP: { - keycode = KEY_KP_8; + case Key::UP: { + keycode = Key::KP_8; } break; - case KEY_PAGEUP: { - keycode = KEY_KP_9; + case Key::PAGEUP: { + keycode = Key::KP_9; } break; - case KEY_LEFT: { - keycode = KEY_KP_4; + case Key::LEFT: { + keycode = Key::KP_4; } break; - case KEY_RIGHT: { - keycode = KEY_KP_6; + case Key::RIGHT: { + keycode = Key::KP_6; } break; - case KEY_END: { - keycode = KEY_KP_1; + case Key::END: { + keycode = Key::KP_1; } break; - case KEY_DOWN: { - keycode = KEY_KP_2; + case Key::DOWN: { + keycode = Key::KP_2; } break; - case KEY_PAGEDOWN: { - keycode = KEY_KP_3; + case Key::PAGEDOWN: { + keycode = Key::KP_3; } break; - case KEY_INSERT: { - keycode = KEY_KP_0; + case Key::INSERT: { + keycode = Key::KP_0; } break; - case KEY_DELETE: { - keycode = KEY_KP_PERIOD; + case Key::KEY_DELETE: { + keycode = Key::KP_PERIOD; } break; - case KEY_PRINT: { - keycode = KEY_KP_MULTIPLY; + case Key::PRINT: { + keycode = Key::KP_MULTIPLY; } break; default: break; diff --git a/platform/windows/key_mapping_windows.h b/platform/windows/key_mapping_windows.h index d056e88f06..0454be7310 100644 --- a/platform/windows/key_mapping_windows.h +++ b/platform/windows/key_mapping_windows.h @@ -41,9 +41,9 @@ class KeyMappingWindows { KeyMappingWindows() {} public: - static unsigned int get_keysym(unsigned int p_code); + static Key get_keysym(unsigned int p_code); static unsigned int get_scancode(Key p_keycode); - static unsigned int get_scansym(unsigned int p_code, bool p_extended); + static Key get_scansym(unsigned int p_code, bool p_extended); static bool is_extended_key(unsigned int p_code); }; diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 75a1723e04..8db1491953 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -33,13 +33,13 @@ #include "scene/scene_string_names.h" #include "servers/audio_server.h" -void Area2D::set_space_override_mode(SpaceOverride p_mode) { - space_override = p_mode; - PhysicsServer2D::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer2D::AreaSpaceOverrideMode(p_mode)); +void Area2D::set_gravity_space_override_mode(SpaceOverride p_mode) { + gravity_space_override = p_mode; + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE, p_mode); } -Area2D::SpaceOverride Area2D::get_space_override_mode() const { - return space_override; +Area2D::SpaceOverride Area2D::get_gravity_space_override_mode() const { + return gravity_space_override; } void Area2D::set_gravity_is_point(bool p_enabled) { @@ -51,21 +51,30 @@ bool Area2D::is_gravity_a_point() const { return gravity_is_point; } -void Area2D::set_gravity_distance_scale(real_t p_scale) { +void Area2D::set_gravity_point_distance_scale(real_t p_scale) { gravity_distance_scale = p_scale; PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); } -real_t Area2D::get_gravity_distance_scale() const { +real_t Area2D::get_gravity_point_distance_scale() const { return gravity_distance_scale; } -void Area2D::set_gravity_vector(const Vector2 &p_vec) { - gravity_vec = p_vec; - PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_vec); +void Area2D::set_gravity_point_center(const Vector2 &p_center) { + gravity_vec = p_center; + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_center); } -Vector2 Area2D::get_gravity_vector() const { +const Vector2 &Area2D::get_gravity_point_center() const { + return gravity_vec; +} + +void Area2D::set_gravity_direction(const Vector2 &p_direction) { + gravity_vec = p_direction; + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_direction); +} + +const Vector2 &Area2D::get_gravity_direction() const { return gravity_vec; } @@ -78,6 +87,24 @@ real_t Area2D::get_gravity() const { return gravity; } +void Area2D::set_linear_damp_space_override_mode(SpaceOverride p_mode) { + linear_damp_space_override = p_mode; + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, p_mode); +} + +Area2D::SpaceOverride Area2D::get_linear_damp_space_override_mode() const { + return linear_damp_space_override; +} + +void Area2D::set_angular_damp_space_override_mode(SpaceOverride p_mode) { + angular_damp_space_override = p_mode; + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, p_mode); +} + +Area2D::SpaceOverride Area2D::get_angular_damp_space_override_mode() const { + return angular_damp_space_override; +} + void Area2D::set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, p_linear_damp); @@ -483,25 +510,56 @@ void Area2D::_validate_property(PropertyInfo &property) const { } property.hint_string = options; + } else if (property.name.begins_with("gravity") && property.name != "gravity_space_override") { + if (gravity_space_override == SPACE_OVERRIDE_DISABLED) { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } else { + if (gravity_is_point) { + if (property.name == "gravity_direction") { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } + } else { + if (property.name.begins_with("gravity_point_")) { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } + } + } + } else if (property.name.begins_with("linear_damp") && property.name != "linear_damp_space_override") { + if (linear_damp_space_override == SPACE_OVERRIDE_DISABLED) { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } + } else if (property.name.begins_with("angular_damp") && property.name != "angular_damp_space_override") { + if (angular_damp_space_override == SPACE_OVERRIDE_DISABLED) { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } } } void Area2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_space_override_mode", "space_override_mode"), &Area2D::set_space_override_mode); - ClassDB::bind_method(D_METHOD("get_space_override_mode"), &Area2D::get_space_override_mode); + ClassDB::bind_method(D_METHOD("set_gravity_space_override_mode", "space_override_mode"), &Area2D::set_gravity_space_override_mode); + ClassDB::bind_method(D_METHOD("get_gravity_space_override_mode"), &Area2D::get_gravity_space_override_mode); ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area2D::set_gravity_is_point); ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area2D::is_gravity_a_point); - ClassDB::bind_method(D_METHOD("set_gravity_distance_scale", "distance_scale"), &Area2D::set_gravity_distance_scale); - ClassDB::bind_method(D_METHOD("get_gravity_distance_scale"), &Area2D::get_gravity_distance_scale); + ClassDB::bind_method(D_METHOD("set_gravity_point_distance_scale", "distance_scale"), &Area2D::set_gravity_point_distance_scale); + ClassDB::bind_method(D_METHOD("get_gravity_point_distance_scale"), &Area2D::get_gravity_point_distance_scale); + + ClassDB::bind_method(D_METHOD("set_gravity_point_center", "center"), &Area2D::set_gravity_point_center); + ClassDB::bind_method(D_METHOD("get_gravity_point_center"), &Area2D::get_gravity_point_center); - ClassDB::bind_method(D_METHOD("set_gravity_vector", "vector"), &Area2D::set_gravity_vector); - ClassDB::bind_method(D_METHOD("get_gravity_vector"), &Area2D::get_gravity_vector); + ClassDB::bind_method(D_METHOD("set_gravity_direction", "direction"), &Area2D::set_gravity_direction); + ClassDB::bind_method(D_METHOD("get_gravity_direction"), &Area2D::get_gravity_direction); ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &Area2D::set_gravity); ClassDB::bind_method(D_METHOD("get_gravity"), &Area2D::get_gravity); + ClassDB::bind_method(D_METHOD("set_linear_damp_space_override_mode", "space_override_mode"), &Area2D::set_linear_damp_space_override_mode); + ClassDB::bind_method(D_METHOD("get_linear_damp_space_override_mode"), &Area2D::get_linear_damp_space_override_mode); + + ClassDB::bind_method(D_METHOD("set_angular_damp_space_override_mode", "space_override_mode"), &Area2D::set_angular_damp_space_override_mode); + ClassDB::bind_method(D_METHOD("get_angular_damp_space_override_mode"), &Area2D::get_angular_damp_space_override_mode); + ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &Area2D::set_linear_damp); ClassDB::bind_method(D_METHOD("get_linear_damp"), &Area2D::get_linear_damp); @@ -543,13 +601,20 @@ void Area2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable"); ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority"); - ADD_GROUP("Physics Overrides", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_distance_scale", "get_gravity_distance_scale"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_vec"), "set_gravity_vector", "get_gravity_vector"); + ADD_GROUP("Gravity", "gravity_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_point_distance_scale", "get_gravity_point_distance_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_point_center"), "set_gravity_point_center", "get_gravity_point_center"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_direction"), "set_gravity_direction", "get_gravity_direction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-4096,4096,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity"); + + ADD_GROUP("Linear Damp", "linear_damp_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_linear_damp_space_override_mode", "get_linear_damp_space_override_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); + + ADD_GROUP("Angular Damp", "angular_damp_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_angular_damp_space_override_mode", "get_angular_damp_space_override_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); ADD_GROUP("Audio Bus", "audio_bus_"); @@ -566,7 +631,7 @@ void Area2D::_bind_methods() { Area2D::Area2D() : CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) { set_gravity(980); - set_gravity_vector(Vector2(0, 1)); + set_gravity_direction(Vector2(0, 1)); set_monitoring(true); set_monitorable(true); } diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 2c29e4660d..98ba270a61 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -47,14 +47,19 @@ public: }; private: - SpaceOverride space_override = SPACE_OVERRIDE_DISABLED; + SpaceOverride gravity_space_override = SPACE_OVERRIDE_DISABLED; Vector2 gravity_vec; real_t gravity; bool gravity_is_point = false; real_t gravity_distance_scale = 0.0; + + SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; + SpaceOverride angular_damp_space_override = SPACE_OVERRIDE_DISABLED; real_t linear_damp = 0.1; real_t angular_damp = 1.0; + int priority = 0; + bool monitoring = false; bool monitorable = false; bool locked = false; @@ -133,21 +138,30 @@ protected: void _validate_property(PropertyInfo &property) const override; public: - void set_space_override_mode(SpaceOverride p_mode); - SpaceOverride get_space_override_mode() const; + void set_gravity_space_override_mode(SpaceOverride p_mode); + SpaceOverride get_gravity_space_override_mode() const; void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; - void set_gravity_distance_scale(real_t p_scale); - real_t get_gravity_distance_scale() const; + void set_gravity_point_distance_scale(real_t p_scale); + real_t get_gravity_point_distance_scale() const; - void set_gravity_vector(const Vector2 &p_vec); - Vector2 get_gravity_vector() const; + void set_gravity_point_center(const Vector2 &p_center); + const Vector2 &get_gravity_point_center() const; + + void set_gravity_direction(const Vector2 &p_direction); + const Vector2 &get_gravity_direction() const; void set_gravity(real_t p_gravity); real_t get_gravity() const; + void set_linear_damp_space_override_mode(SpaceOverride p_mode); + SpaceOverride get_linear_damp_space_override_mode() const; + + void set_angular_damp_space_override_mode(SpaceOverride p_mode); + SpaceOverride get_angular_damp_space_override_mode() const; + void set_linear_damp(real_t p_linear_damp); real_t get_linear_damp() const; diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index b4ee85120e..bf5671be19 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -232,6 +232,7 @@ void Camera2D::_notification(int p_what) { } break; case NOTIFICATION_ENTER_TREE: { + ERR_FAIL_COND(!is_inside_tree()); if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) { viewport = custom_viewport; } else { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index a43d498a62..5ec2a81108 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -133,9 +133,12 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_linear ERR_FAIL_COND_V(!is_inside_tree(), false); PhysicsServer2D::MotionResult *r = nullptr; + PhysicsServer2D::MotionResult temp_result; if (r_collision.is_valid()) { // Needs const_cast because method bindings don't support non-const Ref. r = const_cast<PhysicsServer2D::MotionResult *>(&r_collision->result); + } else { + r = &temp_result; } // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky. @@ -143,7 +146,14 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_linear PhysicsServer2D::MotionParameters parameters(p_from, p_linear_velocity * delta, p_margin); - return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r); + bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r); + + if (colliding) { + // Don't report collision when the whole motion is done. + return (r->collision_safe_fraction < 1.0); + } else { + return false; + } } TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() { @@ -1101,6 +1111,10 @@ bool CharacterBody2D::move_and_slide() { if (bs) { Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2]; current_platform_velocity = bs->get_velocity_at_local_position(local_position); + } else { + // Body is removed or destroyed, invalidate floor. + current_platform_velocity = Vector2(); + platform_rid = RID(); } } else { current_platform_velocity = Vector2(); diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 7af91f3a8d..f9830a8743 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -200,6 +200,7 @@ void RayCast2D::_update_raycast_state() { ray_params.collision_mask = collision_mask; ray_params.collide_with_bodies = collide_with_bodies; ray_params.collide_with_areas = collide_with_areas; + ray_params.hit_from_inside = hit_from_inside; if (dss->intersect_ray(ray_params, rr)) { collided = true; @@ -290,22 +291,30 @@ void RayCast2D::clear_exceptions() { exclude.clear(); } -void RayCast2D::set_collide_with_areas(bool p_clip) { - collide_with_areas = p_clip; +void RayCast2D::set_collide_with_areas(bool p_enabled) { + collide_with_areas = p_enabled; } bool RayCast2D::is_collide_with_areas_enabled() const { return collide_with_areas; } -void RayCast2D::set_collide_with_bodies(bool p_clip) { - collide_with_bodies = p_clip; +void RayCast2D::set_collide_with_bodies(bool p_enabled) { + collide_with_bodies = p_enabled; } bool RayCast2D::is_collide_with_bodies_enabled() const { return collide_with_bodies; } +void RayCast2D::set_hit_from_inside(bool p_enabled) { + hit_from_inside = p_enabled; +} + +bool RayCast2D::is_hit_from_inside_enabled() const { + return hit_from_inside; +} + void RayCast2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast2D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast2D::is_enabled); @@ -344,10 +353,14 @@ void RayCast2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast2D::set_collide_with_bodies); ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast2D::is_collide_with_bodies_enabled); + ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &RayCast2D::set_hit_from_inside); + ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &RayCast2D::is_hit_from_inside_enabled); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled"); ADD_GROUP("Collide With", "collide_with"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled"); diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index 65b6e7899b..3ee09fad32 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -51,6 +51,8 @@ class RayCast2D : public Node2D { bool collide_with_areas = false; bool collide_with_bodies = true; + bool hit_from_inside = false; + void _draw_debug_shape(); protected: @@ -65,6 +67,9 @@ public: void set_collide_with_bodies(bool p_clip); bool is_collide_with_bodies_enabled() const; + void set_hit_from_inside(bool p_enable); + bool is_hit_from_inside_enabled() const; + void set_enabled(bool p_enabled); bool is_enabled() const; diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/shape_cast_2d.cpp new file mode 100644 index 0000000000..50b44eb4ef --- /dev/null +++ b/scene/2d/shape_cast_2d.cpp @@ -0,0 +1,459 @@ +/*************************************************************************/ +/* shape_cast_2d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "shape_cast_2d.h" + +#include "core/config/engine.h" +#include "core/core_string_names.h" +#include "scene/2d/collision_object_2d.h" +#include "scene/2d/physics_body_2d.h" +#include "scene/resources/circle_shape_2d.h" +#include "servers/physics_2d/godot_physics_server_2d.h" + +void ShapeCast2D::set_target_position(const Vector2 &p_point) { + target_position = p_point; + if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) { + update(); + } +} + +Vector2 ShapeCast2D::get_target_position() const { + return target_position; +} + +void ShapeCast2D::set_margin(real_t p_margin) { + margin = p_margin; +} + +real_t ShapeCast2D::get_margin() const { + return margin; +} + +void ShapeCast2D::set_max_results(int p_max_results) { + max_results = p_max_results; +} + +int ShapeCast2D::get_max_results() const { + return max_results; +} + +void ShapeCast2D::set_collision_mask(uint32_t p_mask) { + collision_mask = p_mask; +} + +uint32_t ShapeCast2D::get_collision_mask() const { + return collision_mask; +} + +void ShapeCast2D::set_collision_mask_value(int p_layer_number, bool p_value) { + ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive."); + ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive."); + uint32_t mask = get_collision_mask(); + if (p_value) { + mask |= 1 << (p_layer_number - 1); + } else { + mask &= ~(1 << (p_layer_number - 1)); + } + set_collision_mask(mask); +} + +bool ShapeCast2D::get_collision_mask_value(int p_layer_number) const { + ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive."); + ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive."); + return get_collision_mask() & (1 << (p_layer_number - 1)); +} + +int ShapeCast2D::get_collision_count() const { + return result.size(); +} + +bool ShapeCast2D::is_colliding() const { + return collided; +} + +Object *ShapeCast2D::get_collider(int p_idx) const { + ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), nullptr, "No collider found."); + + if (result[p_idx].collider_id.is_null()) { + return nullptr; + } + return ObjectDB::get_instance(result[p_idx].collider_id); +} + +int ShapeCast2D::get_collider_shape(int p_idx) const { + ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), -1, "No collider shape found."); + return result[p_idx].shape; +} + +Vector2 ShapeCast2D::get_collision_point(int p_idx) const { + ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), Vector2(), "No collision point found."); + return result[p_idx].point; +} + +Vector2 ShapeCast2D::get_collision_normal(int p_idx) const { + ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), Vector2(), "No collision normal found."); + return result[p_idx].normal; +} + +real_t ShapeCast2D::get_closest_collision_safe_fraction() const { + return collision_safe_fraction; +} + +real_t ShapeCast2D::get_closest_collision_unsafe_fraction() const { + return collision_unsafe_fraction; +} + +void ShapeCast2D::set_enabled(bool p_enabled) { + enabled = p_enabled; + update(); + if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(p_enabled); + } + if (!p_enabled) { + collided = false; + } +} + +bool ShapeCast2D::is_enabled() const { + return enabled; +} + +void ShapeCast2D::set_shape(const Ref<Shape2D> &p_shape) { + shape = p_shape; + if (p_shape.is_valid()) { + shape->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &ShapeCast2D::_redraw_shape)); + shape_rid = shape->get_rid(); + } + update_configuration_warnings(); + update(); +} + +Ref<Shape2D> ShapeCast2D::get_shape() const { + return shape; +} + +void ShapeCast2D::set_exclude_parent_body(bool p_exclude_parent_body) { + if (exclude_parent_body == p_exclude_parent_body) { + return; + } + exclude_parent_body = p_exclude_parent_body; + + if (!is_inside_tree()) { + return; + } + if (Object::cast_to<CollisionObject2D>(get_parent())) { + if (exclude_parent_body) { + exclude.insert(Object::cast_to<CollisionObject2D>(get_parent())->get_rid()); + } else { + exclude.erase(Object::cast_to<CollisionObject2D>(get_parent())->get_rid()); + } + } +} + +bool ShapeCast2D::get_exclude_parent_body() const { + return exclude_parent_body; +} + +void ShapeCast2D::_redraw_shape() { + update(); +} + +void ShapeCast2D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + if (enabled && !Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(true); + } else { + set_physics_process_internal(false); + } + if (Object::cast_to<CollisionObject2D>(get_parent())) { + if (exclude_parent_body) { + exclude.insert(Object::cast_to<CollisionObject2D>(get_parent())->get_rid()); + } else { + exclude.erase(Object::cast_to<CollisionObject2D>(get_parent())->get_rid()); + } + } + } break; + case NOTIFICATION_EXIT_TREE: { + if (enabled) { + set_physics_process_internal(false); + } + } break; + + case NOTIFICATION_DRAW: { +#ifdef TOOLS_ENABLED + ERR_FAIL_COND(!is_inside_tree()); + if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) { + break; + } + if (shape.is_null()) { + break; + } + Color draw_col = get_tree()->get_debug_collisions_color(); + if (!enabled) { + float g = draw_col.get_v(); + draw_col.r = g; + draw_col.g = g; + draw_col.b = g; + } + // Draw continuos chain of shapes along the cast. + const int steps = MAX(2, target_position.length() / shape->get_rect().get_size().length() * 4); + for (int i = 0; i <= steps; ++i) { + Vector2 t = (real_t(i) / steps) * target_position; + draw_set_transform(t, 0.0, Size2(1, 1)); + shape->draw(get_canvas_item(), draw_col); + } + draw_set_transform(Vector2(), 0.0, Size2(1, 1)); + + // Draw an arrow indicating where the ShapeCast is pointing to. + if (target_position != Vector2()) { + Transform2D xf; + xf.rotate(target_position.angle()); + xf.translate(Vector2(target_position.length(), 0)); + + draw_line(Vector2(), target_position, draw_col, 2); + Vector<Vector2> pts; + float tsize = 8; + pts.push_back(xf.xform(Vector2(tsize, 0))); + pts.push_back(xf.xform(Vector2(0, Math_SQRT12 * tsize))); + pts.push_back(xf.xform(Vector2(0, -Math_SQRT12 * tsize))); + Vector<Color> cols; + for (int i = 0; i < 3; i++) + cols.push_back(draw_col); + + draw_primitive(pts, cols, Vector<Vector2>()); + } +#endif + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (!enabled) { + break; + } + _update_shapecast_state(); + } break; + } +} + +void ShapeCast2D::_update_shapecast_state() { + result.clear(); + + ERR_FAIL_COND_MSG(shape.is_null(), "Invalid shape."); + + Ref<World2D> w2d = get_world_2d(); + ERR_FAIL_COND(w2d.is_null()); + + PhysicsDirectSpaceState2D *dss = PhysicsServer2D::get_singleton()->space_get_direct_state(w2d->get_space()); + ERR_FAIL_COND(!dss); + + Transform2D gt = get_global_transform(); + + PhysicsDirectSpaceState2D::ShapeParameters params; + params.shape_rid = shape_rid; + params.transform = gt; + params.motion = gt.basis_xform(target_position); + params.margin = margin; + params.exclude = exclude; + params.collision_mask = collision_mask; + params.collide_with_bodies = collide_with_bodies; + params.collide_with_areas = collide_with_areas; + + collision_safe_fraction = 0.0; + collision_unsafe_fraction = 0.0; + + if (target_position != Vector2()) { + dss->cast_motion(params, collision_safe_fraction, collision_unsafe_fraction); + if (collision_unsafe_fraction < 1.0) { + // Move shape transform to the point of impact, + // so we can collect contact info at that point. + gt.set_origin(gt.get_origin() + params.motion * (collision_unsafe_fraction + CMP_EPSILON)); + params.transform = gt; + } + } + // Regardless of whether the shape is stuck or it's moved along + // the motion vector, we'll only consider static collisions from now on. + params.motion = Vector2(); + + bool intersected = true; + while (intersected && result.size() < max_results) { + PhysicsDirectSpaceState2D::ShapeRestInfo info; + intersected = dss->rest_info(params, &info); + if (intersected) { + result.push_back(info); + params.exclude.insert(info.rid); + } + } + collided = !result.is_empty(); +} + +void ShapeCast2D::force_shapecast_update() { + _update_shapecast_state(); +} + +void ShapeCast2D::add_exception_rid(const RID &p_rid) { + exclude.insert(p_rid); +} + +void ShapeCast2D::add_exception(const Object *p_object) { + ERR_FAIL_NULL(p_object); + const CollisionObject2D *co = Object::cast_to<CollisionObject2D>(p_object); + if (!co) { + return; + } + add_exception_rid(co->get_rid()); +} + +void ShapeCast2D::remove_exception_rid(const RID &p_rid) { + exclude.erase(p_rid); +} + +void ShapeCast2D::remove_exception(const Object *p_object) { + ERR_FAIL_NULL(p_object); + const CollisionObject2D *co = Object::cast_to<CollisionObject2D>(p_object); + if (!co) { + return; + } + remove_exception_rid(co->get_rid()); +} + +void ShapeCast2D::clear_exceptions() { + exclude.clear(); +} + +void ShapeCast2D::set_collide_with_areas(bool p_clip) { + collide_with_areas = p_clip; +} + +bool ShapeCast2D::is_collide_with_areas_enabled() const { + return collide_with_areas; +} + +void ShapeCast2D::set_collide_with_bodies(bool p_clip) { + collide_with_bodies = p_clip; +} + +bool ShapeCast2D::is_collide_with_bodies_enabled() const { + return collide_with_bodies; +} + +Array ShapeCast2D::_get_collision_result() const { + Array ret; + + for (int i = 0; i < result.size(); ++i) { + const PhysicsDirectSpaceState2D::ShapeRestInfo &sri = result[i]; + + Dictionary col; + col["point"] = sri.point; + col["normal"] = sri.normal; + col["rid"] = sri.rid; + col["collider"] = ObjectDB::get_instance(sri.collider_id); + col["collider_id"] = sri.collider_id; + col["shape"] = sri.shape; + col["linear_velocity"] = sri.linear_velocity; + + ret.push_back(col); + } + return ret; +} + +TypedArray<String> ShapeCast2D::get_configuration_warnings() const { + TypedArray<String> warnings = Node2D::get_configuration_warnings(); + + if (shape.is_null()) { + warnings.push_back(TTR("This node cannot interact with other objects unless a Shape2D is assigned.")); + } + return warnings; +} + +void ShapeCast2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &ShapeCast2D::set_enabled); + ClassDB::bind_method(D_METHOD("is_enabled"), &ShapeCast2D::is_enabled); + + ClassDB::bind_method(D_METHOD("set_shape", "shape"), &ShapeCast2D::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &ShapeCast2D::get_shape); + + ClassDB::bind_method(D_METHOD("set_target_position", "local_point"), &ShapeCast2D::set_target_position); + ClassDB::bind_method(D_METHOD("get_target_position"), &ShapeCast2D::get_target_position); + + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &ShapeCast2D::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"), &ShapeCast2D::get_margin); + + ClassDB::bind_method(D_METHOD("set_max_results", "max_results"), &ShapeCast2D::set_max_results); + ClassDB::bind_method(D_METHOD("get_max_results"), &ShapeCast2D::get_max_results); + + ClassDB::bind_method(D_METHOD("is_colliding"), &ShapeCast2D::is_colliding); + ClassDB::bind_method(D_METHOD("get_collision_count"), &ShapeCast2D::get_collision_count); + + ClassDB::bind_method(D_METHOD("force_shapecast_update"), &ShapeCast2D::force_shapecast_update); + + ClassDB::bind_method(D_METHOD("get_collider", "index"), &ShapeCast2D::get_collider); + ClassDB::bind_method(D_METHOD("get_collider_shape", "index"), &ShapeCast2D::get_collider_shape); + ClassDB::bind_method(D_METHOD("get_collision_point", "index"), &ShapeCast2D::get_collision_point); + ClassDB::bind_method(D_METHOD("get_collision_normal", "index"), &ShapeCast2D::get_collision_normal); + + ClassDB::bind_method(D_METHOD("get_closest_collision_safe_fraction"), &ShapeCast2D::get_closest_collision_safe_fraction); + ClassDB::bind_method(D_METHOD("get_closest_collision_unsafe_fraction"), &ShapeCast2D::get_closest_collision_unsafe_fraction); + + ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &ShapeCast2D::add_exception_rid); + ClassDB::bind_method(D_METHOD("add_exception", "node"), &ShapeCast2D::add_exception); + + ClassDB::bind_method(D_METHOD("remove_exception_rid", "rid"), &ShapeCast2D::remove_exception_rid); + ClassDB::bind_method(D_METHOD("remove_exception", "node"), &ShapeCast2D::remove_exception); + + ClassDB::bind_method(D_METHOD("clear_exceptions"), &ShapeCast2D::clear_exceptions); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &ShapeCast2D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &ShapeCast2D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_value", "layer_number", "value"), &ShapeCast2D::set_collision_mask_value); + ClassDB::bind_method(D_METHOD("get_collision_mask_value", "layer_number"), &ShapeCast2D::get_collision_mask_value); + + ClassDB::bind_method(D_METHOD("set_exclude_parent_body", "mask"), &ShapeCast2D::set_exclude_parent_body); + ClassDB::bind_method(D_METHOD("get_exclude_parent_body"), &ShapeCast2D::get_exclude_parent_body); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &ShapeCast2D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &ShapeCast2D::is_collide_with_areas_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &ShapeCast2D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &ShapeCast2D::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("_get_collision_result"), &ShapeCast2D::_get_collision_result); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_results"), "set_max_results", "get_max_results"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "_get_collision_result"); + ADD_GROUP("Collide With", "collide_with"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); +} diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/shape_cast_2d.h new file mode 100644 index 0000000000..fca6b46155 --- /dev/null +++ b/scene/2d/shape_cast_2d.h @@ -0,0 +1,120 @@ +/*************************************************************************/ +/* shape_cast_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SHAPE_CAST_2D +#define SHAPE_CAST_2D + +#include "scene/2d/node_2d.h" +#include "scene/resources/shape_2d.h" + +class ShapeCast2D : public Node2D { + GDCLASS(ShapeCast2D, Node2D); + + bool enabled = true; + + Ref<Shape2D> shape; + RID shape_rid; + Vector2 target_position = Vector2(0, 50); + + Set<RID> exclude; + real_t margin = 0.0; + uint32_t collision_mask = 1; + bool exclude_parent_body = true; + bool collide_with_areas = false; + bool collide_with_bodies = true; + + // Result + int max_results = 32; + Vector<PhysicsDirectSpaceState2D::ShapeRestInfo> result; + bool collided = false; + real_t collision_safe_fraction = 1.0; + real_t collision_unsafe_fraction = 1.0; + + Array _get_collision_result() const; + void _redraw_shape(); + +protected: + void _notification(int p_what); + void _update_shapecast_state(); + static void _bind_methods(); + +public: + void set_collide_with_areas(bool p_clip); + bool is_collide_with_areas_enabled() const; + + void set_collide_with_bodies(bool p_clip); + bool is_collide_with_bodies_enabled() const; + + void set_enabled(bool p_enabled); + bool is_enabled() const; + + void set_shape(const Ref<Shape2D> &p_shape); + Ref<Shape2D> get_shape() const; + + void set_target_position(const Vector2 &p_point); + Vector2 get_target_position() const; + + void set_margin(real_t p_margin); + real_t get_margin() const; + + void set_max_results(int p_max_results); + int get_max_results() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_mask_value(int p_layer_number, bool p_value); + bool get_collision_mask_value(int p_layer_number) const; + + void set_exclude_parent_body(bool p_exclude_parent_body); + bool get_exclude_parent_body() const; + + void force_shapecast_update(); + bool is_colliding() const; + + int get_collision_count() const; + Object *get_collider(int p_idx) const; + int get_collider_shape(int p_idx) const; + Vector2 get_collision_point(int p_idx) const; + Vector2 get_collision_normal(int p_idx) const; + + real_t get_closest_collision_safe_fraction() const; + real_t get_closest_collision_unsafe_fraction() const; + + void add_exception_rid(const RID &p_rid); + void add_exception(const Object *p_object); + void remove_exception_rid(const RID &p_rid); + void remove_exception(const Object *p_object); + void clear_exceptions(); + + TypedArray<String> get_configuration_warnings() const override; +}; + +#endif diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 8af7637ffd..96c4164721 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -1259,7 +1259,7 @@ void TileMap::_rendering_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { Vector2i grid_size = atlas_source->get_atlas_grid_size(); - if (!atlas_source->get_texture().is_valid() || c.get_atlas_coords().x >= grid_size.x || c.get_atlas_coords().y >= grid_size.y) { + if (!atlas_source->get_runtime_texture().is_valid() || c.get_atlas_coords().x >= grid_size.x || c.get_atlas_coords().y >= grid_size.y) { // Generate a random color from the hashed values of the tiles. Array to_hash; to_hash.push_back(c.source_id); @@ -1299,7 +1299,7 @@ void TileMap::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSe } // Get the texture. - Ref<Texture2D> tex = atlas_source->get_texture(); + Ref<Texture2D> tex = atlas_source->get_runtime_texture(); if (!tex.is_valid()) { return; } @@ -1321,7 +1321,7 @@ void TileMap::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSe // Get destination rect. Rect2 dest_rect; - dest_rect.size = atlas_source->get_tile_texture_region(p_atlas_coords).size; + dest_rect.size = atlas_source->get_runtime_tile_texture_region(p_atlas_coords).size; dest_rect.size.x += FP_ADJUST; dest_rect.size.y += FP_ADJUST; @@ -1342,10 +1342,10 @@ void TileMap::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSe // Draw the tile. if (p_frame >= 0) { - Rect2i source_rect = atlas_source->get_tile_texture_region(p_atlas_coords, p_frame); + Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, p_frame); tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping()); } else if (atlas_source->get_tile_animation_frames_count(p_atlas_coords) == 1) { - Rect2i source_rect = atlas_source->get_tile_texture_region(p_atlas_coords, 0); + Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, 0); tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping()); } else { real_t speed = atlas_source->get_tile_animation_speed(p_atlas_coords); @@ -1355,7 +1355,7 @@ void TileMap::draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSe real_t frame_duration = atlas_source->get_tile_animation_frame_duration(p_atlas_coords, frame) / speed; RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, animation_duration, time, time + frame_duration, 0.0); - Rect2i source_rect = atlas_source->get_tile_texture_region(p_atlas_coords, frame); + Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, frame); tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping()); time += frame_duration; diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index e459c42e8c..073543638f 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -33,13 +33,13 @@ #include "scene/scene_string_names.h" #include "servers/audio_server.h" -void Area3D::set_space_override_mode(SpaceOverride p_mode) { - space_override = p_mode; - PhysicsServer3D::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer3D::AreaSpaceOverrideMode(p_mode)); +void Area3D::set_gravity_space_override_mode(SpaceOverride p_mode) { + gravity_space_override = p_mode; + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE, p_mode); } -Area3D::SpaceOverride Area3D::get_space_override_mode() const { - return space_override; +Area3D::SpaceOverride Area3D::get_gravity_space_override_mode() const { + return gravity_space_override; } void Area3D::set_gravity_is_point(bool p_enabled) { @@ -51,21 +51,30 @@ bool Area3D::is_gravity_a_point() const { return gravity_is_point; } -void Area3D::set_gravity_distance_scale(real_t p_scale) { +void Area3D::set_gravity_point_distance_scale(real_t p_scale) { gravity_distance_scale = p_scale; PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); } -real_t Area3D::get_gravity_distance_scale() const { +real_t Area3D::get_gravity_point_distance_scale() const { return gravity_distance_scale; } -void Area3D::set_gravity_vector(const Vector3 &p_vec) { - gravity_vec = p_vec; - PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, p_vec); +void Area3D::set_gravity_point_center(const Vector3 &p_center) { + gravity_vec = p_center; + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, p_center); } -Vector3 Area3D::get_gravity_vector() const { +const Vector3 &Area3D::get_gravity_point_center() const { + return gravity_vec; +} + +void Area3D::set_gravity_direction(const Vector3 &p_direction) { + gravity_vec = p_direction; + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, p_direction); +} + +const Vector3 &Area3D::get_gravity_direction() const { return gravity_vec; } @@ -78,6 +87,24 @@ real_t Area3D::get_gravity() const { return gravity; } +void Area3D::set_linear_damp_space_override_mode(SpaceOverride p_mode) { + linear_damp_space_override = p_mode; + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, p_mode); +} + +Area3D::SpaceOverride Area3D::get_linear_damp_space_override_mode() const { + return linear_damp_space_override; +} + +void Area3D::set_angular_damp_space_override_mode(SpaceOverride p_mode) { + angular_damp_space_override = p_mode; + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, p_mode); +} + +Area3D::SpaceOverride Area3D::get_angular_damp_space_override_mode() const { + return angular_damp_space_override; +} + void Area3D::set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, p_linear_damp); @@ -579,27 +606,58 @@ void Area3D::_validate_property(PropertyInfo &property) const { } property.hint_string = options; + } else if (property.name.begins_with("gravity") && property.name != "gravity_space_override") { + if (gravity_space_override == SPACE_OVERRIDE_DISABLED) { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } else { + if (gravity_is_point) { + if (property.name == "gravity_direction") { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } + } else { + if (property.name.begins_with("gravity_point_")) { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } + } + } + } else if (property.name.begins_with("linear_damp") && property.name != "linear_damp_space_override") { + if (linear_damp_space_override == SPACE_OVERRIDE_DISABLED) { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } + } else if (property.name.begins_with("angular_damp") && property.name != "angular_damp_space_override") { + if (angular_damp_space_override == SPACE_OVERRIDE_DISABLED) { + property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + } } CollisionObject3D::_validate_property(property); } void Area3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_space_override_mode", "enable"), &Area3D::set_space_override_mode); - ClassDB::bind_method(D_METHOD("get_space_override_mode"), &Area3D::get_space_override_mode); + ClassDB::bind_method(D_METHOD("set_gravity_space_override_mode", "space_override_mode"), &Area3D::set_gravity_space_override_mode); + ClassDB::bind_method(D_METHOD("get_gravity_space_override_mode"), &Area3D::get_gravity_space_override_mode); ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area3D::set_gravity_is_point); ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area3D::is_gravity_a_point); - ClassDB::bind_method(D_METHOD("set_gravity_distance_scale", "distance_scale"), &Area3D::set_gravity_distance_scale); - ClassDB::bind_method(D_METHOD("get_gravity_distance_scale"), &Area3D::get_gravity_distance_scale); + ClassDB::bind_method(D_METHOD("set_gravity_point_distance_scale", "distance_scale"), &Area3D::set_gravity_point_distance_scale); + ClassDB::bind_method(D_METHOD("get_gravity_point_distance_scale"), &Area3D::get_gravity_point_distance_scale); - ClassDB::bind_method(D_METHOD("set_gravity_vector", "vector"), &Area3D::set_gravity_vector); - ClassDB::bind_method(D_METHOD("get_gravity_vector"), &Area3D::get_gravity_vector); + ClassDB::bind_method(D_METHOD("set_gravity_point_center", "center"), &Area3D::set_gravity_point_center); + ClassDB::bind_method(D_METHOD("get_gravity_point_center"), &Area3D::get_gravity_point_center); + + ClassDB::bind_method(D_METHOD("set_gravity_direction", "direction"), &Area3D::set_gravity_direction); + ClassDB::bind_method(D_METHOD("get_gravity_direction"), &Area3D::get_gravity_direction); ClassDB::bind_method(D_METHOD("set_gravity", "gravity"), &Area3D::set_gravity); ClassDB::bind_method(D_METHOD("get_gravity"), &Area3D::get_gravity); + ClassDB::bind_method(D_METHOD("set_linear_damp_space_override_mode", "space_override_mode"), &Area3D::set_linear_damp_space_override_mode); + ClassDB::bind_method(D_METHOD("get_linear_damp_space_override_mode"), &Area3D::get_linear_damp_space_override_mode); + + ClassDB::bind_method(D_METHOD("set_angular_damp_space_override_mode", "space_override_mode"), &Area3D::set_angular_damp_space_override_mode); + ClassDB::bind_method(D_METHOD("get_angular_damp_space_override_mode"), &Area3D::get_angular_damp_space_override_mode); + ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &Area3D::set_angular_damp); ClassDB::bind_method(D_METHOD("get_angular_damp"), &Area3D::get_angular_damp); @@ -662,14 +720,23 @@ void Area3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable"); ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority"); - ADD_GROUP("Physics Overrides", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine"), "set_space_override_mode", "get_space_override_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point"), "set_gravity_is_point", "is_gravity_a_point"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_distance_scale", "get_gravity_distance_scale"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector"); + ADD_GROUP("Gravity", "gravity_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_point_distance_scale", "get_gravity_point_distance_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_point_center"), "set_gravity_point_center", "get_gravity_point_center"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_direction"), "set_gravity_direction", "get_gravity_direction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-32,32,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity"); + + ADD_GROUP("Linear Damp", "linear_damp_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_linear_damp_space_override_mode", "get_linear_damp_space_override_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); + + ADD_GROUP("Angular Damp", "angular_damp_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_angular_damp_space_override_mode", "get_angular_damp_space_override_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); + + ADD_GROUP("Wind", "wind_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wind_force_magnitude", PROPERTY_HINT_RANGE, "0,10,0.001,or_greater"), "set_wind_force_magnitude", "get_wind_force_magnitude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wind_attenuation_factor", PROPERTY_HINT_RANGE, "0.0,3.0,0.001,or_greater"), "set_wind_attenuation_factor", "get_wind_attenuation_factor"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "wind_source_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_wind_source_path", "get_wind_source_path"); @@ -694,7 +761,7 @@ void Area3D::_bind_methods() { Area3D::Area3D() : CollisionObject3D(PhysicsServer3D::get_singleton()->area_create(), true) { set_gravity(9.8); - set_gravity_vector(Vector3(0, -1, 0)); + set_gravity_direction(Vector3(0, -1, 0)); set_monitoring(true); set_monitorable(true); } diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h index 847d1c5966..7f31be2e17 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -47,17 +47,23 @@ public: }; private: - SpaceOverride space_override = SPACE_OVERRIDE_DISABLED; + SpaceOverride gravity_space_override = SPACE_OVERRIDE_DISABLED; Vector3 gravity_vec; real_t gravity; bool gravity_is_point = false; real_t gravity_distance_scale = 0.0; + + SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; + SpaceOverride angular_damp_space_override = SPACE_OVERRIDE_DISABLED; real_t angular_damp = 0.1; real_t linear_damp = 0.1; + int priority = 0; + real_t wind_force_magnitude = 0.0; real_t wind_attenuation_factor = 0.0; NodePath wind_source_path; + bool monitoring = false; bool monitorable = false; bool locked = false; @@ -144,21 +150,30 @@ protected: static void _bind_methods(); public: - void set_space_override_mode(SpaceOverride p_mode); - SpaceOverride get_space_override_mode() const; + void set_gravity_space_override_mode(SpaceOverride p_mode); + SpaceOverride get_gravity_space_override_mode() const; void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; - void set_gravity_distance_scale(real_t p_scale); - real_t get_gravity_distance_scale() const; + void set_gravity_point_distance_scale(real_t p_scale); + real_t get_gravity_point_distance_scale() const; - void set_gravity_vector(const Vector3 &p_vec); - Vector3 get_gravity_vector() const; + void set_gravity_point_center(const Vector3 &p_center); + const Vector3 &get_gravity_point_center() const; + + void set_gravity_direction(const Vector3 &p_direction); + const Vector3 &get_gravity_direction() const; void set_gravity(real_t p_gravity); real_t get_gravity() const; + void set_linear_damp_space_override_mode(SpaceOverride p_mode); + SpaceOverride get_linear_damp_space_override_mode() const; + + void set_angular_damp_space_override_mode(SpaceOverride p_mode); + SpaceOverride get_angular_damp_space_override_mode() const; + void set_angular_damp(real_t p_angular_damp); real_t get_angular_damp() const; diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp index 6ac9364b1a..2235de1599 100644 --- a/scene/3d/gpu_particles_collision_3d.cpp +++ b/scene/3d/gpu_particles_collision_3d.cpp @@ -256,10 +256,10 @@ void GPUParticlesCollisionSDF::_find_closest_distance(const Vector3 &p_pos, cons Vector2 pq1 = v1 - e1 * CLAMP(v1.dot(e1) / e1.dot(e1), 0.0, 1.0); Vector2 pq2 = v2 - e2 * CLAMP(v2.dot(e2) / e2.dot(e2), 0.0, 1.0); - float s = SGN(e0.x * e2.y - e0.y * e2.x); + float s = SIGN(e0.x * e2.y - e0.y * e2.x); Vector2 d2 = Vector2(pq0.dot(pq0), s * (v0.x * e0.y - v0.y * e0.x)).min(Vector2(pq1.dot(pq1), s * (v1.x * e1.y - v1.y * e1.x))).min(Vector2(pq2.dot(pq2), s * (v2.x * e2.y - v2.y * e2.x))); - inside_d = -Math::sqrt(d2.x) * SGN(d2.y); + inside_d = -Math::sqrt(d2.x) * SIGN(d2.y); } //make sure distance to planes is not shorter if inside @@ -288,7 +288,7 @@ void GPUParticlesCollisionSDF::_find_closest_distance(const Vector3 &p_pos, cons Vector3 nor = ba.cross(ac); inside_d = Math::sqrt( - (SGN(ba.cross(nor).dot(pa)) + SGN(cb.cross(nor).dot(pb)) + SGN(ac.cross(nor).dot(pc)) < 2.0) + (SIGN(ba.cross(nor).dot(pa)) + SIGN(cb.cross(nor).dot(pb)) + SIGN(ac.cross(nor).dot(pc)) < 2.0) ? MIN(MIN( Vector3_dot2(ba * CLAMP(ba.dot(pa) / Vector3_dot2(ba), 0.0, 1.0) - pa), Vector3_dot2(cb * CLAMP(cb.dot(pb) / Vector3_dot2(cb), 0.0, 1.0) - pb)), diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index d0506227b4..5cb7f431e3 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -174,9 +174,12 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_linear ERR_FAIL_COND_V(!is_inside_tree(), false); PhysicsServer3D::MotionResult *r = nullptr; + PhysicsServer3D::MotionResult temp_result; if (r_collision.is_valid()) { // Needs const_cast because method bindings don't support non-const Ref. r = const_cast<PhysicsServer3D::MotionResult *>(&r_collision->result); + } else { + r = &temp_result; } // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky @@ -184,7 +187,14 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_linear PhysicsServer3D::MotionParameters parameters(p_from, p_linear_velocity * delta, p_margin); - return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r); + bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r); + + if (colliding) { + // Don't report collision when the whole motion is done. + return (r->collision_safe_fraction < 1.0); + } else { + return false; + } } void PhysicsBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) { @@ -1145,6 +1155,10 @@ bool CharacterBody3D::move_and_slide() { if (bs) { Vector3 local_position = gt.origin - bs->get_transform().origin; current_platform_velocity = bs->get_velocity_at_local_position(local_position); + } else { + // Body is removed or destroyed, invalidate floor. + current_platform_velocity = Vector3(); + platform_rid = RID(); } } else { current_platform_velocity = Vector3(); diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index 646f659996..bfa397a1f5 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -219,6 +219,7 @@ void RayCast3D::_update_raycast_state() { ray_params.collision_mask = collision_mask; ray_params.collide_with_bodies = collide_with_bodies; ray_params.collide_with_areas = collide_with_areas; + ray_params.hit_from_inside = hit_from_inside; PhysicsDirectSpaceState3D::RayResult rr; if (dss->intersect_ray(ray_params, rr)) { @@ -268,22 +269,30 @@ void RayCast3D::clear_exceptions() { exclude.clear(); } -void RayCast3D::set_collide_with_areas(bool p_clip) { - collide_with_areas = p_clip; +void RayCast3D::set_collide_with_areas(bool p_enabled) { + collide_with_areas = p_enabled; } bool RayCast3D::is_collide_with_areas_enabled() const { return collide_with_areas; } -void RayCast3D::set_collide_with_bodies(bool p_clip) { - collide_with_bodies = p_clip; +void RayCast3D::set_collide_with_bodies(bool p_enabled) { + collide_with_bodies = p_enabled; } bool RayCast3D::is_collide_with_bodies_enabled() const { return collide_with_bodies; } +void RayCast3D::set_hit_from_inside(bool p_enabled) { + hit_from_inside = p_enabled; +} + +bool RayCast3D::is_hit_from_inside_enabled() const { + return hit_from_inside; +} + void RayCast3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast3D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast3D::is_enabled); @@ -322,6 +331,9 @@ void RayCast3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast3D::set_collide_with_bodies); ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast3D::is_collide_with_bodies_enabled); + ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &RayCast3D::set_hit_from_inside); + ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &RayCast3D::is_hit_from_inside_enabled); + ClassDB::bind_method(D_METHOD("set_debug_shape_custom_color", "debug_shape_custom_color"), &RayCast3D::set_debug_shape_custom_color); ClassDB::bind_method(D_METHOD("get_debug_shape_custom_color"), &RayCast3D::get_debug_shape_custom_color); @@ -332,6 +344,7 @@ void RayCast3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled"); ADD_GROUP("Collide With", "collide_with"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled"); diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h index 3828bfb4c4..5c2a61c35b 100644 --- a/scene/3d/ray_cast_3d.h +++ b/scene/3d/ray_cast_3d.h @@ -65,18 +65,23 @@ class RayCast3D : public Node3D { bool collide_with_areas = false; bool collide_with_bodies = true; + bool hit_from_inside = false; + protected: void _notification(int p_what); void _update_raycast_state(); static void _bind_methods(); public: - void set_collide_with_areas(bool p_clip); + void set_collide_with_areas(bool p_enabled); bool is_collide_with_areas_enabled() const; - void set_collide_with_bodies(bool p_clip); + void set_collide_with_bodies(bool p_enabled); bool is_collide_with_bodies_enabled() const; + void set_hit_from_inside(bool p_enabled); + bool is_hit_from_inside_enabled() const; + void set_enabled(bool p_enabled); bool is_enabled() const; diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 40d4d822c9..f7f19596a7 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -94,7 +94,7 @@ void ReflectionProbe::set_extents(const Vector3 &p_extents) { } if (extents[i] - 0.01 < ABS(origin_offset[i])) { - origin_offset[i] = SGN(origin_offset[i]) * (extents[i] - 0.01); + origin_offset[i] = SIGN(origin_offset[i]) * (extents[i] - 0.01); } } @@ -113,7 +113,7 @@ void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) { for (int i = 0; i < 3; i++) { if (extents[i] - 0.01 < ABS(origin_offset[i])) { - origin_offset[i] = SGN(origin_offset[i]) * (extents[i] - 0.01); + origin_offset[i] = SIGN(origin_offset[i]) * (extents[i] - 0.01); } } RS::get_singleton()->reflection_probe_set_extents(probe, extents); diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index b91a2869e4..e621f06ce9 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -30,6 +30,7 @@ #include "animation_blend_space_2d.h" +#include "animation_blend_tree.h" #include "core/math/geometry_2d.h" void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const { @@ -531,6 +532,12 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek) { if (new_closest != closest && new_closest != -1) { float from = 0.0; if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) { + //for ping-pong loop + Ref<AnimationNodeAnimation> na_c = static_cast<Ref<AnimationNodeAnimation>>(blend_points[closest].node); + Ref<AnimationNodeAnimation> na_n = static_cast<Ref<AnimationNodeAnimation>>(blend_points[new_closest].node); + if (!na_c.is_null() && !na_n.is_null()) { + na_n->set_backward(na_c->is_backward()); + } //see how much animation remains from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, 0.0, FILTER_IGNORE, false); } diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index d18e1a92d8..d6c5d0b51c 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -30,6 +30,7 @@ #include "animation_blend_tree.h" +#include "scene/resources/animation.h" #include "scene/scene_string_names.h" void AnimationNodeAnimation::set_animation(const StringName &p_name) { @@ -83,30 +84,55 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek) { } Ref<Animation> anim = ap->get_animation(animation); - - double step; + double anim_size = (double)anim->get_length(); + double step = 0.0; + double prev_time = time; + int pingponged = 0; + bool current_backward = signbit(p_time); if (p_seek) { + step = p_time - time; time = p_time; - step = 0; } else { - time = MAX(0, time + p_time); - step = p_time; + p_time *= backward ? -1.0 : 1.0; + if (!(time == anim_size && !current_backward) && !(time == 0 && current_backward)) { + time = time + p_time; + step = p_time; + } } - double anim_size = anim->get_length(); - - if (anim->has_loop()) { + if (anim->get_loop_mode() == Animation::LoopMode::LOOP_PINGPONG) { if (anim_size) { - time = Math::fposmod(time, anim_size); + if ((int)Math::floor(abs(time - prev_time) / anim_size) % 2 == 0) { + if (prev_time > 0 && time <= 0) { + backward = !backward; + pingponged = -1; + } + if (prev_time < anim_size && time >= anim_size) { + backward = !backward; + pingponged = 1; + } + } + time = Math::pingpong(time, anim_size); } - - } else if (time > anim_size) { - time = anim_size; + } else { + if (anim->get_loop_mode() == Animation::LoopMode::LOOP_LINEAR) { + if (anim_size) { + time = Math::fposmod(time, anim_size); + } + } else if (time < 0) { + time = 0; + } else if (time > anim_size) { + time = anim_size; + } + backward = false; } - blend_animation(animation, time, step, p_seek, 1.0); - + if (play_mode == PLAY_MODE_FORWARD) { + blend_animation(animation, time, step, p_seek, 1.0, pingponged); + } else { + blend_animation(animation, anim_size - time, -step, p_seek, 1.0, pingponged); + } set_parameter(this->time, time); return anim_size - time; @@ -116,11 +142,34 @@ String AnimationNodeAnimation::get_caption() const { return "Animation"; } +void AnimationNodeAnimation::set_play_mode(PlayMode p_play_mode) { + play_mode = p_play_mode; +} + +AnimationNodeAnimation::PlayMode AnimationNodeAnimation::get_play_mode() const { + return play_mode; +} + +void AnimationNodeAnimation::set_backward(bool p_backward) { + backward = p_backward; +} + +bool AnimationNodeAnimation::is_backward() const { + return backward; +} + void AnimationNodeAnimation::_bind_methods() { ClassDB::bind_method(D_METHOD("set_animation", "name"), &AnimationNodeAnimation::set_animation); ClassDB::bind_method(D_METHOD("get_animation"), &AnimationNodeAnimation::get_animation); + ClassDB::bind_method(D_METHOD("set_play_mode", "mode"), &AnimationNodeAnimation::set_play_mode); + ClassDB::bind_method(D_METHOD("get_play_mode"), &AnimationNodeAnimation::get_play_mode); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "play_mode", PROPERTY_HINT_ENUM, "Forward,Backward"), "set_play_mode", "get_play_mode"); + + BIND_ENUM_CONSTANT(PLAY_MODE_FORWARD); + BIND_ENUM_CONSTANT(PLAY_MODE_BACKWARD); } AnimationNodeAnimation::AnimationNodeAnimation() { @@ -533,7 +582,7 @@ AnimationNodeBlend3::AnimationNodeBlend3() { ///////////////////////////////// void AnimationNodeTimeScale::get_parameter_list(List<PropertyInfo> *r_list) const { - r_list->push_back(PropertyInfo(Variant::FLOAT, scale, PROPERTY_HINT_RANGE, "0,32,0.01,or_greater")); + r_list->push_back(PropertyInfo(Variant::FLOAT, scale, PROPERTY_HINT_RANGE, "-32,32,0.01,or_lesser,or_greater")); } Variant AnimationNodeTimeScale::get_parameter_default_value(const StringName &p_parameter) const { diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 258443a999..e55dfb58ed 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -42,12 +42,12 @@ class AnimationNodeAnimation : public AnimationRootNode { uint64_t last_version = 0; bool skip = false; -protected: - void _validate_property(PropertyInfo &property) const override; - - static void _bind_methods(); - public: + enum PlayMode { + PLAY_MODE_FORWARD, + PLAY_MODE_BACKWARD + }; + void get_parameter_list(List<PropertyInfo> *r_list) const override; static Vector<String> (*get_editable_animation_list)(); @@ -58,9 +58,25 @@ public: void set_animation(const StringName &p_name); StringName get_animation() const; + void set_play_mode(PlayMode p_play_mode); + PlayMode get_play_mode() const; + + void set_backward(bool p_backward); + bool is_backward() const; + AnimationNodeAnimation(); + +protected: + void _validate_property(PropertyInfo &property) const override; + static void _bind_methods(); + +private: + PlayMode play_mode = PLAY_MODE_FORWARD; + bool backward = false; }; +VARIANT_ENUM_CAST(AnimationNodeAnimation::PlayMode) + class AnimationNodeOneShot : public AnimationNode { GDCLASS(AnimationNodeOneShot, AnimationNode); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index f91422ac1a..93339711bd 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -398,12 +398,13 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov } } -void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started) { +void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) { _ensure_node_caches(p_anim); ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); Animation *a = p_anim->animation.operator->(); bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint(); + bool backward = signbit(p_delta); for (int i = 0; i < a->get_track_count(); i++) { // If an animation changes this animation (or it animates itself) @@ -557,8 +558,8 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double continue; //eeh not worth it } - float first_key_time = a->track_get_key_time(i, 0); - float transition = 1.0; + double first_key_time = a->track_get_key_time(i, 0); + double transition = 1.0; int first_key = 0; if (first_key_time == 0.0) { @@ -566,13 +567,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (key_count == 1) { continue; //with one key we can't do anything } - transition = a->track_get_key_transition(i, 0); + transition = (double)a->track_get_key_transition(i, 0); first_key_time = a->track_get_key_time(i, 1); first_key = 1; } if (p_time < first_key_time) { - float c = Math::ease(p_time / first_key_time, transition); + double c = Math::ease(p_time / first_key_time, transition); Variant first_value = a->track_get_key_value(i, first_key); Variant interp_value; Variant::interpolate(pa->capture, first_value, c, interp_value); @@ -614,7 +615,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double } else if (p_is_current && p_delta != 0) { List<int> indices; - a->value_track_get_key_indices(i, p_time, p_delta, &indices); + a->value_track_get_key_indices(i, p_time, p_delta, &indices, p_pingponged); for (int &F : indices) { Variant value = a->track_get_key_value(i, F); @@ -673,7 +674,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double List<int> indices; - a->method_track_get_key_indices(i, p_time, p_delta, &indices); + a->method_track_get_key_indices(i, p_time, p_delta, &indices, p_pingponged); for (int &E : indices) { StringName method = a->method_track_get_name(i, E); @@ -728,7 +729,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double TrackNodeCache::BezierAnim *ba = &E->get(); - float bezier = a->bezier_track_interpolate(i, p_time); + real_t bezier = a->bezier_track_interpolate(i, p_time); if (ba->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_bezier_size >= NODE_CACHE_UPDATE_MAX); cache_update_bezier[cache_update_bezier_size++] = ba; @@ -789,7 +790,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double } else { //find stuff to play List<int> to_play; - a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play); + a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged); if (to_play.size()) { int idx = to_play.back()->get(); @@ -817,12 +818,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double nc->audio_start = p_time; } } else if (nc->audio_playing) { - bool loop = a->has_loop(); + bool loop = a->get_loop_mode() != Animation::LoopMode::LOOP_NONE; bool stop = false; - if (!loop && p_time < nc->audio_start) { - stop = true; + if (!loop) { + if ((p_time < nc->audio_start && !backward) || (p_time > nc->audio_start && backward)) { + stop = true; + } } else if (nc->audio_len > 0) { float len = nc->audio_start > p_time ? (a->get_length() - nc->audio_start) + p_time : p_time - nc->audio_start; @@ -863,12 +866,23 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double Ref<Animation> anim = player->get_animation(anim_name); - double at_anim_pos; + double at_anim_pos = 0.0; - if (anim->has_loop()) { - at_anim_pos = Math::fposmod(p_time - pos, (double)anim->get_length()); //seek to loop - } else { - at_anim_pos = MIN((double)anim->get_length(), p_time - pos); //seek to end + switch (anim->get_loop_mode()) { + case Animation::LoopMode::LOOP_NONE: { + at_anim_pos = MIN((double)anim->get_length(), p_time - pos); //seek to end + } break; + + case Animation::LoopMode::LOOP_LINEAR: { + at_anim_pos = Math::fposmod(p_time - pos, (double)anim->get_length()); //seek to loop + } break; + + case Animation::LoopMode::LOOP_PINGPONG: { + at_anim_pos = Math::pingpong(p_time - pos, (double)anim->get_length()); + } break; + + default: + break; } if (player->is_playing() || p_seeked) { @@ -883,7 +897,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double } else { //find stuff to play List<int> to_play; - a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play); + a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged); if (to_play.size()) { int idx = to_play.back()->get(); @@ -913,46 +927,73 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, double next_pos = cd.pos + delta; real_t len = cd.from->animation->get_length(); - bool loop = cd.from->animation->has_loop(); + int pingponged = 0; + + switch (cd.from->animation->get_loop_mode()) { + case Animation::LoopMode::LOOP_NONE: { + if (next_pos < 0) { + next_pos = 0; + } else if (next_pos > len) { + next_pos = len; + } - if (!loop) { - if (next_pos < 0) { - next_pos = 0; - } else if (next_pos > len) { - next_pos = len; - } + bool backwards = signbit(delta); // Negative zero means playing backwards too + delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here) - bool backwards = signbit(delta); // Negative zero means playing backwards too - delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here) + if (&cd == &playback.current) { + if (!backwards && cd.pos <= len && next_pos == len) { + //playback finished + end_reached = true; + end_notify = cd.pos < len; // Notify only if not already at the end + } - if (&cd == &playback.current) { - if (!backwards && cd.pos <= len && next_pos == len) { - //playback finished - end_reached = true; - end_notify = cd.pos < len; // Notify only if not already at the end + if (backwards && cd.pos >= 0 && next_pos == 0) { + //playback finished + end_reached = true; + end_notify = cd.pos > 0; // Notify only if not already at the beginning + } } + } break; - if (backwards && cd.pos >= 0 && next_pos == 0) { - //playback finished - end_reached = true; - end_notify = cd.pos > 0; // Notify only if not already at the beginning + case Animation::LoopMode::LOOP_LINEAR: { + double looped_next_pos = Math::fposmod(next_pos, (double)len); + if (looped_next_pos == 0 && next_pos != 0) { + // Loop multiples of the length to it, rather than 0 + // so state at time=length is previewable in the editor + next_pos = len; + } else { + next_pos = looped_next_pos; } - } + } break; - } else { - double looped_next_pos = Math::fposmod(next_pos, (double)len); - if (looped_next_pos == 0 && next_pos != 0) { - // Loop multiples of the length to it, rather than 0 - // so state at time=length is previewable in the editor - next_pos = len; - } else { - next_pos = looped_next_pos; - } + case Animation::LoopMode::LOOP_PINGPONG: { + if ((int)Math::floor(abs(next_pos - cd.pos) / len) % 2 == 0) { + if (next_pos < 0 && cd.pos >= 0) { + cd.speed_scale *= -1.0; + pingponged = -1; + } + if (next_pos > len && cd.pos <= len) { + cd.speed_scale *= -1.0; + pingponged = 1; + } + } + double looped_next_pos = Math::pingpong(next_pos, (double)len); + if (looped_next_pos == 0 && next_pos != 0) { + // Loop multiples of the length to it, rather than 0 + // so state at time=length is previewable in the editor + next_pos = len; + } else { + next_pos = looped_next_pos; + } + } break; + + default: + break; } cd.pos = next_pos; - _animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started); + _animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started, pingponged); } void AnimationPlayer::_animation_process2(double p_delta, bool p_started) { diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index d9d88b5510..ea04918988 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -231,7 +231,7 @@ private: NodePath root; - void _animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false); + void _animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false, int p_pingponged = 0); void _ensure_node_caches(AnimationData *p_anim, Node *p_root_override = nullptr); void _animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 4b71fe7a01..37e754148c 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -32,6 +32,7 @@ #include "animation_blend_tree.h" #include "core/config/engine.h" +#include "scene/resources/animation.h" #include "scene/scene_string_names.h" #include "servers/audio/audio_stream.h" @@ -87,7 +88,7 @@ void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) { } } -void AnimationNode::blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend) { +void AnimationNode::blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend, int p_pingponged) { ERR_FAIL_COND(!state); ERR_FAIL_COND(!state->player->has_animation(p_animation)); @@ -113,6 +114,7 @@ void AnimationNode::blend_animation(const StringName &p_animation, real_t p_time anim_state.time = p_time; anim_state.animation = animation; anim_state.seeked = p_seeked; + anim_state.pingponged = p_pingponged; state->animation_states.push_back(anim_state); } @@ -418,7 +420,7 @@ void AnimationNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_filters", "filters"), &AnimationNode::_set_filters); ClassDB::bind_method(D_METHOD("_get_filters"), &AnimationNode::_get_filters); - ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "blend"), &AnimationNode::blend_animation); + ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "blend", "pingponged"), &AnimationNode::blend_animation, DEFVAL(0)); ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true)); ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true)); @@ -898,6 +900,10 @@ void AnimationTree::_process_graph(real_t p_delta) { double delta = as.delta; real_t weight = as.blend; bool seeked = as.seeked; + int pingponged = as.pingponged; +#ifndef _3D_DISABLED + bool backward = signbit(delta); +#endif // _3D_DISABLED for (int i = 0; i < a->get_track_count(); i++) { NodePath path = a->track_get_path(i); @@ -939,27 +945,63 @@ void AnimationTree::_process_graph(real_t p_delta) { } if (track->root_motion) { - real_t prev_time = time - delta; - if (prev_time < 0) { - if (!a->has_loop()) { - prev_time = 0; - } else { - prev_time = a->get_length() + prev_time; + double prev_time = time - delta; + if (!backward) { + if (prev_time < 0) { + switch (a->get_loop_mode()) { + case Animation::LOOP_NONE: { + prev_time = 0; + } break; + case Animation::LOOP_LINEAR: { + prev_time = Math::fposmod(prev_time, (double)a->get_length()); + } break; + case Animation::LOOP_PINGPONG: { + prev_time = Math::pingpong(prev_time, (double)a->get_length()); + } break; + default: + break; + } + } + } else { + if (prev_time > a->get_length()) { + switch (a->get_loop_mode()) { + case Animation::LOOP_NONE: { + prev_time = (double)a->get_length(); + } break; + case Animation::LOOP_LINEAR: { + prev_time = Math::fposmod(prev_time, (double)a->get_length()); + } break; + case Animation::LOOP_PINGPONG: { + prev_time = Math::pingpong(prev_time, (double)a->get_length()); + } break; + default: + break; + } } } Vector3 loc[2]; - if (prev_time > time) { - Error err = a->position_track_interpolate(i, prev_time, &loc[0]); - if (err != OK) { - continue; + if (!backward) { + if (prev_time > time) { + Error err = a->position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + a->position_track_interpolate(i, (double)a->get_length(), &loc[1]); + t->loc += (loc[1] - loc[0]) * blend; + prev_time = 0; + } + } else { + if (prev_time < time) { + Error err = a->position_track_interpolate(i, prev_time, &loc[0]); + if (err != OK) { + continue; + } + a->position_track_interpolate(i, 0, &loc[1]); + t->loc += (loc[1] - loc[0]) * blend; + prev_time = 0; } - - a->position_track_interpolate(i, a->get_length(), &loc[1]); - - t->loc += (loc[1] - loc[0]) * blend; - prev_time = 0; } Error err = a->position_track_interpolate(i, prev_time, &loc[0]); @@ -968,17 +1010,13 @@ void AnimationTree::_process_graph(real_t p_delta) { } a->position_track_interpolate(i, time, &loc[1]); - t->loc += (loc[1] - loc[0]) * blend; - - prev_time = 0; + prev_time = !backward ? 0 : (double)a->get_length(); } else { Vector3 loc; Error err = a->position_track_interpolate(i, time, &loc); - //ERR_CONTINUE(err!=OK); //used for testing, should be removed - if (err != OK) { continue; } @@ -1000,29 +1038,65 @@ void AnimationTree::_process_graph(real_t p_delta) { } if (track->root_motion) { - real_t prev_time = time - delta; - if (prev_time < 0) { - if (!a->has_loop()) { - prev_time = 0; - } else { - prev_time = a->get_length() + prev_time; + double prev_time = time - delta; + if (!backward) { + if (prev_time < 0) { + switch (a->get_loop_mode()) { + case Animation::LOOP_NONE: { + prev_time = 0; + } break; + case Animation::LOOP_LINEAR: { + prev_time = Math::fposmod(prev_time, (double)a->get_length()); + } break; + case Animation::LOOP_PINGPONG: { + prev_time = Math::pingpong(prev_time, (double)a->get_length()); + } break; + default: + break; + } + } + } else { + if (prev_time > a->get_length()) { + switch (a->get_loop_mode()) { + case Animation::LOOP_NONE: { + prev_time = (double)a->get_length(); + } break; + case Animation::LOOP_LINEAR: { + prev_time = Math::fposmod(prev_time, (double)a->get_length()); + } break; + case Animation::LOOP_PINGPONG: { + prev_time = Math::pingpong(prev_time, (double)a->get_length()); + } break; + default: + break; + } } } Quaternion rot[2]; - if (prev_time > time) { - Error err = a->rotation_track_interpolate(i, prev_time, &rot[0]); - if (err != OK) { - continue; + if (!backward) { + if (prev_time > time) { + Error err = a->rotation_track_interpolate(i, prev_time, &rot[0]); + if (err != OK) { + continue; + } + a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]); + Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized(); + t->rot = (t->rot * q).normalized(); + prev_time = 0; + } + } else { + if (prev_time < time) { + Error err = a->rotation_track_interpolate(i, prev_time, &rot[0]); + if (err != OK) { + continue; + } + a->rotation_track_interpolate(i, 0, &rot[1]); + Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized(); + t->rot = (t->rot * q).normalized(); + prev_time = 0; } - - a->rotation_track_interpolate(i, a->get_length(), &rot[1]); - - Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized(); - t->rot = (t->rot * q).normalized(); - - prev_time = 0; } Error err = a->rotation_track_interpolate(i, prev_time, &rot[0]); @@ -1031,18 +1105,14 @@ void AnimationTree::_process_graph(real_t p_delta) { } a->rotation_track_interpolate(i, time, &rot[1]); - Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized(); t->rot = (t->rot * q).normalized(); - - prev_time = 0; + prev_time = !backward ? 0 : (double)a->get_length(); } else { Quaternion rot; Error err = a->rotation_track_interpolate(i, time, &rot); - //ERR_CONTINUE(err!=OK); //used for testing, should be removed - if (err != OK) { continue; } @@ -1071,28 +1141,63 @@ void AnimationTree::_process_graph(real_t p_delta) { } if (track->root_motion) { - real_t prev_time = time - delta; - if (prev_time < 0) { - if (!a->has_loop()) { - prev_time = 0; - } else { - prev_time = a->get_length() + prev_time; + double prev_time = time - delta; + if (!backward) { + if (prev_time < 0) { + switch (a->get_loop_mode()) { + case Animation::LOOP_NONE: { + prev_time = 0; + } break; + case Animation::LOOP_LINEAR: { + prev_time = Math::fposmod(prev_time, (double)a->get_length()); + } break; + case Animation::LOOP_PINGPONG: { + prev_time = Math::pingpong(prev_time, (double)a->get_length()); + } break; + default: + break; + } + } + } else { + if (prev_time > a->get_length()) { + switch (a->get_loop_mode()) { + case Animation::LOOP_NONE: { + prev_time = (double)a->get_length(); + } break; + case Animation::LOOP_LINEAR: { + prev_time = Math::fposmod(prev_time, (double)a->get_length()); + } break; + case Animation::LOOP_PINGPONG: { + prev_time = Math::pingpong(prev_time, (double)a->get_length()); + } break; + default: + break; + } } } Vector3 scale[2]; - if (prev_time > time) { - Error err = a->scale_track_interpolate(i, prev_time, &scale[0]); - if (err != OK) { - continue; + if (!backward) { + if (prev_time > time) { + Error err = a->scale_track_interpolate(i, prev_time, &scale[0]); + if (err != OK) { + continue; + } + a->scale_track_interpolate(i, (double)a->get_length(), &scale[1]); + t->scale += (scale[1] - scale[0]) * blend; + prev_time = 0; + } + } else { + if (prev_time < time) { + Error err = a->scale_track_interpolate(i, prev_time, &scale[0]); + if (err != OK) { + continue; + } + a->scale_track_interpolate(i, 0, &scale[1]); + t->scale += (scale[1] - scale[0]) * blend; + prev_time = 0; } - - a->scale_track_interpolate(i, a->get_length(), &scale[1]); - - t->scale += (scale[1] - scale[0]) * blend; - - prev_time = 0; } Error err = a->scale_track_interpolate(i, prev_time, &scale[0]); @@ -1101,17 +1206,13 @@ void AnimationTree::_process_graph(real_t p_delta) { } a->scale_track_interpolate(i, time, &scale[1]); - t->scale += (scale[1] - scale[0]) * blend; - - prev_time = 0; + prev_time = !backward ? 0 : (double)a->get_length(); } else { Vector3 scale; Error err = a->scale_track_interpolate(i, time, &scale); - //ERR_CONTINUE(err!=OK); //used for testing, should be removed - if (err != OK) { continue; } @@ -1164,7 +1265,7 @@ void AnimationTree::_process_graph(real_t p_delta) { } else { List<int> indices; - a->value_track_get_key_indices(i, time, delta, &indices); + a->value_track_get_key_indices(i, time, delta, &indices, pingponged); for (int &F : indices) { Variant value = a->track_get_key_value(i, F); @@ -1181,7 +1282,7 @@ void AnimationTree::_process_graph(real_t p_delta) { List<int> indices; - a->method_track_get_key_indices(i, time, delta, &indices); + a->method_track_get_key_indices(i, time, delta, &indices, pingponged); for (int &F : indices) { StringName method = a->method_track_get_name(i, F); @@ -1264,7 +1365,7 @@ void AnimationTree::_process_graph(real_t p_delta) { } else { //find stuff to play List<int> to_play; - a->track_get_key_indices_in_range(i, time, delta, &to_play); + a->track_get_key_indices_in_range(i, time, delta, &to_play, pingponged); if (to_play.size()) { int idx = to_play.back()->get(); @@ -1292,12 +1393,20 @@ void AnimationTree::_process_graph(real_t p_delta) { t->start = time; } } else if (t->playing) { - bool loop = a->has_loop(); + bool loop = a->get_loop_mode() != Animation::LoopMode::LOOP_NONE; bool stop = false; - if (!loop && time < t->start) { - stop = true; + if (!loop) { + if (delta > 0) { + if (time < t->start) { + stop = true; + } + } else if (delta < 0) { + if (time > t->start) { + stop = true; + } + } } else if (t->len > 0) { real_t len = t->start > time ? (a->get_length() - t->start) + time : time - t->start; @@ -1331,7 +1440,7 @@ void AnimationTree::_process_graph(real_t p_delta) { continue; } - if (delta == 0 || seeked) { + if (seeked) { //seek int idx = a->track_find_key(i, time); if (idx < 0) { @@ -1347,12 +1456,20 @@ void AnimationTree::_process_graph(real_t p_delta) { Ref<Animation> anim = player2->get_animation(anim_name); - real_t at_anim_pos; - - if (anim->has_loop()) { - at_anim_pos = Math::fposmod(time - pos, (double)anim->get_length()); //seek to loop - } else { - at_anim_pos = MAX(anim->get_length(), time - pos); //seek to end + real_t at_anim_pos = 0.0; + + switch (anim->get_loop_mode()) { + case Animation::LoopMode::LOOP_NONE: { + at_anim_pos = MAX((double)anim->get_length(), time - pos); //seek to end + } break; + case Animation::LoopMode::LOOP_LINEAR: { + at_anim_pos = Math::fposmod(time - pos, (double)anim->get_length()); //seek to loop + } break; + case Animation::LoopMode::LOOP_PINGPONG: { + at_anim_pos = Math::pingpong(time - pos, (double)a->get_length()); + } break; + default: + break; } if (player2->is_playing() || seeked) { @@ -1367,7 +1484,7 @@ void AnimationTree::_process_graph(real_t p_delta) { } else { //find stuff to play List<int> to_play; - a->track_get_key_indices_in_range(i, time, delta, &to_play); + a->track_get_key_indices_in_range(i, time, delta, &to_play, pingponged); if (to_play.size()) { int idx = to_play.back()->get(); diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 5abea39d20..6fc051fa41 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -66,6 +66,7 @@ public: const Vector<real_t> *track_blends = nullptr; real_t blend = 0.0; bool seeked = false; + int pingponged = 0; }; struct State { @@ -98,9 +99,10 @@ public: real_t _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, real_t *r_max = nullptr); protected: - void blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend); + void blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend, int p_pingponged = 0); real_t blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true); real_t blend_input(int p_input, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true); + void make_invalid(const String &p_reason); static void _bind_methods(); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index bef1011364..9f712ed478 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -62,7 +62,7 @@ void BaseButton::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mouse_button = p_event; bool ui_accept = p_event->is_action("ui_accept") && !p_event->is_echo(); - bool button_masked = mouse_button.is_valid() && ((1 << (mouse_button->get_button_index() - 1)) & button_mask) != 0; + bool button_masked = mouse_button.is_valid() && (mouse_button_to_mask(mouse_button->get_button_index()) & button_mask) != MouseButton::NONE; if (button_masked || ui_accept) { on_action_event(p_event); return; @@ -313,11 +313,11 @@ BaseButton::ActionMode BaseButton::get_action_mode() const { return action_mode; } -void BaseButton::set_button_mask(int p_mask) { +void BaseButton::set_button_mask(MouseButton p_mask) { button_mask = p_mask; } -int BaseButton::get_button_mask() const { +MouseButton BaseButton::get_button_mask() const { return button_mask; } diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index cd6e78464f..3ea59c3ff9 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -45,7 +45,7 @@ public: }; private: - int button_mask = MOUSE_BUTTON_MASK_LEFT; + MouseButton button_mask = MouseButton::MASK_LEFT; bool toggle_mode = false; bool shortcut_in_tooltip = true; bool keep_pressed_outside = false; @@ -118,8 +118,8 @@ public: void set_keep_pressed_outside(bool p_on); bool is_keep_pressed_outside() const; - void set_button_mask(int p_mask); - int get_button_mask() const; + void set_button_mask(MouseButton p_mask); + MouseButton get_button_mask() const; void set_shortcut(const Ref<Shortcut> &p_shortcut); Ref<Shortcut> get_shortcut() const; diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 046d256867..324b21c6d0 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -263,19 +263,19 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } switch (mb->get_button_index()) { - case MOUSE_BUTTON_WHEEL_UP: { + case MouseButton::WHEEL_UP: { if (code_completion_current_selected > 0) { code_completion_current_selected--; update(); } } break; - case MOUSE_BUTTON_WHEEL_DOWN: { + case MouseButton::WHEEL_DOWN: { if (code_completion_current_selected < code_completion_options.size() - 1) { code_completion_current_selected++; update(); } } break; - case MOUSE_BUTTON_LEFT: { + case MouseButton::LEFT: { code_completion_current_selected = CLAMP(code_completion_line_ofs + (mb->get_position().y - code_completion_rect.position.y) / get_line_height(), 0, code_completion_options.size() - 1); if (mb->is_double_click()) { confirm_code_completion(); @@ -300,7 +300,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { int line = pos.y; int col = pos.x; - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (is_line_folded(line)) { int wrap_index = get_line_wrap_index_at_column(line, col); if (wrap_index == get_line_wrap_count(line)) { @@ -314,7 +314,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } } } else { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_command_pressed() && symbol_lookup_word != String()) { Vector2i mpos = mb->get_position(); if (is_layout_rtl()) { @@ -340,7 +340,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } if (symbol_lookup_on_click_enabled) { - if (mm->is_command_pressed() && mm->get_button_mask() == 0 && !is_dragging_cursor()) { + if (mm->is_command_pressed() && mm->get_button_mask() == MouseButton::NONE && !is_dragging_cursor()) { symbol_lookup_new_word = get_word_at_pos(mpos); if (symbol_lookup_new_word != symbol_lookup_word) { emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word); @@ -360,9 +360,9 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { /* Ctrl + Hover symbols */ #ifdef OSX_ENABLED - if (k->get_keycode() == KEY_META) { + if (k->get_keycode() == Key::META) { #else - if (k->get_keycode() == KEY_CTRL) { + if (k->get_keycode() == Key::CTRL) { #endif if (symbol_lookup_on_click_enabled) { if (k->is_pressed() && !is_dragging_cursor()) { @@ -378,7 +378,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } /* If a modifier has been pressed, and nothing else, return. */ - if (!k->is_pressed() || k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) { + if (!k->is_pressed() || k->get_keycode() == Key::CTRL || k->get_keycode() == Key::ALT || k->get_keycode() == Key::SHIFT || k->get_keycode() == Key::META) { return; } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 894175d559..049cdb5bef 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -582,7 +582,7 @@ void ColorPicker::_update_text_value() { void ColorPicker::_sample_input(const Ref<InputEvent> &p_event) { const Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95)); if (rect_old.has_point(mb->get_position())) { // Revert to the old color when left-clicking the old color sample. @@ -827,7 +827,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid()) { - if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { + if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { Vector2 center = c->get_size() / 2.0; if (picker_type == SHAPE_VHS_CIRCLE) { real_t dist = center.distance_to(bev->get_position()); @@ -875,7 +875,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) { if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); } - } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { + } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { emit_signal(SNAME("color_changed"), color); changing_color = false; spinning = false; @@ -929,7 +929,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid()) { - if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { + if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { changing_color = true; float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height); if (picker_type == SHAPE_VHS_CIRCLE) { @@ -946,7 +946,7 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { _update_color(); if (!deferred_mode_enabled) { emit_signal(SNAME("color_changed"), color); - } else if (!bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { + } else if (!bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { emit_signal(SNAME("color_changed"), color); } } @@ -977,11 +977,11 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event, const Color &p_c Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid()) { - if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_LEFT) { + if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) { set_pick_color(p_color); _update_color(); emit_signal(SNAME("color_changed"), p_color); - } else if (bev->is_pressed() && bev->get_button_index() == MOUSE_BUTTON_RIGHT && presets_enabled) { + } else if (bev->is_pressed() && bev->get_button_index() == MouseButton::RIGHT && presets_enabled) { erase_preset(p_color); emit_signal(SNAME("preset_removed"), p_color); } @@ -994,7 +994,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseButton> bev = p_event; - if (bev.is_valid() && bev->get_button_index() == MOUSE_BUTTON_LEFT && !bev->is_pressed()) { + if (bev.is_valid() && bev->get_button_index() == MouseButton::LEFT && !bev->is_pressed()) { emit_signal(SNAME("color_changed"), color); screen->hide(); } diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 71d2778cc3..f66d3f6835 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -44,7 +44,7 @@ void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) { Ref<InputEventKey> key = p_event; - if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ESCAPE) { + if (key.is_valid() && key->is_pressed() && key->get_keycode() == Key::ESCAPE) { _cancel_pressed(); } } diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 5f9f09fc50..44853fc006 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -110,7 +110,7 @@ void FileDialog::unhandled_input(const Ref<InputEvent> &p_event) { bool handled = true; switch (k->get_keycode()) { - case KEY_H: { + case Key::H: { if (k->is_command_pressed()) { set_show_hidden_files(!show_hidden_files); } else { @@ -118,10 +118,10 @@ void FileDialog::unhandled_input(const Ref<InputEvent> &p_event) { } } break; - case KEY_F5: { + case Key::F5: { invalidate(); } break; - case KEY_BACKSPACE: { + case Key::BACKSPACE: { _dir_submitted(".."); } break; default: { diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index e5b23d8006..ae15b021a5 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -88,7 +88,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && grabbed != -1) { + if (k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && grabbed != -1) { points.remove(grabbed); grabbed = -1; grabbing = false; @@ -99,14 +99,14 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; // Show color picker on double click. - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_double_click() && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_double_click() && mb->is_pressed()) { grabbed = _get_point_from_pos(mb->get_position().x); _show_color_picker(); accept_event(); } // Delete point on right click. - if (mb.is_valid() && mb->get_button_index() == 2 && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { grabbed = _get_point_from_pos(mb->get_position().x); if (grabbed != -1) { points.remove(grabbed); @@ -119,7 +119,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } // Hold alt key to duplicate selected color. - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && mb->is_alt_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && mb->is_alt_pressed()) { int x = mb->get_position().x; grabbed = _get_point_from_pos(x); @@ -143,7 +143,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { } // Select. - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { update(); int x = mb->get_position().x; int total_w = get_size().width - get_size().height - draw_spacing; @@ -209,7 +209,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) { emit_signal(SNAME("ramp_changed")); } - if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { if (grabbing) { grabbing = false; emit_signal(SNAME("ramp_changed")); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 35e31be9af..e7d98a686f 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -150,7 +150,7 @@ void GraphEditMinimap::gui_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseButton> mb = p_ev; Ref<InputEventMouseMotion> mm = p_ev; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { is_pressing = true; @@ -501,6 +501,43 @@ void GraphEdit::_notification(int p_what) { } } +void GraphEdit::_update_comment_enclosed_nodes_list(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes) { + Rect2 comment_node_rect = p_node->get_rect(); + Vector<GraphNode *> enclosed_nodes; + + for (int i = 0; i < get_child_count(); i++) { + GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); + if (!gn || gn->is_selected()) { + continue; + } + + Rect2 node_rect = gn->get_rect(); + bool included = comment_node_rect.encloses(node_rect); + if (included) { + enclosed_nodes.push_back(gn); + } + } + + p_comment_enclosed_nodes.set(p_node->get_name(), enclosed_nodes); +} + +void GraphEdit::_set_drag_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, bool p_drag) { + for (int i = 0; i < p_comment_enclosed_nodes[p_node->get_name()].size(); i++) { + p_comment_enclosed_nodes[p_node->get_name()][i]->set_drag(p_drag); + } +} + +void GraphEdit::_set_position_of_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, Vector2 p_drag_accum) { + for (int i = 0; i < p_comment_enclosed_nodes[p_node->get_name()].size(); i++) { + Vector2 pos = (p_comment_enclosed_nodes[p_node->get_name()][i]->get_drag_from() * zoom + drag_accum) / zoom; + if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(Key::CTRL)) { + const int snap = get_snap(); + pos = pos.snapped(Vector2(snap, snap)); + } + p_comment_enclosed_nodes[p_node->get_name()][i]->set_position_offset(pos); + } +} + bool GraphEdit::_filter_input(const Point2 &p_point) { Ref<Texture2D> port = get_theme_icon(SNAME("port"), SNAME("GraphNode")); Vector2i port_size = Vector2i(port->get_width(), port->get_height()); @@ -531,7 +568,7 @@ bool GraphEdit::_filter_input(const Point2 &p_point) { void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseButton> mb = p_ev; - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { Ref<Texture2D> port = get_theme_icon(SNAME("port"), SNAME("GraphNode")); Vector2i port_size = Vector2i(port->get_width(), port->get_height()); @@ -678,7 +715,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { } } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { if (connecting_valid) { if (connecting && connecting_target) { String from = connecting_from; @@ -1031,7 +1068,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { ERR_FAIL_COND(p_ev.is_null()); Ref<InputEventMouseMotion> mm = p_ev; - if (mm.is_valid() && (mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { + if (mm.is_valid() && ((mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE || ((mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE && Input::get_singleton()->is_key_pressed(Key::SPACE)))) { Vector2i relative = Input::get_singleton()->warp_mouse_motion(mm, get_global_rect()); h_scroll->set_value(h_scroll->get_value() - relative.x); v_scroll->set_value(v_scroll->get_value() - relative.y); @@ -1052,12 +1089,15 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { // Snapping can be toggled temporarily by holding down Ctrl. // This is done here as to not toggle the grid when holding down Ctrl. - if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(Key::CTRL)) { const int snap = get_snap(); pos = pos.snapped(Vector2(snap, snap)); } gn->set_position_offset(pos); + if (gn->is_comment()) { + _set_position_of_comment_enclosed_nodes(gn, comment_enclosed_nodes, drag_accum); + } } } } @@ -1101,7 +1141,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseButton> b = p_ev; if (b.is_valid()) { - if (b->get_button_index() == MOUSE_BUTTON_RIGHT && b->is_pressed()) { + if (b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { if (box_selecting) { box_selecting = false; for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1131,8 +1171,8 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } } - if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && dragging) { - if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (b->get_button_index() == MouseButton::LEFT && !b->is_pressed() && dragging) { + if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(Key::CTRL)) { //deselect current node for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); @@ -1153,6 +1193,9 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); if (gn && gn->is_selected()) { gn->set_drag(false); + if (gn->is_comment()) { + _set_drag_comment_enclosed_nodes(gn, comment_enclosed_nodes, false); + } } } } @@ -1170,7 +1213,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { connections_layer->update(); } - if (b->get_button_index() == MOUSE_BUTTON_LEFT && b->is_pressed()) { + if (b->get_button_index() == MouseButton::LEFT && b->is_pressed()) { GraphNode *gn = nullptr; for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1196,7 +1239,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { dragging = true; drag_accum = Vector2(); just_selected = !gn->is_selected(); - if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CTRL)) { + if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { for (int i = 0; i < get_child_count(); i++) { GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i)); if (o_gn) { @@ -1220,6 +1263,10 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } if (o_gn->is_selected()) { o_gn->set_drag(true); + if (o_gn->is_comment()) { + _update_comment_enclosed_nodes_list(o_gn, comment_enclosed_nodes); + _set_drag_comment_enclosed_nodes(o_gn, comment_enclosed_nodes, true); + } } } @@ -1227,7 +1274,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { if (_filter_input(b->get_position())) { return; } - if (Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + if (Input::get_singleton()->is_key_pressed(Key::SPACE)) { return; } @@ -1272,7 +1319,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } } - if (b->get_button_index() == MOUSE_BUTTON_LEFT && !b->is_pressed() && box_selecting) { + if (b->get_button_index() == MouseButton::LEFT && !b->is_pressed() && box_selecting) { box_selecting = false; box_selecting_rect = Rect2(); previous_selected.clear(); @@ -1280,7 +1327,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { minimap->update(); } - int scroll_direction = (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) - (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP); + int scroll_direction = (b->get_button_index() == MouseButton::WHEEL_DOWN) - (b->get_button_index() == MouseButton::WHEEL_UP); if (scroll_direction != 0) { if (b->is_ctrl_pressed()) { if (b->is_shift_pressed()) { diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 44e50aa3c2..6c11f9df6a 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -217,6 +217,11 @@ private: Set<int> valid_left_disconnect_types; Set<int> valid_right_disconnect_types; + HashMap<StringName, Vector<GraphNode *>> comment_enclosed_nodes; + void _update_comment_enclosed_nodes_list(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes); + void _set_drag_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, bool p_drag); + void _set_position_of_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, Vector2 p_pos); + HBoxContainer *zoom_hb; friend class GraphEditFilter; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 8462fd259e..e7094c89b1 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -894,7 +894,7 @@ void GraphNode::gui_input(const Ref<InputEvent> &p_ev) { if (mb.is_valid()) { ERR_FAIL_COND_MSG(get_parent_control() == nullptr, "GraphNode must be the child of a GraphEdit node."); - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Vector2 mpos = mb->get_position(); if (close_rect.size != Size2() && close_rect.has_point(mpos)) { //send focus to parent @@ -917,7 +917,7 @@ void GraphNode::gui_input(const Ref<InputEvent> &p_ev) { emit_signal(SNAME("raise_request")); } - if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (!mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { resizing = false; } } diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 8470003b3e..c0f2cdbef1 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -547,7 +547,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (defer_select_single >= 0 && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) { + if (defer_select_single >= 0 && mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { select(defer_select_single, true); emit_signal(SNAME("multi_selected"), defer_select_single, true); @@ -555,7 +555,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { return; } - if (mb.is_valid() && (mb->get_button_index() == MOUSE_BUTTON_LEFT || (allow_rmb_select && mb->get_button_index() == MOUSE_BUTTON_RIGHT)) && mb->is_pressed()) { + if (mb.is_valid() && (mb->get_button_index() == MouseButton::LEFT || (allow_rmb_select && mb->get_button_index() == MouseButton::RIGHT)) && mb->is_pressed()) { search_string = ""; //any mousepress cancels Vector2 pos = mb->get_position(); Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg")); @@ -601,16 +601,16 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->get_button_index() == MouseButton::RIGHT) { emit_signal(SNAME("item_rmb_selected"), i, get_local_mouse_position()); } } else { - if (!mb->is_double_click() && !mb->is_command_pressed() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (!mb->is_double_click() && !mb->is_command_pressed() && select_mode == SELECT_MULTI && items[i].selectable && !items[i].disabled && items[i].selected && mb->get_button_index() == MouseButton::LEFT) { defer_select_single = i; return; } - if (items[i].selected && mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (items[i].selected && mb->get_button_index() == MouseButton::RIGHT) { emit_signal(SNAME("item_rmb_selected"), i, get_local_mouse_position()); } else { bool selected = items[i].selected; @@ -625,7 +625,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->get_button_index() == MouseButton::RIGHT) { emit_signal(SNAME("item_rmb_selected"), i, get_local_mouse_position()); } else if (/*select_mode==SELECT_SINGLE &&*/ mb->is_double_click()) { emit_signal(SNAME("item_activated"), i); @@ -635,7 +635,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { return; } - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (mb->get_button_index() == MouseButton::RIGHT) { emit_signal(SNAME("rmb_clicked"), mb->get_position()); return; @@ -644,10 +644,10 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { // Since closest is null, more likely we clicked on empty space, so send signal to interested controls. Allows, for example, implement items deselecting. emit_signal(SNAME("nothing_selected")); } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) { scroll_bar->set_value(scroll_bar->get_value() - scroll_bar->get_page() * mb->get_factor() / 8); } - if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) { scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() * mb->get_factor() / 8); } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 15fd22ced5..124d5c7821 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -225,7 +225,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { // Ignore mouse clicks in IME input mode. return; } - if (b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) { + if (b->is_pressed() && b->get_button_index() == MouseButton::RIGHT && context_menu_enabled) { _ensure_menu(); menu->set_position(get_screen_transform().xform(get_local_mouse_position())); menu->set_size(Vector2(1, 1)); @@ -235,7 +235,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { return; } - if (is_middle_mouse_paste_enabled() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_MIDDLE && is_editable() && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { + if (is_middle_mouse_paste_enabled() && b->is_pressed() && b->get_button_index() == MouseButton::MIDDLE && is_editable() && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { String paste_buffer = DisplayServer::get_singleton()->clipboard_get_primary().strip_escapes(); deselect(); @@ -254,7 +254,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { return; } - if (b->get_button_index() != MOUSE_BUTTON_LEFT) { + if (b->get_button_index() != MouseButton::LEFT) { return; } @@ -328,7 +328,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { update(); } else { - if (selection.enabled && !pass && b->get_button_index() == MOUSE_BUTTON_LEFT && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { + if (selection.enabled && !pass && b->get_button_index() == MouseButton::LEFT && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { DisplayServer::get_singleton()->clipboard_set_primary(text.substr(selection.begin, selection.end - selection.begin)); } if (!text.is_empty() && is_editable() && clear_button_enabled) { @@ -363,7 +363,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { } } - if (m->get_button_mask() & MOUSE_BUTTON_LEFT) { + if ((m->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { if (selection.creating) { set_caret_at_pixel_pos(m->get_position().x); selection_fill_at_caret(); @@ -577,13 +577,12 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { if (p_data.get_type() == Variant::STRING) { set_caret_at_pixel_pos(p_point.x); - int selected = selection.end - selection.begin; - text.erase(selection.begin, selected); + text = text.left(selection.begin) + text.substr(selection.end); _shape(); insert_text_at_caret(p_data); - selection.begin = caret_column - selected; + selection.begin = caret_column - (selection.end - selection.begin); selection.end = caret_column; } } @@ -1244,7 +1243,7 @@ void LineEdit::delete_char() { return; } - text.erase(caret_column - 1, 1); + text = text.left(caret_column - 1) + text.substr(caret_column); _shape(); set_caret_column(get_caret_column() - 1); @@ -1256,7 +1255,7 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { ERR_FAIL_COND_MSG(p_from_column < 0 || p_from_column > p_to_column || p_to_column > text.length(), vformat("Positional parameters (from: %d, to: %d) are inverted or outside the text length (%d).", p_from_column, p_to_column, text.length())); - text.erase(p_from_column, p_to_column - p_from_column); + text = text.left(p_from_column) + text.substr(p_to_column); _shape(); caret_column -= CLAMP(caret_column - p_from_column, 0, p_to_column - p_from_column); @@ -2071,25 +2070,25 @@ void LineEdit::_create_undo_state() { undo_stack.push_back(op); } -int LineEdit::_get_menu_action_accelerator(const String &p_action) { +Key LineEdit::_get_menu_action_accelerator(const String &p_action) { const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(p_action); if (!events) { - return 0; + return Key::NONE; } // Use first event in the list for the accelerator. const List<Ref<InputEvent>>::Element *first_event = events->front(); if (!first_event) { - return 0; + return Key::NONE; } const Ref<InputEventKey> event = first_event->get(); if (event.is_null()) { - return 0; + return Key::NONE; } // Use physical keycode if non-zero - if (event->get_physical_keycode() != 0) { + if (event->get_physical_keycode() != Key::NONE) { return event->get_physical_keycode_with_modifiers(); } else { return event->get_keycode_with_modifiers(); @@ -2345,21 +2344,21 @@ void LineEdit::_ensure_menu() { // Reorganize context menu. menu->clear(); if (editable) { - menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : 0); + menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : Key::NONE); } - menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : 0); + menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : Key::NONE); if (editable) { - menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : 0); + menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : Key::NONE); } menu->add_separator(); if (is_selecting_enabled()) { - menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : 0); + menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : Key::NONE); } if (editable) { menu->add_item(RTR("Clear"), MENU_CLEAR); menu->add_separator(); - menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : 0); - menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0); + menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : Key::NONE); + menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : Key::NONE); } menu->add_separator(); menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu"); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 2ec7f08865..134d5f8f76 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -170,7 +170,7 @@ private: void _clear_redo(); void _create_undo_state(); - int _get_menu_action_accelerator(const String &p_action); + Key _get_menu_action_accelerator(const String &p_action); void _shape(); void _fit_to_width(); diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index f54ff9228b..a48ad0f770 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -36,7 +36,7 @@ void Popup::_input_from_window(const Ref<InputEvent> &p_event) { Ref<InputEventKey> key = p_event; - if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ESCAPE) { + if (key.is_valid() && key->is_pressed() && key->get_keycode() == Key::ESCAPE) { _close_pressed(); } } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 54af9f3885..7e9b545776 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -39,7 +39,7 @@ String PopupMenu::_get_accel_text(const Item &p_item) const { if (p_item.shortcut.is_valid()) { return p_item.shortcut->get_as_text(); - } else if (p_item.accel) { + } else if (p_item.accel != Key::NONE) { return keycode_get_string(p_item.accel); } return String(); @@ -74,7 +74,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const { size.width += items[i].text_buf->get_size().x; size.height += vseparation; - if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) { + if (items[i].accel != Key::NONE || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) { int accel_w = hseparation * 2; accel_w += items[i].accel_text_buf->get_size().x; accel_max_w = MAX(accel_w, accel_max_w); @@ -358,15 +358,15 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) { return; } - int button_idx = b->get_button_index(); + MouseButton button_idx = b->get_button_index(); if (!b->is_pressed()) { // Activate the item on release of either the left mouse button or // any mouse button held down when the popup was opened. // This allows for opening the popup and triggering an action in a single mouse click. - if (button_idx == MOUSE_BUTTON_LEFT || (initial_button_mask & (1 << (button_idx - 1)))) { + if (button_idx == MouseButton::LEFT || (initial_button_mask & mouse_button_to_mask(button_idx)) != MouseButton::NONE) { bool was_during_grabbed_click = during_grabbed_click; during_grabbed_click = false; - initial_button_mask = 0; + initial_button_mask = MouseButton::NONE; // Disable clicks under a time threshold to avoid selection right when opening the popup. uint64_t now = OS::get_singleton()->get_ticks_msec(); @@ -637,7 +637,7 @@ void PopupMenu::_draw_items() { } // Accelerator / Shortcut - if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) { + if (items[i].accel != Key::NONE || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) { if (rtl) { item_ofs.x = scroll_width + style->get_margin(SIDE_LEFT) + item_end_padding; } else { @@ -813,7 +813,7 @@ void PopupMenu::_notification(int p_what) { item.id = p_id == -1 ? items.size() : p_id; \ item.accel = p_accel; -void PopupMenu::add_item(const String &p_label, int p_id, uint32_t p_accel) { +void PopupMenu::add_item(const String &p_label, int p_id, Key p_accel) { Item item; ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); items.push_back(item); @@ -823,7 +823,7 @@ void PopupMenu::add_item(const String &p_label, int p_id, uint32_t p_accel) { notify_property_list_changed(); } -void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) { +void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, Key p_accel) { Item item; ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.icon = p_icon; @@ -834,7 +834,7 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe notify_property_list_changed(); } -void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel) { +void PopupMenu::add_check_item(const String &p_label, int p_id, Key p_accel) { Item item; ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; @@ -844,7 +844,7 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel child_controls_changed(); } -void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) { +void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, Key p_accel) { Item item; ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.icon = p_icon; @@ -855,7 +855,7 @@ void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String & child_controls_changed(); } -void PopupMenu::add_radio_check_item(const String &p_label, int p_id, uint32_t p_accel) { +void PopupMenu::add_radio_check_item(const String &p_label, int p_id, Key p_accel) { Item item; ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; @@ -865,7 +865,7 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_id, uint32_t p child_controls_changed(); } -void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) { +void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, Key p_accel) { Item item; ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.icon = p_icon; @@ -876,7 +876,7 @@ void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const St child_controls_changed(); } -void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_id, uint32_t p_accel) { +void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_id, Key p_accel) { Item item; ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.max_states = p_max_states; @@ -1045,7 +1045,7 @@ void PopupMenu::set_item_id(int p_idx, int p_id) { child_controls_changed(); } -void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) { +void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].accel = p_accel; items.write[p_idx].dirty = true; @@ -1121,8 +1121,8 @@ Ref<Texture2D> PopupMenu::get_item_icon(int p_idx) const { return items[p_idx].icon; } -uint32_t PopupMenu::get_item_accelerator(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, items.size(), 0); +Key PopupMenu::get_item_accelerator(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, items.size(), Key::NONE); return items[p_idx].accel; } @@ -1286,25 +1286,25 @@ int PopupMenu::get_item_count() const { } bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only) { - Key code = KEY_NONE; + Key code = Key::NONE; Ref<InputEventKey> k = p_event; if (k.is_valid()) { code = k->get_keycode(); - if (code == KEY_NONE) { + if (code == Key::NONE) { code = (Key)k->get_unicode(); } if (k->is_ctrl_pressed()) { - code |= KEY_MASK_CTRL; + code |= KeyModifierMask::CTRL; } if (k->is_alt_pressed()) { - code |= KEY_MASK_ALT; + code |= KeyModifierMask::ALT; } if (k->is_meta_pressed()) { - code |= KEY_MASK_META; + code |= KeyModifierMask::META; } if (k->is_shift_pressed()) { - code |= KEY_MASK_SHIFT; + code |= KeyModifierMask::SHIFT; } } @@ -1318,7 +1318,7 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo return true; } - if (code != 0 && items[i].accel == code) { + if (code != Key::NONE && items[i].accel == code) { activate_item(i); return true; } @@ -1603,7 +1603,7 @@ bool PopupMenu::_set(const StringName &p_name, const Variant &p_value) { set_item_id(idx, id); set_item_metadata(idx, meta); set_item_as_separator(idx, sep); - set_item_accelerator(idx, accel); + set_item_accelerator(idx, (Key)accel); set_item_submenu(idx, subm); } } diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 80874ca1e0..22912fb59c 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -66,7 +66,7 @@ class PopupMenu : public Popup { Variant metadata; String submenu; String tooltip; - uint32_t accel = 0; + Key accel = Key::NONE; int _ofs_cache = 0; int _height_cache = 0; int h_ofs = 0; @@ -92,7 +92,7 @@ class PopupMenu : public Popup { Timer *submenu_timer; List<Rect2> autohide_areas; Vector<Item> items; - int initial_button_mask = 0; + MouseButton initial_button_mask = MouseButton::NONE; bool during_grabbed_click = false; int mouse_over = -1; int submenu_over = -1; @@ -148,14 +148,14 @@ public: // this value should be updated to reflect the new size. static const int ITEM_PROPERTY_SIZE = 10; - void add_item(const String &p_label, int p_id = -1, uint32_t p_accel = 0); - void add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0); - void add_check_item(const String &p_label, int p_id = -1, uint32_t p_accel = 0); - void add_icon_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0); - void add_radio_check_item(const String &p_label, int p_id = -1, uint32_t p_accel = 0); - void add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, uint32_t p_accel = 0); + void add_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE); + void add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, Key p_accel = Key::NONE); + void add_check_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE); + void add_icon_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, Key p_accel = Key::NONE); + void add_radio_check_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE); + void add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, Key p_accel = Key::NONE); - void add_multistate_item(const String &p_label, int p_max_states, int p_default_state = 0, int p_id = -1, uint32_t p_accel = 0); + void add_multistate_item(const String &p_label, int p_max_states, int p_default_state = 0, int p_id = -1, Key p_accel = Key::NONE); void add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); void add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); @@ -175,7 +175,7 @@ public: void set_item_icon(int p_idx, const Ref<Texture2D> &p_icon); void set_item_checked(int p_idx, bool p_checked); void set_item_id(int p_idx, int p_id); - void set_item_accelerator(int p_idx, uint32_t p_accel); + void set_item_accelerator(int p_idx, Key p_accel); void set_item_metadata(int p_idx, const Variant &p_meta); void set_item_disabled(int p_idx, bool p_disabled); void set_item_submenu(int p_idx, const String &p_submenu); @@ -200,7 +200,7 @@ public: bool is_item_checked(int p_idx) const; int get_item_id(int p_idx) const; int get_item_index(int p_id) const; - uint32_t get_item_accelerator(int p_idx) const; + Key get_item_accelerator(int p_idx) const; Variant get_item_metadata(int p_idx) const; bool is_item_disabled(int p_idx) const; String get_item_submenu(int p_idx) const; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 308880ef18..f191dfecb4 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -36,7 +36,7 @@ #include "scene/scene_string_names.h" #include "servers/display_server.h" -#include "modules/modules_enabled.gen.h" +#include "modules/modules_enabled.gen.h" // For regex. #ifdef MODULE_REGEX_ENABLED #include "modules/regex/regex.h" #endif @@ -1545,7 +1545,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) { return; } - if (b->get_button_index() == MOUSE_BUTTON_LEFT) { + if (b->get_button_index() == MouseButton::LEFT) { if (b->is_pressed() && !b->is_double_click()) { scroll_updated = false; ItemFrame *c_frame = nullptr; @@ -1636,12 +1636,12 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) { } } - if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (b->get_button_index() == MouseButton::WHEEL_UP) { if (scroll_active) { vscroll->set_value(vscroll->get_value() - vscroll->get_page() * b->get_factor() * 0.5 / 8); } } - if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + if (b->get_button_index() == MouseButton::WHEEL_DOWN) { if (scroll_active) { vscroll->set_value(vscroll->get_value() + vscroll->get_page() * b->get_factor() * 0.5 / 8); } @@ -3801,45 +3801,32 @@ String RichTextLabel::_get_line_text(ItemFrame *p_frame, int p_line, Selection p } } for (Item *it = l.from; it && it != it_to; it = _get_next_item(it)) { + if (it->type == ITEM_TABLE) { + ItemTable *table = static_cast<ItemTable *>(it); + for (Item *E : table->subitems) { + ERR_CONTINUE(E->type != ITEM_FRAME); // Children should all be frames. + ItemFrame *frame = static_cast<ItemFrame *>(E); + for (int i = 0; i < frame->lines.size(); i++) { + text += _get_line_text(frame, i, p_selection); + } + } + } if ((p_selection.to_item != nullptr) && (p_selection.to_item->index < l.from->index)) { - break; + continue; } if ((p_selection.from_item != nullptr) && (p_selection.from_item->index >= end_idx)) { - break; + continue; } - switch (it->type) { - case ITEM_NEWLINE: { - text += "\n"; - } break; - case ITEM_TEXT: { - ItemText *t = (ItemText *)it; - text += t->text; - } break; - case ITEM_IMAGE: { - text += " "; - } break; - case ITEM_TABLE: { - ItemTable *table = static_cast<ItemTable *>(it); - int idx = 0; - int col_count = table->columns.size(); - for (Item *E : table->subitems) { - ERR_CONTINUE(E->type != ITEM_FRAME); // Children should all be frames. - ItemFrame *frame = static_cast<ItemFrame *>(E); - int column = idx % col_count; - - for (int i = 0; i < frame->lines.size(); i++) { - text += _get_line_text(frame, i, p_selection); - } - if (column == col_count - 1) { - text += "\n"; - } else { - text += " "; - } - idx++; - } - } break; - default: - break; + if (it->type == ITEM_DROPCAP) { + const ItemDropcap *dc = static_cast<ItemDropcap *>(it); + text += dc->text; + } else if (it->type == ITEM_TEXT) { + const ItemText *t = static_cast<ItemText *>(it); + text += t->text; + } else if (it->type == ITEM_NEWLINE) { + text += "\n"; + } else if (it->type == ITEM_IMAGE) { + text += " "; } } if ((l.from != nullptr) && (p_frame == p_selection.to_frame) && (p_selection.to_item != nullptr) && (p_selection.to_item->index >= l.from->index) && (p_selection.to_item->index < end_idx)) { diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index 4a3a6837d5..8c292e663e 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -54,17 +54,17 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) { if (b.is_valid()) { accept_event(); - if (b->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && b->is_pressed()) { + if (b->get_button_index() == MouseButton::WHEEL_DOWN && b->is_pressed()) { set_value(get_value() + get_page() / 4.0); accept_event(); } - if (b->get_button_index() == MOUSE_BUTTON_WHEEL_UP && b->is_pressed()) { + if (b->get_button_index() == MouseButton::WHEEL_UP && b->is_pressed()) { set_value(get_value() - get_page() / 4.0); accept_event(); } - if (b->get_button_index() != MOUSE_BUTTON_LEFT) { + if (b->get_button_index() != MouseButton::LEFT) { return; } @@ -525,7 +525,7 @@ void ScrollBar::_drag_node_input(const Ref<InputEvent> &p_input) { Ref<InputEventMouseButton> mb = p_input; if (mb.is_valid()) { - if (mb->get_button_index() != 1) { + if (mb->get_button_index() != MouseButton::LEFT) { return; } diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 0c0ec39c7f..7b2ea46e17 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -92,7 +92,7 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { Ref<InputEventMouseButton> mb = p_gui_input; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) { // only horizontal is enabled, scroll horizontally if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb->get_factor()); @@ -101,7 +101,7 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { } } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) { // only horizontal is enabled, scroll horizontally if (h_scroll->is_visible() && (!v_scroll->is_visible() || mb->is_shift_pressed())) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb->get_factor()); @@ -110,13 +110,13 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { } } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_LEFT && mb->is_pressed()) { if (h_scroll->is_visible_in_tree()) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb->get_factor() / 8); } } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT && mb->is_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_RIGHT && mb->is_pressed()) { if (h_scroll->is_visible_in_tree()) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * mb->get_factor() / 8); } @@ -130,7 +130,7 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { return; } - if (mb->get_button_index() != MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() != MouseButton::LEFT) { return; } @@ -320,7 +320,9 @@ void ScrollContainer::_notification(int p_what) { }; if (p_what == NOTIFICATION_READY) { - get_viewport()->connect("gui_focus_changed", callable_mp(this, &ScrollContainer::_gui_focus_changed)); + Viewport *viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + viewport->connect("gui_focus_changed", callable_mp(this, &ScrollContainer::_gui_focus_changed)); _update_dimensions(); } diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 352f87954e..4cc425aad3 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -55,7 +55,7 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { Ref<Texture2D> grabber = get_theme_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber"); grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x; @@ -74,10 +74,10 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) { grab.active = false; } } else if (scrollable) { - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { grab_focus(); set_value(get_value() + get_step()); - } else if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) { + } else if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { grab_focus(); set_value(get_value() - get_step()); } diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 0446e1b402..f30206c943 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -85,7 +85,7 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) { } void SpinBox::_range_click_timeout() { - if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) { + if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) { bool up = get_local_mouse_position().y < (get_size().height / 2); set_value(get_value() + (up ? get_step() : -get_step())); @@ -121,7 +121,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { bool up = mb->get_position().y < (get_size().height / 2); switch (mb->get_button_index()) { - case MOUSE_BUTTON_LEFT: { + case MouseButton::LEFT: { line_edit->grab_focus(); set_value(get_value() + (up ? get_step() : -get_step())); @@ -133,17 +133,17 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { drag.allowed = true; drag.capture_pos = mb->get_position(); } break; - case MOUSE_BUTTON_RIGHT: { + case MouseButton::RIGHT: { line_edit->grab_focus(); set_value((up ? get_max() : get_min())); } break; - case MOUSE_BUTTON_WHEEL_UP: { + case MouseButton::WHEEL_UP: { if (line_edit->has_focus()) { set_value(get_value() + get_step() * mb->get_factor()); accept_event(); } } break; - case MOUSE_BUTTON_WHEEL_DOWN: { + case MouseButton::WHEEL_DOWN: { if (line_edit->has_focus()) { set_value(get_value() - get_step() * mb->get_factor()); accept_event(); @@ -154,7 +154,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { //set_default_cursor_shape(CURSOR_ARROW); range_click_timer->stop(); _release_mouse(); @@ -163,10 +163,10 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { if (drag.enabled) { drag.diff_y += mm->get_relative().y; - float diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8f) * SGN(drag.diff_y); + float diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8f) * SIGN(drag.diff_y); set_value(CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max())); } else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 4736a1ad37..6b53c0220e 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -216,7 +216,7 @@ void SplitContainer::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { int sep = get_theme_constant(SNAME("separation")); diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index 405fbdae75..1dda29f668 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -143,7 +143,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->is_command_pressed()) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP && !mb->is_command_pressed()) { if (scrolling_enabled && buttons_visible) { if (offset > 0) { offset--; @@ -152,7 +152,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { } } - if (mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->is_command_pressed()) { + if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN && !mb->is_command_pressed()) { if (scrolling_enabled && buttons_visible) { if (missing_right) { offset++; @@ -162,7 +162,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { } } - if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (rb_hover != -1) { // pressed emit_signal(SNAME("tab_rmb_clicked"), rb_hover); @@ -172,7 +172,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { update(); } - if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (cb_hover != -1) { // pressed emit_signal(SNAME("tab_close_pressed"), cb_hover); @@ -182,7 +182,7 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { update(); } - if (mb->is_pressed() && (mb->get_button_index() == MOUSE_BUTTON_LEFT || (select_with_rmb && mb->get_button_index() == MOUSE_BUTTON_RIGHT))) { + if (mb->is_pressed() && (mb->get_button_index() == MouseButton::LEFT || (select_with_rmb && mb->get_button_index() == MouseButton::RIGHT))) { // clicks Point2 pos = mb->get_position(); diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index c8a0501d8a..ff53d91ea3 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -78,7 +78,7 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) { Popup *popup = get_popup(); - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { Point2 pos = mb->get_position(); Size2 size = get_size(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index cb7a6c0978..fbfeea5722 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1407,7 +1407,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } if (mb->is_pressed()) { - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP && !mb->is_command_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_UP && !mb->is_command_pressed()) { if (mb->is_shift_pressed()) { h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); } else if (mb->is_alt_pressed()) { @@ -1418,7 +1418,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { _scroll_up(3 * mb->get_factor()); } } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN && !mb->is_command_pressed()) { + if (mb->get_button_index() == MouseButton::WHEEL_DOWN && !mb->is_command_pressed()) { if (mb->is_shift_pressed()) { h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); } else if (mb->is_alt_pressed()) { @@ -1429,13 +1429,13 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { _scroll_down(3 * mb->get_factor()); } } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT) { + if (mb->get_button_index() == MouseButton::WHEEL_LEFT) { h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); } - if (mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT) { + if (mb->get_button_index() == MouseButton::WHEEL_RIGHT) { h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); } - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { _reset_caret_blink_timer(); Point2i pos = get_line_column_at_pos(mpos); @@ -1538,11 +1538,11 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { update(); } - if (is_middle_mouse_paste_enabled() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { + if (is_middle_mouse_paste_enabled() && mb->get_button_index() == MouseButton::MIDDLE && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { paste_primary_clipboard(); } - if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) { + if (mb->get_button_index() == MouseButton::RIGHT && context_menu_enabled) { _reset_caret_blink_timer(); Point2i pos = get_line_column_at_pos(mpos); @@ -1574,7 +1574,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { grab_focus(); } } else { - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { dragging_minimap = false; dragging_selection = false; can_drag_minimap = false; @@ -1613,7 +1613,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { mpos.x = get_size().x - mpos.x; } - if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging. + if ((mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging. _reset_caret_blink_timer(); if (draw_minimap && !dragging_selection) { @@ -1681,7 +1681,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } // If a modifier has been pressed, and nothing else, return. - if (k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) { + if (k->get_keycode() == Key::CTRL || k->get_keycode() == Key::ALT || k->get_keycode() == Key::SHIFT || k->get_keycode() == Key::META) { return; } @@ -1898,7 +1898,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } // Handle Unicode (if no modifiers active). Tab has a value of 0x09. - if (allow_unicode_handling && editable && (k->get_unicode() >= 32 || k->get_keycode() == KEY_TAB)) { + if (allow_unicode_handling && editable && (k->get_unicode() >= 32 || k->get_keycode() == Key::TAB)) { handle_unicode_input(k->get_unicode()); accept_event(); return; @@ -3396,7 +3396,7 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos) const { int wrap_index = 0; if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE || _is_hiding_enabled()) { - Point2i f_ofs = get_next_visible_line_index_offset_from(first_vis_line, caret.wrap_ofs, rows + (1 * SGN(rows))); + Point2i f_ofs = get_next_visible_line_index_offset_from(first_vis_line, caret.wrap_ofs, rows + (1 * SIGN(rows))); wrap_index = f_ofs.y; if (rows < 0) { row = first_vis_line - (f_ofs.x - 1); @@ -3471,7 +3471,7 @@ int TextEdit::get_minimap_line_at_pos(const Point2i &p_pos) const { int row = minimap_line + Math::floor(rows); if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE || _is_hiding_enabled()) { - int f_ofs = get_next_visible_line_index_offset_from(minimap_line, caret.wrap_ofs, rows + (1 * SGN(rows))).x - 1; + int f_ofs = get_next_visible_line_index_offset_from(minimap_line, caret.wrap_ofs, rows + (1 * SIGN(rows))).x - 1; if (rows < 0) { row = minimap_line - f_ofs; } else { @@ -3697,8 +3697,10 @@ void TextEdit::set_selection_mode(SelectionMode p_mode, int p_line, int p_column if (p_line >= 0) { ERR_FAIL_INDEX(p_line, text.size()); selection.selecting_line = p_line; + selection.selecting_column = CLAMP(selection.selecting_column, 0, text[selection.selecting_line].length()); } if (p_column >= 0) { + ERR_FAIL_INDEX(selection.selecting_line, text.size()); ERR_FAIL_INDEX(p_column, text[selection.selecting_line].length()); selection.selecting_column = p_column; } @@ -5249,21 +5251,21 @@ void TextEdit::_generate_context_menu() { // Reorganize context menu. menu->clear(); if (editable) { - menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : 0); + menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_cut") : Key::NONE); } - menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : 0); + menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : Key::NONE); if (editable) { - menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : 0); + menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : Key::NONE); } menu->add_separator(); if (is_selecting_enabled()) { - menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : 0); + menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : Key::NONE); } if (editable) { menu->add_item(RTR("Clear"), MENU_CLEAR); menu->add_separator(); - menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : 0); - menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0); + menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_undo") : Key::NONE); + menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : Key::NONE); } menu->add_separator(); menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu"); @@ -5284,25 +5286,25 @@ void TextEdit::_generate_context_menu() { } } -int TextEdit::_get_menu_action_accelerator(const String &p_action) { +Key TextEdit::_get_menu_action_accelerator(const String &p_action) { const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(p_action); if (!events) { - return 0; + return Key::NONE; } // Use first event in the list for the accelerator. const List<Ref<InputEvent>>::Element *first_event = events->front(); if (!first_event) { - return 0; + return Key::NONE; } const Ref<InputEventKey> event = first_event->get(); if (event.is_null()) { - return 0; + return Key::NONE; } // Use physical keycode if non-zero - if (event->get_physical_keycode() != 0) { + if (event->get_physical_keycode() != Key::NONE) { return event->get_physical_keycode_with_modifiers(); } else { return event->get_keycode_with_modifiers(); @@ -5457,10 +5459,10 @@ int TextEdit::_get_column_x_offset_for_line(int p_char, int p_line) const { /* Selection */ void TextEdit::_click_selection_held() { - // Warning: is_mouse_button_pressed(MOUSE_BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD + // Warning: is_mouse_button_pressed(MouseButton::LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD // and MODE_LINE. However, moving the mouse triggers _gui_input, which calls these functions too, so that's not a huge problem. // I'm unsure if there's an actual fix that doesn't have a ton of side effects. - if (Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && selection.selecting_mode != SelectionMode::SELECTION_MODE_NONE) { + if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT) && selection.selecting_mode != SelectionMode::SELECTION_MODE_NONE) { switch (selection.selecting_mode) { case SelectionMode::SELECTION_MODE_POINTER: { _update_selection_mode_pointer(); @@ -5760,7 +5762,7 @@ double TextEdit::_get_v_scroll_offset() const { } void TextEdit::_scroll_up(real_t p_delta) { - if (scrolling && smooth_scroll_enabled && SGN(target_v_scroll - v_scroll->get_value()) != SGN(-p_delta)) { + if (scrolling && smooth_scroll_enabled && SIGN(target_v_scroll - v_scroll->get_value()) != SIGN(-p_delta)) { scrolling = false; minimap_clicked = false; } @@ -5787,7 +5789,7 @@ void TextEdit::_scroll_up(real_t p_delta) { } void TextEdit::_scroll_down(real_t p_delta) { - if (scrolling && smooth_scroll_enabled && SGN(target_v_scroll - v_scroll->get_value()) != SGN(p_delta)) { + if (scrolling && smooth_scroll_enabled && SIGN(target_v_scroll - v_scroll->get_value()) != SIGN(p_delta)) { scrolling = false; minimap_clicked = false; } diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 23f80efce0..1a7dc851b5 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -280,7 +280,7 @@ private: PopupMenu *menu_ctl = nullptr; void _generate_context_menu(); - int _get_menu_action_accelerator(const String &p_action); + Key _get_menu_action_accelerator(const String &p_action); /* Versioning */ struct TextOperation { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 1245a37c4d..27e617bdd0 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1955,7 +1955,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (p_item->cells[i].custom_button) { if (cache.hover_item == p_item && cache.hover_cell == i) { - if (Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) { + if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) { draw_style_box(cache.custom_button_pressed, ir); } else { draw_style_box(cache.custom_button_hover, ir); @@ -2256,7 +2256,7 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) { } void Tree::_range_click_timeout() { - if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) { + if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) { Point2 pos = get_local_mouse_position() - cache.bg->get_offset(); if (show_column_titles) { pos.y -= _get_title_button_height(); @@ -2284,7 +2284,7 @@ void Tree::_range_click_timeout() { propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case) blocked++; - propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, false, root, MOUSE_BUTTON_LEFT, mb); + propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, false, root, MouseButton::LEFT, mb); blocked--; if (range_click_timer->is_one_shot()) { @@ -2307,7 +2307,7 @@ void Tree::_range_click_timeout() { } } -int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) { +int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, MouseButton p_button, const Ref<InputEventWithModifiers> &p_mod) { int item_h = compute_item_height(p_item) + cache.vseparation; bool skip = (p_item == root && hide_root); @@ -2427,7 +2427,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int col_width -= w + cache.button_margin; } - if (p_button == MOUSE_BUTTON_LEFT || (p_button == MOUSE_BUTTON_RIGHT && allow_rmb_select)) { + if (p_button == MouseButton::LEFT || (p_button == MouseButton::RIGHT && allow_rmb_select)) { /* process selection */ if (p_double_click && (!c.editable || c.mode == TreeItem::CELL_MODE_CUSTOM || c.mode == TreeItem::CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/)) { //it's confusing for check @@ -2439,10 +2439,10 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int } if (select_mode == SELECT_MULTI && p_mod->is_command_pressed() && c.selectable) { - if (!c.selected || p_button == MOUSE_BUTTON_RIGHT) { + if (!c.selected || p_button == MouseButton::RIGHT) { p_item->select(col); emit_signal(SNAME("multi_selected"), p_item, col, true); - if (p_button == MOUSE_BUTTON_RIGHT) { + if (p_button == MouseButton::RIGHT) { emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position()); } @@ -2459,21 +2459,21 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int bool inrange = false; select_single_item(p_item, root, col, selected_item, &inrange); - if (p_button == MOUSE_BUTTON_RIGHT) { + if (p_button == MouseButton::RIGHT) { emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position()); } } else { int icount = _count_selected_items(root); - if (select_mode == SELECT_MULTI && icount > 1 && p_button != MOUSE_BUTTON_RIGHT) { + if (select_mode == SELECT_MULTI && icount > 1 && p_button != MouseButton::RIGHT) { single_select_defer = p_item; single_select_defer_column = col; } else { - if (p_button != MOUSE_BUTTON_RIGHT || !c.selected) { + if (p_button != MouseButton::RIGHT || !c.selected) { select_single_item(p_item, root, col); } - if (p_button == MOUSE_BUTTON_RIGHT) { + if (p_button == MouseButton::RIGHT) { emit_signal(SNAME("item_rmb_selected"), get_local_mouse_position()); } } @@ -2543,7 +2543,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int /* touching the combo */ bool up = p_pos.y < (item_h / 2); - if (p_button == MOUSE_BUTTON_LEFT) { + if (p_button == MouseButton::LEFT) { if (range_click_timer->get_time_left() == 0) { range_item_last = p_item; range_up_last = up; @@ -2560,13 +2560,13 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int item_edited(col, p_item); - } else if (p_button == MOUSE_BUTTON_RIGHT) { + } else if (p_button == MouseButton::RIGHT) { p_item->set_range(col, (up ? c.max : c.min)); item_edited(col, p_item); - } else if (p_button == MOUSE_BUTTON_WHEEL_UP) { + } else if (p_button == MouseButton::WHEEL_UP) { p_item->set_range(col, c.val + c.step); item_edited(col, p_item); - } else if (p_button == MOUSE_BUTTON_WHEEL_DOWN) { + } else if (p_button == MouseButton::WHEEL_DOWN) { p_item->set_range(col, c.val - c.step); item_edited(col, p_item); } @@ -2599,14 +2599,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int } if (!p_item->cells[col].custom_button || !on_arrow) { - item_edited(col, p_item, p_button == MOUSE_BUTTON_LEFT); + item_edited(col, p_item, p_button == MouseButton::LEFT); } click_handled = true; return -1; } break; }; - if (!bring_up_editor || p_button != MOUSE_BUTTON_LEFT) { + if (!bring_up_editor || p_button != MouseButton::LEFT) { return -1; } @@ -2646,7 +2646,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int item_h += child_h; } } - if (p_item == root && p_button == MOUSE_BUTTON_RIGHT) { + if (p_item == root && p_button == MouseButton::RIGHT) { emit_signal(SNAME("empty_rmb"), get_local_mouse_position()); } } @@ -2655,9 +2655,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int } void Tree::_text_editor_modal_close() { - if (Input::get_singleton()->is_key_pressed(KEY_ESCAPE) || - Input::get_singleton()->is_key_pressed(KEY_KP_ENTER) || - Input::get_singleton()->is_key_pressed(KEY_ENTER)) { + if (Input::get_singleton()->is_key_pressed(Key::ESCAPE) || + Input::get_singleton()->is_key_pressed(Key::KP_ENTER) || + Input::get_singleton()->is_key_pressed(Key::ENTER)) { return; } @@ -3048,7 +3048,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { return; } else { - if (k->get_keycode() != KEY_SHIFT) { + if (k->get_keycode() != Key::SHIFT) { last_keypress = 0; } } @@ -3164,7 +3164,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { } else { const TreeItem::Cell &c = popup_edited_item->cells[popup_edited_item_col]; float diff_y = -mm->get_relative().y; - diff_y = Math::pow(ABS(diff_y), 1.8f) * SGN(diff_y); + diff_y = Math::pow(ABS(diff_y), 1.8f) * SIGN(diff_y); diff_y *= 0.1; range_drag_base = CLAMP(range_drag_base + c.step * diff_y, c.min, c.max); popup_edited_item->set_range(popup_edited_item_col, range_drag_base); @@ -3189,7 +3189,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { bool rtl = is_layout_rtl(); if (!b->is_pressed()) { - if (b->get_button_index() == MOUSE_BUTTON_LEFT) { + if (b->get_button_index() == MouseButton::LEFT) { Point2 pos = b->get_position(); if (rtl) { pos.x = get_size().width - pos.x; @@ -3270,8 +3270,8 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { } switch (b->get_button_index()) { - case MOUSE_BUTTON_RIGHT: - case MOUSE_BUTTON_LEFT: { + case MouseButton::RIGHT: + case MouseButton::LEFT: { Ref<StyleBox> bg = cache.bg; Point2 pos = b->get_position(); @@ -3284,7 +3284,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { pos.y -= _get_title_button_height(); if (pos.y < 0) { - if (b->get_button_index() == MOUSE_BUTTON_LEFT) { + if (b->get_button_index() == MouseButton::LEFT) { pos.x += cache.offset.x; int len = 0; for (int i = 0; i < columns.size(); i++) { @@ -3302,7 +3302,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { } } if (!root || (!root->get_first_child() && hide_root)) { - if (b->get_button_index() == MOUSE_BUTTON_RIGHT && allow_rmb_select) { + if (b->get_button_index() == MouseButton::RIGHT && allow_rmb_select) { emit_signal(SNAME("empty_tree_rmb_selected"), get_local_mouse_position()); } break; @@ -3329,7 +3329,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { } } - if (b->get_button_index() == MOUSE_BUTTON_RIGHT) { + if (b->get_button_index() == MouseButton::RIGHT) { break; } @@ -3352,7 +3352,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { set_physics_process_internal(true); } - if (b->get_button_index() == MOUSE_BUTTON_LEFT) { + if (b->get_button_index() == MouseButton::LEFT) { if (get_item_at_position(b->get_position()) == nullptr && !b->is_shift_pressed() && !b->is_ctrl_pressed() && !b->is_command_pressed()) { emit_signal(SNAME("nothing_selected")); } @@ -3365,7 +3365,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { } } break; - case MOUSE_BUTTON_WHEEL_UP: { + case MouseButton::WHEEL_UP: { double prev_value = v_scroll->get_value(); v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); if (v_scroll->get_value() != prev_value) { @@ -3373,7 +3373,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { } } break; - case MOUSE_BUTTON_WHEEL_DOWN: { + case MouseButton::WHEEL_DOWN: { double prev_value = v_scroll->get_value(); v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8); if (v_scroll->get_value() != prev_value) { diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 6ca9458e9b..2e4e1bd364 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -462,7 +462,7 @@ private: void draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color); int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item); void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = nullptr, bool *r_in_range = nullptr, bool p_force_deselect = false); - int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod); + int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, MouseButton p_button, const Ref<InputEventWithModifiers> &p_mod); void _text_editor_submit(String p_text); void _text_editor_modal_close(); void value_editor_changed(double p_value); diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 5065684839..22e3c3bf24 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -274,6 +274,7 @@ void CanvasItem::_exit_canvas() { void CanvasItem::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { + ERR_FAIL_COND(!is_inside_tree()); _update_texture_filter_changed(false); _update_texture_repeat_changed(false); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 3be73af861..44420fcc31 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2889,7 +2889,7 @@ void Node::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "process_priority"), "set_process_priority", "get_process_priority"); ADD_GROUP("Editor Description", "editor_"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "set_editor_description", "get_editor_description"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT), "set_editor_description", "get_editor_description"); GDVIRTUAL_BIND(_process, "delta"); GDVIRTUAL_BIND(_physics_process, "delta"); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 31e8c20991..1ecc3c762a 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -584,9 +584,9 @@ void Viewport::_process_picking() { physics_last_mouse_state.meta = mb->is_meta_pressed(); if (mb->is_pressed()) { - physics_last_mouse_state.mouse_mask |= (MouseButton)(1 << (mb->get_button_index() - 1)); + physics_last_mouse_state.mouse_mask |= mouse_button_to_mask(mb->get_button_index()); } else { - physics_last_mouse_state.mouse_mask &= (MouseButton) ~(1 << (mb->get_button_index() - 1)); + physics_last_mouse_state.mouse_mask &= ~mouse_button_to_mask(mb->get_button_index()); // If touch mouse raised, assume we don't know last mouse pos until new events come if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) { @@ -696,7 +696,7 @@ void Viewport::_process_picking() { if (co && camera_3d) { _collision_object_3d_input_event(co, camera_3d, ev, Vector3(), Vector3(), 0); captured = true; - if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) { + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { physics_object_capture = ObjectID(); } @@ -712,7 +712,7 @@ void Viewport::_process_picking() { if (ObjectDB::get_instance(last_id) && last_object) { // Good, exists. _collision_object_3d_input_event(last_object, camera_3d, ev, result.position, result.normal, result.shape); - if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { + if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { physics_object_capture = last_id; } } @@ -740,7 +740,7 @@ void Viewport::_process_picking() { last_object = co; last_id = result.collider_id; new_collider = last_id; - if (co->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { + if (co->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { physics_object_capture = last_id; } } @@ -1259,10 +1259,10 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu Ref<InputEventMouseButton> mb = p_input; bool cant_stop_me_now = (mb.is_valid() && - (mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN || - mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP || - mb->get_button_index() == MOUSE_BUTTON_WHEEL_LEFT || - mb->get_button_index() == MOUSE_BUTTON_WHEEL_RIGHT)); + (mb->get_button_index() == MouseButton::WHEEL_DOWN || + mb->get_button_index() == MouseButton::WHEEL_UP || + mb->get_button_index() == MouseButton::WHEEL_LEFT || + mb->get_button_index() == MouseButton::WHEEL_RIGHT)); Ref<InputEventPanGesture> pn = p_input; cant_stop_me_now = pn.is_valid() || cant_stop_me_now; @@ -1445,21 +1445,21 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { gui.last_mouse_pos = mpos; if (mb->is_pressed()) { Size2 pos = mpos; - if (gui.mouse_focus_mask) { + if (gui.mouse_focus_mask != MouseButton::NONE) { // Do not steal mouse focus and stuff while a focus mask exists. - gui.mouse_focus_mask |= 1 << (mb->get_button_index() - 1); // Add the button to the mask. + gui.mouse_focus_mask |= mouse_button_to_mask(mb->get_button_index()); } else { gui.mouse_focus = gui_find_control(pos); gui.last_mouse_focus = gui.mouse_focus; if (!gui.mouse_focus) { - gui.mouse_focus_mask = 0; + gui.mouse_focus_mask = MouseButton::NONE; return; } - gui.mouse_focus_mask = 1 << (mb->get_button_index() - 1); + gui.mouse_focus_mask = mouse_button_to_mask(mb->get_button_index()); - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb->get_button_index() == MouseButton::LEFT) { gui.drag_accum = Vector2(); gui.drag_attempted = false; } @@ -1482,7 +1482,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } #endif - if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { // Assign focus. + if (mb->get_button_index() == MouseButton::LEFT) { // Assign focus. CanvasItem *ci = gui.mouse_focus; while (ci) { Control *control = Object::cast_to<Control>(ci); @@ -1513,7 +1513,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { set_input_as_handled(); - if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) { // Alternate drop use (when using force_drag(), as proposed by #5342). if (gui.mouse_focus) { _gui_drop(gui.mouse_focus, pos, false); @@ -1533,7 +1533,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { _gui_cancel_tooltip(); } else { - if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == MouseButton::LEFT) { if (gui.drag_mouse_over) { _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false); } @@ -1551,7 +1551,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { // Change mouse accordingly. } - gui.mouse_focus_mask &= ~(1 << (mb->get_button_index() - 1)); // Remove from mask. + gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask. if (!gui.mouse_focus) { // Release event is only sent if a mouse focus (previously pressed button) exists. @@ -1570,7 +1570,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { // Disable mouse focus if needed before calling input, // this makes popups on mouse press event work better, // as the release will never be received otherwise. - if (gui.mouse_focus_mask == 0) { + if (gui.mouse_focus_mask == MouseButton::NONE) { gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; } @@ -1590,7 +1590,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { over = gui_find_control(mpos); } - if (gui.mouse_focus_mask == 0 && over != gui.mouse_over) { + if (gui.mouse_focus_mask == MouseButton::NONE && over != gui.mouse_over) { if (gui.mouse_over) { _gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT); } @@ -1618,7 +1618,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Control *over = nullptr; // Drag & drop. - if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if (!gui.drag_attempted && gui.mouse_focus && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { gui.drag_accum += mm->get_relative(); float len = gui.drag_accum.length(); if (len > 10) { @@ -1632,7 +1632,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL) { gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; - gui.mouse_focus_mask = 0; + gui.mouse_focus_mask = MouseButton::NONE; break; } else { Control *drag_preview = _gui_get_drag_preview(); @@ -1701,7 +1701,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { mm->set_speed(speed); mm->set_relative(rel); - if (mm->get_button_mask() == 0) { + if (mm->get_button_mask() == MouseButton::NONE) { // Nothing pressed. bool can_tooltip = true; @@ -1754,7 +1754,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Control *c = over; Vector2 cpos = pos; while (c) { - if (gui.mouse_focus_mask != 0 || c->has_point(cpos)) { + if (gui.mouse_focus_mask != MouseButton::NONE || c->has_point(cpos)) { cursor_shape = c->get_cursor_shape(cpos); } else { cursor_shape = Control::CURSOR_ARROW; @@ -1867,7 +1867,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse(); gui.drag_mouse_over_pos = localizer.xform(viewport_pos); - if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if ((mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true); if (!can_drop) { @@ -2108,7 +2108,7 @@ void Viewport::_gui_remove_control(Control *p_control) { if (gui.mouse_focus == p_control) { gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; - gui.mouse_focus_mask = 0; + gui.mouse_focus_mask = MouseButton::NONE; } if (gui.last_mouse_focus == p_control) { gui.last_mouse_focus = nullptr; @@ -2178,13 +2178,13 @@ void Viewport::_gui_accept_event() { void Viewport::_drop_mouse_focus() { Control *c = gui.mouse_focus; - int mask = gui.mouse_focus_mask; + MouseButton mask = gui.mouse_focus_mask; gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; - gui.mouse_focus_mask = 0; + gui.mouse_focus_mask = MouseButton::NONE; for (int i = 0; i < 3; i++) { - if (mask & (1 << i)) { + if ((int)mask & (1 << i)) { Ref<InputEventMouseButton> mb; mb.instantiate(); mb->set_position(c->get_local_mouse_position()); @@ -2293,11 +2293,11 @@ void Viewport::_post_gui_grab_click_focus() { return; } - int mask = gui.mouse_focus_mask; + MouseButton mask = gui.mouse_focus_mask; Point2 click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos); for (int i = 0; i < 3; i++) { - if (mask & (1 << i)) { + if ((int)mask & (1 << i)) { Ref<InputEventMouseButton> mb; mb.instantiate(); @@ -2315,7 +2315,7 @@ void Viewport::_post_gui_grab_click_focus() { click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos); for (int i = 0; i < 3; i++) { - if (mask & (1 << i)) { + if ((int)mask & (1 << i)) { Ref<InputEventMouseButton> mb; mb.instantiate(); @@ -2412,7 +2412,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND_V(gui.subwindow_focused == nullptr, false); Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) { if (gui.subwindow_drag_close_rect.has_point(mb->get_position())) { // Close window. @@ -2537,7 +2537,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; // If the event is a mouse button, we need to check whether another window was clicked. - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { bool click_on_window = false; for (int i = gui.sub_windows.size() - 1; i >= 0; i--) { SubWindow &sw = gui.sub_windows.write[i]; @@ -3041,7 +3041,7 @@ void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) { gui.mouse_focus = nullptr; gui.forced_mouse_focus = false; - gui.mouse_focus_mask = 0; + gui.mouse_focus_mask = MouseButton::NONE; } } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 1f19ff04c9..5320aea02a 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -244,7 +244,7 @@ private: bool control = false; bool shift = false; bool meta = false; - int mouse_mask = 0; + MouseButton mouse_mask = MouseButton::NONE; } physics_last_mouse_state; @@ -327,7 +327,7 @@ private: Control *mouse_focus = nullptr; Control *last_mouse_focus = nullptr; Control *mouse_click_grabber = nullptr; - int mouse_focus_mask = 0; + MouseButton mouse_focus_mask = MouseButton::NONE; Control *key_focus = nullptr; Control *mouse_over = nullptr; Control *drag_mouse_over = nullptr; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index a0f62c853f..5da5a183f7 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -895,7 +895,7 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) { if (EngineDebugger::is_active()) { //quit from game window using F8 Ref<InputEventKey> k = p_ev; - if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_F8) { + if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::F8) { EngineDebugger::get_singleton()->send_message("request_quit", Array()); } } diff --git a/scene/property_utils.cpp b/scene/property_utils.cpp index 79821b8399..7df601492b 100644 --- a/scene/property_utils.cpp +++ b/scene/property_utils.cpp @@ -32,9 +32,12 @@ #include "core/config/engine.h" #include "core/templates/local_vector.h" -#include "editor/editor_node.h" #include "scene/resources/packed_scene.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#endif // TOOLS_ENABLED + bool PropertyUtils::is_property_value_different(const Variant &p_a, const Variant &p_b) { if (p_a.get_type() == Variant::FLOAT && p_b.get_type() == Variant::FLOAT) { //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index c193850a78..056ace5e4e 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -63,6 +63,7 @@ #include "scene/2d/position_2d.h" #include "scene/2d/ray_cast_2d.h" #include "scene/2d/remote_transform_2d.h" +#include "scene/2d/shape_cast_2d.h" #include "scene/2d/skeleton_2d.h" #include "scene/2d/sprite_2d.h" #include "scene/2d/tile_map.h" @@ -628,6 +629,7 @@ void register_scene_types() { GDREGISTER_CLASS(VisualShaderNodeParticleSphereEmitter); GDREGISTER_CLASS(VisualShaderNodeParticleBoxEmitter); GDREGISTER_CLASS(VisualShaderNodeParticleRingEmitter); + GDREGISTER_CLASS(VisualShaderNodeParticleMeshEmitter); GDREGISTER_CLASS(VisualShaderNodeParticleMultiplyByAxisAngle); GDREGISTER_CLASS(VisualShaderNodeParticleConeVelocity); GDREGISTER_CLASS(VisualShaderNodeParticleRandomness); @@ -665,6 +667,7 @@ void register_scene_types() { GDREGISTER_CLASS(CollisionShape2D); GDREGISTER_CLASS(CollisionPolygon2D); GDREGISTER_CLASS(RayCast2D); + GDREGISTER_CLASS(ShapeCast2D); GDREGISTER_CLASS(VisibleOnScreenNotifier2D); GDREGISTER_CLASS(VisibleOnScreenEnabler2D); GDREGISTER_CLASS(Polygon2D); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 71d2774335..29aca6b321 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -317,7 +317,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { Vector<real_t> times = d["times"]; Vector<real_t> values = d["points"]; - ERR_FAIL_COND_V(times.size() * 5 != values.size(), false); + ERR_FAIL_COND_V(times.size() * 6 != values.size(), false); if (times.size()) { int valcount = times.size(); @@ -330,11 +330,12 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { for (int i = 0; i < valcount; i++) { bt->values.write[i].time = rt[i]; bt->values.write[i].transition = 0; //unused in bezier - bt->values.write[i].value.value = rv[i * 5 + 0]; - bt->values.write[i].value.in_handle.x = rv[i * 5 + 1]; - bt->values.write[i].value.in_handle.y = rv[i * 5 + 2]; - bt->values.write[i].value.out_handle.x = rv[i * 5 + 3]; - bt->values.write[i].value.out_handle.y = rv[i * 5 + 4]; + bt->values.write[i].value.value = rv[i * 6 + 0]; + bt->values.write[i].value.in_handle.x = rv[i * 6 + 1]; + bt->values.write[i].value.in_handle.y = rv[i * 6 + 2]; + bt->values.write[i].value.out_handle.x = rv[i * 6 + 3]; + bt->values.write[i].value.out_handle.y = rv[i * 6 + 4]; + bt->values.write[i].value.handle_mode = (HandleMode)rv[i * 6 + 5]; } } @@ -449,8 +450,8 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { return true; } else if (name == "length") { r_ret = length; - } else if (name == "loop") { - r_ret = loop; + } else if (name == "loop_mode") { + r_ret = loop_mode; } else if (name == "step") { r_ret = step; } else if (name.begins_with("tracks/")) { @@ -698,7 +699,7 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { int kk = bt->values.size(); key_times.resize(kk); - key_points.resize(kk * 5); + key_points.resize(kk * 6); real_t *wti = key_times.ptrw(); real_t *wpo = key_points.ptrw(); @@ -709,11 +710,12 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { for (int i = 0; i < kk; i++) { wti[idx] = vls[i].time; - wpo[idx * 5 + 0] = vls[i].value.value; - wpo[idx * 5 + 1] = vls[i].value.in_handle.x; - wpo[idx * 5 + 2] = vls[i].value.in_handle.y; - wpo[idx * 5 + 3] = vls[i].value.out_handle.x; - wpo[idx * 5 + 4] = vls[i].value.out_handle.y; + wpo[idx * 6 + 0] = vls[i].value.value; + wpo[idx * 6 + 1] = vls[i].value.in_handle.x; + wpo[idx * 6 + 2] = vls[i].value.in_handle.y; + wpo[idx * 6 + 3] = vls[i].value.out_handle.x; + wpo[idx * 6 + 4] = vls[i].value.out_handle.y; + wpo[idx * 6 + 5] = (double)vls[i].value.handle_mode; idx++; } @@ -1623,7 +1625,7 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke BezierTrack *bt = static_cast<BezierTrack *>(t); Array arr = p_key; - ERR_FAIL_COND(arr.size() != 5); + ERR_FAIL_COND(arr.size() != 6); TKey<BezierKey> k; k.time = p_time; @@ -1632,6 +1634,7 @@ void Animation::track_insert_key(int p_track, double p_time, const Variant &p_ke k.value.in_handle.y = arr[2]; k.value.out_handle.x = arr[3]; k.value.out_handle.y = arr[4]; + k.value.handle_mode = (HandleMode) int(arr[5]); _insert(p_time, bt->values, k); } break; @@ -1770,12 +1773,13 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const { ERR_FAIL_INDEX_V(p_key_idx, bt->values.size(), Variant()); Array arr; - arr.resize(5); + arr.resize(6); arr[0] = bt->values[p_key_idx].value.value; arr[1] = bt->values[p_key_idx].value.in_handle.x; arr[2] = bt->values[p_key_idx].value.in_handle.y; arr[3] = bt->values[p_key_idx].value.out_handle.x; arr[4] = bt->values[p_key_idx].value.out_handle.y; + arr[5] = (double)bt->values[p_key_idx].value.handle_mode; return arr; } break; @@ -2144,13 +2148,14 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p ERR_FAIL_INDEX(p_key_idx, bt->values.size()); Array arr = p_value; - ERR_FAIL_COND(arr.size() != 5); + ERR_FAIL_COND(arr.size() != 6); bt->values.write[p_key_idx].value.value = arr[0]; bt->values.write[p_key_idx].value.in_handle.x = arr[1]; bt->values.write[p_key_idx].value.in_handle.y = arr[2]; bt->values.write[p_key_idx].value.out_handle.x = arr[3]; bt->values.write[p_key_idx].value.out_handle.y = arr[4]; + bt->values.write[p_key_idx].value.handle_mode = (HandleMode) int(arr[5]); } break; case TYPE_AUDIO: { @@ -2231,7 +2236,7 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, real_t p_tr } template <class K> -int Animation::_find(const Vector<K> &p_keys, double p_time) const { +int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward) const { int len = p_keys.size(); if (len == 0) { return -2; @@ -2261,8 +2266,14 @@ int Animation::_find(const Vector<K> &p_keys, double p_time) const { } } - if (keys[middle].time > p_time) { - middle--; + if (!p_backward) { + if (keys[middle].time > p_time) { + middle--; + } + } else { + if (keys[middle].time < p_time) { + middle++; + } } return middle; @@ -2385,7 +2396,7 @@ real_t Animation::_cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, c } template <class T> -T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const { +T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward) const { int len = _find(p_keys, length) + 1; // try to find last key (there may be more past the end) if (len <= 0) { @@ -2403,7 +2414,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol return p_keys[0].value; } - int idx = _find(p_keys, p_time); + int idx = _find(p_keys, p_time, p_backward); ERR_FAIL_COND_V(idx == -2, T()); @@ -2412,24 +2423,42 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol real_t c = 0.0; // prepare for all cases of interpolation - if (loop && p_loop_wrap) { + if ((loop_mode == LOOP_LINEAR || loop_mode == LOOP_PINGPONG) && p_loop_wrap) { // loop - if (idx >= 0) { - if ((idx + 1) < len) { - next = idx + 1; - real_t delta = p_keys[next].time - p_keys[idx].time; - real_t from = p_time - p_keys[idx].time; - - if (Math::is_zero_approx(delta)) { - c = 0; + if (!p_backward) { + // no backward + if (idx >= 0) { + if (idx < len - 1) { + next = idx + 1; + real_t delta = p_keys[next].time - p_keys[idx].time; + real_t from = p_time - p_keys[idx].time; + + if (Math::is_zero_approx(delta)) { + c = 0; + } else { + c = from / delta; + } } else { - c = from / delta; - } + next = 0; + real_t delta = (length - p_keys[idx].time) + p_keys[next].time; + real_t from = p_time - p_keys[idx].time; + if (Math::is_zero_approx(delta)) { + c = 0; + } else { + c = from / delta; + } + } } else { + // on loop, behind first key + idx = len - 1; next = 0; - real_t delta = (length - p_keys[idx].time) + p_keys[next].time; - real_t from = p_time - p_keys[idx].time; + real_t endtime = (length - p_keys[idx].time); + if (endtime < 0) { // may be keys past the end + endtime = 0; + } + real_t delta = endtime + p_keys[next].time; + real_t from = endtime + p_time; if (Math::is_zero_approx(delta)) { c = 0; @@ -2437,49 +2466,81 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol c = from / delta; } } - } else { - // on loop, behind first key - idx = len - 1; - next = 0; - real_t endtime = (length - p_keys[idx].time); - if (endtime < 0) { // may be keys past the end - endtime = 0; - } - real_t delta = endtime + p_keys[next].time; - real_t from = endtime + p_time; - - if (Math::is_zero_approx(delta)) { - c = 0; + // backward + if (idx <= len - 1) { + if (idx > 0) { + next = idx - 1; + real_t delta = (length - p_keys[next].time) - (length - p_keys[idx].time); + real_t from = (length - p_time) - (length - p_keys[idx].time); + + if (Math::is_zero_approx(delta)) + c = 0; + else + c = from / delta; + } else { + next = len - 1; + real_t delta = p_keys[idx].time + (length - p_keys[next].time); + real_t from = (length - p_time) - (length - p_keys[idx].time); + + if (Math::is_zero_approx(delta)) + c = 0; + else + c = from / delta; + } } else { - c = from / delta; + // on loop, in front of last key + idx = 0; + next = len - 1; + real_t endtime = p_keys[idx].time; + if (endtime > length) // may be keys past the end + endtime = length; + real_t delta = p_keys[next].time - endtime; + real_t from = p_time - endtime; + + if (Math::is_zero_approx(delta)) + c = 0; + else + c = from / delta; } } - } else { // no loop - - if (idx >= 0) { - if ((idx + 1) < len) { - next = idx + 1; - real_t delta = p_keys[next].time - p_keys[idx].time; - real_t from = p_time - p_keys[idx].time; - - if (Math::is_zero_approx(delta)) { - c = 0; + if (!p_backward) { + if (idx >= 0) { + if (idx < len - 1) { + next = idx + 1; + real_t delta = p_keys[next].time - p_keys[idx].time; + real_t from = p_time - p_keys[idx].time; + + if (Math::is_zero_approx(delta)) { + c = 0; + } else { + c = from / delta; + } } else { - c = from / delta; + next = idx; } - } else { - next = idx; + idx = next = 0; } - } else { - // only allow extending first key to anim start if looping - if (loop) { - idx = next = 0; + if (idx <= len - 1) { + if (idx > 0) { + next = idx - 1; + real_t delta = (length - p_keys[next].time) - (length - p_keys[idx].time); + real_t from = (length - p_time) - (length - p_keys[idx].time); + + if (Math::is_zero_approx(delta)) { + c = 0; + } else { + c = from / delta; + } + + } else { + next = idx; + } } else { - result = false; + idx = next = len - 1; } } } @@ -2583,7 +2644,7 @@ void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, doub } } -void Animation::value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const { +void Animation::value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_VALUE); @@ -2597,30 +2658,50 @@ void Animation::value_track_get_key_indices(int p_track, double p_time, double p SWAP(from_time, to_time); } - if (loop) { - from_time = Math::fposmod(from_time, length); - to_time = Math::fposmod(to_time, length); + switch (loop_mode) { + case LOOP_NONE: { + if (from_time < 0) { + from_time = 0; + } + if (from_time > length) { + from_time = length; + } - if (from_time > to_time) { - // handle loop by splitting - _value_track_get_key_indices_in_range(vt, from_time, length, p_indices); - _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices); - return; - } - } else { - if (from_time < 0) { - from_time = 0; - } - if (from_time > length) { - from_time = length; - } + if (to_time < 0) { + to_time = 0; + } + if (to_time > length) { + to_time = length; + } + } break; + case LOOP_LINEAR: { + from_time = Math::fposmod(from_time, length); + to_time = Math::fposmod(to_time, length); - if (to_time < 0) { - to_time = 0; - } - if (to_time > length) { - to_time = length; - } + if (from_time > to_time) { + // handle loop by splitting + _value_track_get_key_indices_in_range(vt, from_time, length, p_indices); + _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices); + return; + } + } break; + case LOOP_PINGPONG: { + from_time = Math::pingpong(from_time, length); + to_time = Math::pingpong(to_time, length); + + if (p_pingponged == -1) { + // handle loop by splitting + _value_track_get_key_indices_in_range(vt, 0, from_time, p_indices); + _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices); + return; + } + if (p_pingponged == 1) { + // handle loop by splitting + _value_track_get_key_indices_in_range(vt, from_time, length, p_indices); + _value_track_get_key_indices_in_range(vt, to_time, length, p_indices); + return; + } + } break; } _value_track_get_key_indices_in_range(vt, from_time, to_time, p_indices); @@ -2679,7 +2760,7 @@ void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double } } -void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices) const { +void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const { ERR_FAIL_INDEX(p_track, tracks.size()); const Track *t = tracks[p_track]; @@ -2690,114 +2771,255 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl SWAP(from_time, to_time); } - if (loop) { - if (from_time > length || from_time < 0) { - from_time = Math::fposmod(from_time, length); - } - - if (to_time > length || to_time < 0) { - to_time = Math::fposmod(to_time, length); - } - - if (from_time > to_time) { - // handle loop by splitting - - switch (t->type) { - case TYPE_POSITION_3D: { - const PositionTrack *tt = static_cast<const PositionTrack *>(t); - if (tt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices); - _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices); - - } else { - _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices); - _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices); - } - - } break; - case TYPE_ROTATION_3D: { - const RotationTrack *rt = static_cast<const RotationTrack *>(t); - if (rt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices); - _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices); + switch (loop_mode) { + case LOOP_NONE: { + if (from_time < 0) { + from_time = 0; + } + if (from_time > length) { + from_time = length; + } - } else { - _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices); - _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices); - } + if (to_time < 0) { + to_time = 0; + } + if (to_time > length) { + to_time = length; + } + } break; + case LOOP_LINEAR: { + if (from_time > length || from_time < 0) { + from_time = Math::fposmod(from_time, length); + } + if (to_time > length || to_time < 0) { + to_time = Math::fposmod(to_time, length); + } - } break; - case TYPE_SCALE_3D: { - const ScaleTrack *st = static_cast<const ScaleTrack *>(t); - if (st->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices); - _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices); + if (from_time > to_time) { + // handle loop by splitting + switch (t->type) { + case TYPE_POSITION_3D: { + const PositionTrack *tt = static_cast<const PositionTrack *>(t); + if (tt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices); + _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices); + } + } break; + case TYPE_ROTATION_3D: { + const RotationTrack *rt = static_cast<const RotationTrack *>(t); + if (rt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices); + _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices); + } + } break; + case TYPE_SCALE_3D: { + const ScaleTrack *st = static_cast<const ScaleTrack *>(t); + if (st->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(st->scales, from_time, length, p_indices); + _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices); + } + } break; + case TYPE_BLEND_SHAPE: { + const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); + if (bst->compressed_track >= 0) { + _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices); + _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices); + } + } break; + case TYPE_VALUE: { + const ValueTrack *vt = static_cast<const ValueTrack *>(t); + _track_get_key_indices_in_range(vt->values, from_time, length, p_indices); + _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices); + } break; + case TYPE_METHOD: { + const MethodTrack *mt = static_cast<const MethodTrack *>(t); + _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices); + _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices); + } break; + case TYPE_BEZIER: { + const BezierTrack *bz = static_cast<const BezierTrack *>(t); + _track_get_key_indices_in_range(bz->values, from_time, length, p_indices); + _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices); + } break; + case TYPE_AUDIO: { + const AudioTrack *ad = static_cast<const AudioTrack *>(t); + _track_get_key_indices_in_range(ad->values, from_time, length, p_indices); + _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices); + } break; + case TYPE_ANIMATION: { + const AnimationTrack *an = static_cast<const AnimationTrack *>(t); + _track_get_key_indices_in_range(an->values, from_time, length, p_indices); + _track_get_key_indices_in_range(an->values, 0, to_time, p_indices); + } break; + } + return; + } + } break; + case LOOP_PINGPONG: { + if (from_time > length || from_time < 0) { + from_time = Math::pingpong(from_time, length); + } + if (to_time > length || to_time < 0) { + to_time = Math::pingpong(to_time, length); + } - } else { - _track_get_key_indices_in_range(st->scales, from_time, length, p_indices); - _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices); + if ((int)Math::floor(abs(p_delta) / length) % 2 == 0) { + if (p_pingponged == -1) { + // handle loop by splitting + switch (t->type) { + case TYPE_POSITION_3D: { + const PositionTrack *tt = static_cast<const PositionTrack *>(t); + if (tt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, from_time, p_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(tt->positions, 0, from_time, p_indices); + _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices); + } + } break; + case TYPE_ROTATION_3D: { + const RotationTrack *rt = static_cast<const RotationTrack *>(t); + if (rt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, from_time, p_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(rt->rotations, 0, from_time, p_indices); + _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices); + } + } break; + case TYPE_SCALE_3D: { + const ScaleTrack *st = static_cast<const ScaleTrack *>(t); + if (st->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, from_time, p_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(st->scales, 0, from_time, p_indices); + _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices); + } + } break; + case TYPE_BLEND_SHAPE: { + const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); + if (bst->compressed_track >= 0) { + _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, from_time, p_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(bst->blend_shapes, 0, from_time, p_indices); + _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices); + } + } break; + case TYPE_VALUE: { + const ValueTrack *vt = static_cast<const ValueTrack *>(t); + _track_get_key_indices_in_range(vt->values, 0, from_time, p_indices); + _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices); + } break; + case TYPE_METHOD: { + const MethodTrack *mt = static_cast<const MethodTrack *>(t); + _track_get_key_indices_in_range(mt->methods, 0, from_time, p_indices); + _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices); + } break; + case TYPE_BEZIER: { + const BezierTrack *bz = static_cast<const BezierTrack *>(t); + _track_get_key_indices_in_range(bz->values, 0, from_time, p_indices); + _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices); + } break; + case TYPE_AUDIO: { + const AudioTrack *ad = static_cast<const AudioTrack *>(t); + _track_get_key_indices_in_range(ad->values, 0, from_time, p_indices); + _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices); + } break; + case TYPE_ANIMATION: { + const AnimationTrack *an = static_cast<const AnimationTrack *>(t); + _track_get_key_indices_in_range(an->values, 0, from_time, p_indices); + _track_get_key_indices_in_range(an->values, 0, to_time, p_indices); + } break; } - - } break; - case TYPE_BLEND_SHAPE: { - const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); - if (bst->compressed_track >= 0) { - _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices); - _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices); - - } else { - _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices); - _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices); + return; + } + if (p_pingponged == 1) { + // handle loop by splitting + switch (t->type) { + case TYPE_POSITION_3D: { + const PositionTrack *tt = static_cast<const PositionTrack *>(t); + if (tt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, length, p_indices); + } else { + _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices); + _track_get_key_indices_in_range(tt->positions, to_time, length, p_indices); + } + } break; + case TYPE_ROTATION_3D: { + const RotationTrack *rt = static_cast<const RotationTrack *>(t); + if (rt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, length, p_indices); + } else { + _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices); + _track_get_key_indices_in_range(rt->rotations, to_time, length, p_indices); + } + } break; + case TYPE_SCALE_3D: { + const ScaleTrack *st = static_cast<const ScaleTrack *>(t); + if (st->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, length, p_indices); + } else { + _track_get_key_indices_in_range(st->scales, from_time, length, p_indices); + _track_get_key_indices_in_range(st->scales, to_time, length, p_indices); + } + } break; + case TYPE_BLEND_SHAPE: { + const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); + if (bst->compressed_track >= 0) { + _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, length, p_indices); + } else { + _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices); + _track_get_key_indices_in_range(bst->blend_shapes, to_time, length, p_indices); + } + } break; + case TYPE_VALUE: { + const ValueTrack *vt = static_cast<const ValueTrack *>(t); + _track_get_key_indices_in_range(vt->values, from_time, length, p_indices); + _track_get_key_indices_in_range(vt->values, to_time, length, p_indices); + } break; + case TYPE_METHOD: { + const MethodTrack *mt = static_cast<const MethodTrack *>(t); + _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices); + _track_get_key_indices_in_range(mt->methods, to_time, length, p_indices); + } break; + case TYPE_BEZIER: { + const BezierTrack *bz = static_cast<const BezierTrack *>(t); + _track_get_key_indices_in_range(bz->values, from_time, length, p_indices); + _track_get_key_indices_in_range(bz->values, to_time, length, p_indices); + } break; + case TYPE_AUDIO: { + const AudioTrack *ad = static_cast<const AudioTrack *>(t); + _track_get_key_indices_in_range(ad->values, from_time, length, p_indices); + _track_get_key_indices_in_range(ad->values, to_time, length, p_indices); + } break; + case TYPE_ANIMATION: { + const AnimationTrack *an = static_cast<const AnimationTrack *>(t); + _track_get_key_indices_in_range(an->values, from_time, length, p_indices); + _track_get_key_indices_in_range(an->values, to_time, length, p_indices); + } break; } - - } break; - case TYPE_VALUE: { - const ValueTrack *vt = static_cast<const ValueTrack *>(t); - _track_get_key_indices_in_range(vt->values, from_time, length, p_indices); - _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices); - - } break; - case TYPE_METHOD: { - const MethodTrack *mt = static_cast<const MethodTrack *>(t); - _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices); - _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices); - - } break; - case TYPE_BEZIER: { - const BezierTrack *bz = static_cast<const BezierTrack *>(t); - _track_get_key_indices_in_range(bz->values, from_time, length, p_indices); - _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices); - - } break; - case TYPE_AUDIO: { - const AudioTrack *ad = static_cast<const AudioTrack *>(t); - _track_get_key_indices_in_range(ad->values, from_time, length, p_indices); - _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices); - - } break; - case TYPE_ANIMATION: { - const AnimationTrack *an = static_cast<const AnimationTrack *>(t); - _track_get_key_indices_in_range(an->values, from_time, length, p_indices); - _track_get_key_indices_in_range(an->values, 0, to_time, p_indices); - - } break; + return; + } } - return; - } - } else { - if (from_time < 0) { - from_time = 0; - } - if (from_time > length) { - from_time = length; - } - - if (to_time < 0) { - to_time = 0; - } - if (to_time > length) { - to_time = length; - } + } break; } switch (t->type) { @@ -2808,7 +3030,6 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl } else { _track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices); } - } break; case TYPE_ROTATION_3D: { const RotationTrack *rt = static_cast<const RotationTrack *>(t); @@ -2817,7 +3038,6 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl } else { _track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices); } - } break; case TYPE_SCALE_3D: { const ScaleTrack *st = static_cast<const ScaleTrack *>(t); @@ -2826,7 +3046,6 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl } else { _track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices); } - } break; case TYPE_BLEND_SHAPE: { const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); @@ -2835,32 +3054,26 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl } else { _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices); } - } break; case TYPE_VALUE: { const ValueTrack *vt = static_cast<const ValueTrack *>(t); _track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices); - } break; case TYPE_METHOD: { const MethodTrack *mt = static_cast<const MethodTrack *>(t); _track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices); - } break; case TYPE_BEZIER: { const BezierTrack *bz = static_cast<const BezierTrack *>(t); _track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices); - } break; case TYPE_AUDIO: { const AudioTrack *ad = static_cast<const AudioTrack *>(t); _track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices); - } break; case TYPE_ANIMATION: { const AnimationTrack *an = static_cast<const AnimationTrack *>(t); _track_get_key_indices_in_range(an->values, from_time, to_time, p_indices); - } break; } } @@ -2898,7 +3111,7 @@ void Animation::_method_track_get_key_indices_in_range(const MethodTrack *mt, do } } -void Animation::method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const { +void Animation::method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_METHOD); @@ -2912,35 +3125,58 @@ void Animation::method_track_get_key_indices(int p_track, double p_time, double SWAP(from_time, to_time); } - if (loop) { - if (from_time > length || from_time < 0) { - from_time = Math::fposmod(from_time, length); - } + switch (loop_mode) { + case LOOP_NONE: { + if (from_time < 0) { + from_time = 0; + } + if (from_time > length) { + from_time = length; + } - if (to_time > length || to_time < 0) { - to_time = Math::fposmod(to_time, length); - } + if (to_time < 0) { + to_time = 0; + } + if (to_time > length) { + to_time = length; + } + } break; + case LOOP_LINEAR: { + if (from_time > length || from_time < 0) { + from_time = Math::fposmod(from_time, length); + } + if (to_time > length || to_time < 0) { + to_time = Math::fposmod(to_time, length); + } - if (from_time > to_time) { - // handle loop by splitting - _method_track_get_key_indices_in_range(mt, from_time, length, p_indices); - _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices); - return; - } - } else { - if (from_time < 0) { - from_time = 0; - } - if (from_time > length) { - from_time = length; - } + if (from_time > to_time) { + // handle loop by splitting + _method_track_get_key_indices_in_range(mt, from_time, length, p_indices); + _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices); + return; + } + } break; + case LOOP_PINGPONG: { + if (from_time > length || from_time < 0) { + from_time = Math::pingpong(from_time, length); + } + if (to_time > length || to_time < 0) { + to_time = Math::pingpong(to_time, length); + } - if (to_time < 0) { - to_time = 0; - } - if (to_time > length) { - to_time = length; - } + if (p_pingponged == -1) { + _method_track_get_key_indices_in_range(mt, 0, from_time, p_indices); + _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices); + return; + } + if (p_pingponged == 1) { + _method_track_get_key_indices_in_range(mt, from_time, length, p_indices); + _method_track_get_key_indices_in_range(mt, to_time, length, p_indices); + return; + } + } break; + default: + break; } _method_track_get_key_indices_in_range(mt, from_time, to_time, p_indices); @@ -2972,7 +3208,7 @@ StringName Animation::method_track_get_name(int p_track, int p_key_idx) const { return pm->methods[p_key_idx].method; } -int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle) { +int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const HandleMode p_handle_mode) { ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_BEZIER, -1); @@ -2990,6 +3226,7 @@ int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_valu if (k.value.out_handle.x < 0) { k.value.out_handle.x = 0; } + k.value.handle_mode = p_handle_mode; int key = _insert(p_time, bt->values, k); @@ -2998,6 +3235,30 @@ int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_valu return key; } +void Animation::bezier_track_set_key_handle_mode(int p_track, int p_index, HandleMode p_mode, double p_balanced_value_time_ratio) { + ERR_FAIL_INDEX(p_track, tracks.size()); + Track *t = tracks[p_track]; + ERR_FAIL_COND(t->type != TYPE_BEZIER); + + BezierTrack *bt = static_cast<BezierTrack *>(t); + + ERR_FAIL_INDEX(p_index, bt->values.size()); + + bt->values.write[p_index].value.handle_mode = p_mode; + + if (p_mode == HANDLE_MODE_BALANCED) { + Transform2D xform; + xform.set_scale(Vector2(1.0, 1.0 / p_balanced_value_time_ratio)); + + Vector2 vec_in = xform.xform(bt->values[p_index].value.in_handle); + Vector2 vec_out = xform.xform(bt->values[p_index].value.out_handle); + + bt->values.write[p_index].value.in_handle = xform.affine_inverse().xform(-vec_out.normalized() * vec_in.length()); + } + + emit_changed(); +} + void Animation::bezier_track_set_key_value(int p_track, int p_index, real_t p_value) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; @@ -3011,7 +3272,7 @@ void Animation::bezier_track_set_key_value(int p_track, int p_index, real_t p_va emit_changed(); } -void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle) { +void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle, double p_balanced_value_time_ratio) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_BEZIER); @@ -3020,14 +3281,26 @@ void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const V ERR_FAIL_INDEX(p_index, bt->values.size()); - bt->values.write[p_index].value.in_handle = p_handle; - if (bt->values[p_index].value.in_handle.x > 0) { - bt->values.write[p_index].value.in_handle.x = 0; + Vector2 in_handle = p_handle; + if (in_handle.x > 0) { + in_handle.x = 0; + } + bt->values.write[p_index].value.in_handle = in_handle; + + if (bt->values[p_index].value.handle_mode == HANDLE_MODE_BALANCED) { + Transform2D xform; + xform.set_scale(Vector2(1.0, 1.0 / p_balanced_value_time_ratio)); + + Vector2 vec_out = xform.xform(bt->values[p_index].value.out_handle); + Vector2 vec_in = xform.xform(in_handle); + + bt->values.write[p_index].value.out_handle = xform.affine_inverse().xform(-vec_in.normalized() * vec_out.length()); } + emit_changed(); } -void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle) { +void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle, double p_balanced_value_time_ratio) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_BEZIER); @@ -3036,10 +3309,22 @@ void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const ERR_FAIL_INDEX(p_index, bt->values.size()); - bt->values.write[p_index].value.out_handle = p_handle; - if (bt->values[p_index].value.out_handle.x < 0) { - bt->values.write[p_index].value.out_handle.x = 0; + Vector2 out_handle = p_handle; + if (out_handle.x < 0) { + out_handle.x = 0; + } + bt->values.write[p_index].value.out_handle = out_handle; + + if (bt->values[p_index].value.handle_mode == HANDLE_MODE_BALANCED) { + Transform2D xform; + xform.set_scale(Vector2(1.0, 1.0 / p_balanced_value_time_ratio)); + + Vector2 vec_in = xform.xform(bt->values[p_index].value.in_handle); + Vector2 vec_out = xform.xform(out_handle); + + bt->values.write[p_index].value.in_handle = xform.affine_inverse().xform(-vec_out.normalized() * vec_in.length()); } + emit_changed(); } @@ -3055,6 +3340,18 @@ real_t Animation::bezier_track_get_key_value(int p_track, int p_index) const { return bt->values[p_index].value.value; } +int Animation::bezier_track_get_key_handle_mode(int p_track, int p_index) const { + ERR_FAIL_INDEX_V(p_track, tracks.size(), 0); + Track *t = tracks[p_track]; + ERR_FAIL_COND_V(t->type != TYPE_BEZIER, 0); + + BezierTrack *bt = static_cast<BezierTrack *>(t); + + ERR_FAIL_INDEX_V(p_index, bt->values.size(), 0); + + return bt->values[p_index].value.handle_mode; +} + Vector2 Animation::bezier_track_get_key_in_handle(int p_track, int p_index) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), Vector2()); Track *t = tracks[p_track]; @@ -3326,13 +3623,13 @@ real_t Animation::get_length() const { return length; } -void Animation::set_loop(bool p_enabled) { - loop = p_enabled; +void Animation::set_loop_mode(Animation::LoopMode p_loop_mode) { + loop_mode = p_loop_mode; emit_changed(); } -bool Animation::has_loop() const { - return loop; +Animation::LoopMode Animation::get_loop_mode() const { + return loop_mode; } void Animation::track_set_imported(int p_track, bool p_imported) { @@ -3487,11 +3784,11 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("method_track_get_name", "track_idx", "key_idx"), &Animation::method_track_get_name); ClassDB::bind_method(D_METHOD("method_track_get_params", "track_idx", "key_idx"), &Animation::method_track_get_params); - ClassDB::bind_method(D_METHOD("bezier_track_insert_key", "track_idx", "time", "value", "in_handle", "out_handle"), &Animation::bezier_track_insert_key, DEFVAL(Vector2()), DEFVAL(Vector2())); + ClassDB::bind_method(D_METHOD("bezier_track_insert_key", "track_idx", "time", "value", "in_handle", "out_handle", "handle_mode"), &Animation::bezier_track_insert_key, DEFVAL(Vector2()), DEFVAL(Vector2()), DEFVAL(Animation::HandleMode::HANDLE_MODE_BALANCED)); ClassDB::bind_method(D_METHOD("bezier_track_set_key_value", "track_idx", "key_idx", "value"), &Animation::bezier_track_set_key_value); - ClassDB::bind_method(D_METHOD("bezier_track_set_key_in_handle", "track_idx", "key_idx", "in_handle"), &Animation::bezier_track_set_key_in_handle); - ClassDB::bind_method(D_METHOD("bezier_track_set_key_out_handle", "track_idx", "key_idx", "out_handle"), &Animation::bezier_track_set_key_out_handle); + ClassDB::bind_method(D_METHOD("bezier_track_set_key_in_handle", "track_idx", "key_idx", "in_handle", "balanced_value_time_ratio"), &Animation::bezier_track_set_key_in_handle, DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("bezier_track_set_key_out_handle", "track_idx", "key_idx", "out_handle", "balanced_value_time_ratio"), &Animation::bezier_track_set_key_out_handle, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("bezier_track_get_key_value", "track_idx", "key_idx"), &Animation::bezier_track_get_key_value); ClassDB::bind_method(D_METHOD("bezier_track_get_key_in_handle", "track_idx", "key_idx"), &Animation::bezier_track_get_key_in_handle); @@ -3507,6 +3804,9 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("audio_track_get_key_start_offset", "track_idx", "key_idx"), &Animation::audio_track_get_key_start_offset); ClassDB::bind_method(D_METHOD("audio_track_get_key_end_offset", "track_idx", "key_idx"), &Animation::audio_track_get_key_end_offset); + ClassDB::bind_method(D_METHOD("bezier_track_set_key_handle_mode", "track_idx", "key_idx", "key_handle_mode", "balanced_value_time_ratio"), &Animation::bezier_track_set_key_handle_mode, DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("bezier_track_get_key_handle_mode", "track_idx", "key_idx"), &Animation::bezier_track_get_key_handle_mode); + ClassDB::bind_method(D_METHOD("animation_track_insert_key", "track_idx", "time", "animation"), &Animation::animation_track_insert_key); ClassDB::bind_method(D_METHOD("animation_track_set_key_animation", "track_idx", "key_idx", "animation"), &Animation::animation_track_set_key_animation); ClassDB::bind_method(D_METHOD("animation_track_get_key_animation", "track_idx", "key_idx"), &Animation::animation_track_get_key_animation); @@ -3514,8 +3814,8 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("set_length", "time_sec"), &Animation::set_length); ClassDB::bind_method(D_METHOD("get_length"), &Animation::get_length); - ClassDB::bind_method(D_METHOD("set_loop", "enabled"), &Animation::set_loop); - ClassDB::bind_method(D_METHOD("has_loop"), &Animation::has_loop); + ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &Animation::set_loop_mode); + ClassDB::bind_method(D_METHOD("get_loop_mode"), &Animation::get_loop_mode); ClassDB::bind_method(D_METHOD("set_step", "size_sec"), &Animation::set_step); ClassDB::bind_method(D_METHOD("get_step"), &Animation::get_step); @@ -3526,7 +3826,7 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("compress", "page_size", "fps", "split_tolerance"), &Animation::compress, DEFVAL(8192), DEFVAL(120), DEFVAL(4.0)); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001"), "set_length", "get_length"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode"), "set_loop_mode", "get_loop_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step"); ADD_SIGNAL(MethodInfo("tracks_changed")); @@ -3549,6 +3849,13 @@ void Animation::_bind_methods() { BIND_ENUM_CONSTANT(UPDATE_DISCRETE); BIND_ENUM_CONSTANT(UPDATE_TRIGGER); BIND_ENUM_CONSTANT(UPDATE_CAPTURE); + + BIND_ENUM_CONSTANT(LOOP_NONE); + BIND_ENUM_CONSTANT(LOOP_LINEAR); + BIND_ENUM_CONSTANT(LOOP_PINGPONG); + + BIND_ENUM_CONSTANT(HANDLE_MODE_FREE); + BIND_ENUM_CONSTANT(HANDLE_MODE_BALANCED); } void Animation::clear() { @@ -3556,7 +3863,7 @@ void Animation::clear() { memdelete(tracks[i]); } tracks.clear(); - loop = false; + loop_mode = LOOP_NONE; length = 1; compression.enabled = false; compression.bounds.clear(); diff --git a/scene/resources/animation.h b/scene/resources/animation.h index ee07fb19d3..8e4287e4fb 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -64,7 +64,17 @@ public: UPDATE_DISCRETE, UPDATE_TRIGGER, UPDATE_CAPTURE, + }; + + enum LoopMode { + LOOP_NONE, + LOOP_LINEAR, + LOOP_PINGPONG, + }; + enum HandleMode { + HANDLE_MODE_FREE, + HANDLE_MODE_BALANCED, }; private: @@ -152,10 +162,10 @@ private: }; /* BEZIER TRACK */ - struct BezierKey { Vector2 in_handle; //relative (x always <0) Vector2 out_handle; //relative (x always >0) + HandleMode handle_mode = HANDLE_MODE_BALANCED; real_t value = 0.0; }; @@ -208,7 +218,8 @@ private: int _insert(double p_time, T &p_keys, const V &p_value); template <class K> - inline int _find(const Vector<K> &p_keys, double p_time) const; + + inline int _find(const Vector<K> &p_keys, double p_time, bool p_backward = false) const; _FORCE_INLINE_ Vector3 _interpolate(const Vector3 &p_a, const Vector3 &p_b, real_t p_c) const; _FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, real_t p_c) const; @@ -221,7 +232,7 @@ private: _FORCE_INLINE_ real_t _cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const; template <class T> - _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const; + _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const; template <class T> _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const; @@ -231,7 +242,8 @@ private: double length = 1.0; real_t step = 0.1; - bool loop = false; + LoopMode loop_mode = LOOP_NONE; + int pingponged = 0; /* Animation compression page format (version 1): * @@ -412,11 +424,13 @@ public: void track_set_interpolation_type(int p_track, InterpolationType p_interp); InterpolationType track_get_interpolation_type(int p_track) const; - int bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle); + int bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const HandleMode p_handle_mode = HandleMode::HANDLE_MODE_BALANCED); + void bezier_track_set_key_handle_mode(int p_track, int p_index, HandleMode p_mode, double p_balanced_value_time_ratio = 1.0); void bezier_track_set_key_value(int p_track, int p_index, real_t p_value); - void bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle); - void bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle); + void bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle, double p_balanced_value_time_ratio = 1.0); + void bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle, double p_balanced_value_time_ratio = 1.0); real_t bezier_track_get_key_value(int p_track, int p_index) const; + int bezier_track_get_key_handle_mode(int p_track, int p_index) const; Vector2 bezier_track_get_key_in_handle(int p_track, int p_index) const; Vector2 bezier_track_get_key_out_handle(int p_track, int p_index) const; @@ -438,23 +452,23 @@ public: bool track_get_interpolation_loop_wrap(int p_track) const; Variant value_track_interpolate(int p_track, double p_time) const; - void value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const; + void value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const; void value_track_set_update_mode(int p_track, UpdateMode p_mode); UpdateMode value_track_get_update_mode(int p_track) const; - void method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const; + void method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const; Vector<Variant> method_track_get_params(int p_track, int p_key_idx) const; StringName method_track_get_name(int p_track, int p_key_idx) const; void copy_track(int p_track, Ref<Animation> p_to_animation); - void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices) const; + void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const; void set_length(real_t p_length); real_t get_length() const; - void set_loop(bool p_enabled); - bool has_loop() const; + void set_loop_mode(LoopMode p_loop_mode); + LoopMode get_loop_mode() const; void set_step(real_t p_step); real_t get_step() const; @@ -471,5 +485,7 @@ public: VARIANT_ENUM_CAST(Animation::TrackType); VARIANT_ENUM_CAST(Animation::InterpolationType); VARIANT_ENUM_CAST(Animation::UpdateMode); +VARIANT_ENUM_CAST(Animation::HandleMode); +VARIANT_ENUM_CAST(Animation::LoopMode); #endif diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index 5cfc4a9d40..d3fab802c5 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -299,7 +299,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int if (loop_format != AudioStreamSample::LOOP_DISABLED && offset < loop_begin_fp) { /* loopstart reached */ - if (loop_format == AudioStreamSample::LOOP_PING_PONG) { + if (loop_format == AudioStreamSample::LOOP_PINGPONG) { /* bounce ping pong */ offset = loop_begin_fp + (loop_begin_fp - offset); increment = -increment; @@ -320,7 +320,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int if (loop_format != AudioStreamSample::LOOP_DISABLED && offset >= loop_end_fp) { /* loopend reached */ - if (loop_format == AudioStreamSample::LOOP_PING_PONG) { + if (loop_format == AudioStreamSample::LOOP_PINGPONG) { /* bounce ping pong */ offset = loop_end_fp - (offset - loop_end_fp); increment = -increment; @@ -650,7 +650,7 @@ void AudioStreamSample::_bind_methods() { BIND_ENUM_CONSTANT(LOOP_DISABLED); BIND_ENUM_CONSTANT(LOOP_FORWARD); - BIND_ENUM_CONSTANT(LOOP_PING_PONG); + BIND_ENUM_CONSTANT(LOOP_PINGPONG); BIND_ENUM_CONSTANT(LOOP_BACKWARD); } diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h index 24198e3c98..0eb34be9bf 100644 --- a/scene/resources/audio_stream_sample.h +++ b/scene/resources/audio_stream_sample.h @@ -92,7 +92,7 @@ public: enum LoopMode { LOOP_DISABLED, LOOP_FORWARD, - LOOP_PING_PONG, + LOOP_PINGPONG, LOOP_BACKWARD }; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 9fab5791d6..84fa07e4f4 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -97,28 +97,36 @@ RID Shader::get_rid() const { return shader; } -void Shader::set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture) { +void Shader::set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture, int p_index) { if (p_texture.is_valid()) { - default_textures[p_param] = p_texture; - RS::get_singleton()->shader_set_default_texture_param(shader, p_param, p_texture->get_rid()); + if (!default_textures.has(p_param)) { + default_textures[p_param] = Map<int, Ref<Texture2D>>(); + } + default_textures[p_param][p_index] = p_texture; + RS::get_singleton()->shader_set_default_texture_param(shader, p_param, p_texture->get_rid(), p_index); } else { - default_textures.erase(p_param); - RS::get_singleton()->shader_set_default_texture_param(shader, p_param, RID()); + if (default_textures.has(p_param) && default_textures[p_param].has(p_index)) { + default_textures[p_param].erase(p_index); + + if (default_textures[p_param].is_empty()) { + default_textures.erase(p_param); + } + } + RS::get_singleton()->shader_set_default_texture_param(shader, p_param, RID(), p_index); } emit_changed(); } -Ref<Texture2D> Shader::get_default_texture_param(const StringName &p_param) const { - if (default_textures.has(p_param)) { - return default_textures[p_param]; - } else { - return Ref<Texture2D>(); +Ref<Texture2D> Shader::get_default_texture_param(const StringName &p_param, int p_index) const { + if (default_textures.has(p_param) && default_textures[p_param].has(p_index)) { + return default_textures[p_param][p_index]; } + return Ref<Texture2D>(); } void Shader::get_default_texture_param_list(List<StringName> *r_textures) const { - for (const KeyValue<StringName, Ref<Texture2D>> &E : default_textures) { + for (const KeyValue<StringName, Map<int, Ref<Texture2D>>> &E : default_textures) { r_textures->push_back(E.key); } } @@ -140,8 +148,8 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("set_code", "code"), &Shader::set_code); ClassDB::bind_method(D_METHOD("get_code"), &Shader::get_code); - ClassDB::bind_method(D_METHOD("set_default_texture_param", "param", "texture"), &Shader::set_default_texture_param); - ClassDB::bind_method(D_METHOD("get_default_texture_param", "param"), &Shader::get_default_texture_param); + ClassDB::bind_method(D_METHOD("set_default_texture_param", "param", "texture", "index"), &Shader::set_default_texture_param, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("get_default_texture_param", "param", "index"), &Shader::get_default_texture_param, DEFVAL(0)); ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param); diff --git a/scene/resources/shader.h b/scene/resources/shader.h index c0dc07b403..c688dc1bab 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -59,7 +59,7 @@ private: // conversion fast and save memory. mutable bool params_cache_dirty = true; mutable Map<StringName, StringName> params_cache; //map a shader param to a material param.. - Map<StringName, Ref<Texture2D>> default_textures; + Map<StringName, Map<int, Ref<Texture2D>>> default_textures; virtual void _update_shader() const; //used for visual shader protected: @@ -75,8 +75,8 @@ public: void get_param_list(List<PropertyInfo> *p_params) const; bool has_param(const StringName &p_param) const; - void set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture); - Ref<Texture2D> get_default_texture_param(const StringName &p_param) const; + void set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture, int p_index = 0); + Ref<Texture2D> get_default_texture_param(const StringName &p_param, int p_index = 0) const; void get_default_texture_param_list(List<StringName> *r_textures) const; virtual bool is_text_shader() const; diff --git a/scene/resources/skeleton_modification_stack_2d.cpp b/scene/resources/skeleton_modification_stack_2d.cpp index db9fe62b4d..25c3e9d2ef 100644 --- a/scene/resources/skeleton_modification_stack_2d.cpp +++ b/scene/resources/skeleton_modification_stack_2d.cpp @@ -195,6 +195,7 @@ void SkeletonModificationStack2D::set_modification(int p_mod_idx, Ref<SkeletonMo } void SkeletonModificationStack2D::set_modification_count(int p_count) { + ERR_FAIL_COND_MSG(p_count < 0, "Modification count cannot be less than zero."); modifications.resize(p_count); notify_property_list_changed(); diff --git a/scene/resources/skeleton_modification_stack_3d.cpp b/scene/resources/skeleton_modification_stack_3d.cpp index c03210cf48..301811f0b6 100644 --- a/scene/resources/skeleton_modification_stack_3d.cpp +++ b/scene/resources/skeleton_modification_stack_3d.cpp @@ -149,6 +149,7 @@ void SkeletonModificationStack3D::set_modification(int p_mod_idx, Ref<SkeletonMo } void SkeletonModificationStack3D::set_modification_count(int p_count) { + ERR_FAIL_COND_MSG(p_count < 0, "Modification count cannot be less than zero."); modifications.resize(p_count); notify_property_list_changed(); } diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 5256803d56..8c92445338 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -3359,6 +3359,10 @@ void TileSetAtlasSource::set_tile_set(const TileSet *p_tile_set) { } } +const TileSet *TileSetAtlasSource::get_tile_set() const { + return tile_set; +} + void TileSetAtlasSource::notify_tile_data_properties_should_change() { // Set the TileSet on all TileData. for (KeyValue<Vector2i, TileAlternativesData> &E_tile : tiles) { @@ -3522,9 +3526,18 @@ void TileSetAtlasSource::reset_state() { } void TileSetAtlasSource::set_texture(Ref<Texture2D> p_texture) { + if (texture.is_valid()) { + texture->disconnect(SNAME("changed"), callable_mp(this, &TileSetAtlasSource::_queue_update_padded_texture)); + } + texture = p_texture; + if (texture.is_valid()) { + texture->connect(SNAME("changed"), callable_mp(this, &TileSetAtlasSource::_queue_update_padded_texture)); + } + _clear_tiles_outside_texture(); + _queue_update_padded_texture(); emit_changed(); } @@ -3541,8 +3554,10 @@ void TileSetAtlasSource::set_margins(Vector2i p_margins) { } _clear_tiles_outside_texture(); + _queue_update_padded_texture(); emit_changed(); } + Vector2i TileSetAtlasSource::get_margins() const { return margins; } @@ -3556,8 +3571,10 @@ void TileSetAtlasSource::set_separation(Vector2i p_separation) { } _clear_tiles_outside_texture(); + _queue_update_padded_texture(); emit_changed(); } + Vector2i TileSetAtlasSource::get_separation() const { return separation; } @@ -3571,12 +3588,27 @@ void TileSetAtlasSource::set_texture_region_size(Vector2i p_tile_size) { } _clear_tiles_outside_texture(); + _queue_update_padded_texture(); emit_changed(); } + Vector2i TileSetAtlasSource::get_texture_region_size() const { return texture_region_size; } +void TileSetAtlasSource::set_use_texture_padding(bool p_use_padding) { + if (use_texture_padding == p_use_padding) { + return; + } + use_texture_padding = p_use_padding; + _queue_update_padded_texture(); + emit_changed(); +} + +bool TileSetAtlasSource::get_use_texture_padding() const { + return use_texture_padding; +} + Vector2i TileSetAtlasSource::get_atlas_grid_size() const { Ref<Texture2D> texture = get_texture(); if (!texture.is_valid()) { @@ -3835,6 +3867,7 @@ void TileSetAtlasSource::create_tile(const Vector2i p_atlas_coords, const Vector tiles_ids.sort(); _create_coords_mapping_cache(p_atlas_coords); + _queue_update_padded_texture(); emit_signal(SNAME("changed")); } @@ -3855,6 +3888,8 @@ void TileSetAtlasSource::remove_tile(Vector2i p_atlas_coords) { tiles_ids.erase(p_atlas_coords); tiles_ids.sort(); + _queue_update_padded_texture(); + emit_signal(SNAME("changed")); } @@ -3883,6 +3918,7 @@ void TileSetAtlasSource::set_tile_animation_columns(const Vector2i p_atlas_coord tiles[p_atlas_coords].animation_columns = p_frame_columns; _create_coords_mapping_cache(p_atlas_coords); + _queue_update_padded_texture(); emit_signal(SNAME("changed")); } @@ -3905,6 +3941,7 @@ void TileSetAtlasSource::set_tile_animation_separation(const Vector2i p_atlas_co tiles[p_atlas_coords].animation_separation = p_separation; _create_coords_mapping_cache(p_atlas_coords); + _queue_update_padded_texture(); emit_signal(SNAME("changed")); } @@ -3932,19 +3969,24 @@ void TileSetAtlasSource::set_tile_animation_frames_count(const Vector2i p_atlas_ ERR_FAIL_COND_MSG(!tiles.has(p_atlas_coords), vformat("TileSetAtlasSource has no tile at %s.", Vector2i(p_atlas_coords))); ERR_FAIL_COND(p_frames_count < 1); + int old_size = tiles[p_atlas_coords].animation_frames_durations.size(); + if (p_frames_count == old_size) { + return; + } + TileAlternativesData &tad = tiles[p_atlas_coords]; bool room_for_tile = has_room_for_tile(p_atlas_coords, tad.size_in_atlas, tad.animation_columns, tad.animation_separation, p_frames_count, p_atlas_coords); ERR_FAIL_COND_MSG(!room_for_tile, "Cannot set animation columns count, tiles are already present in the space the tile would cover."); _clear_coords_mapping_cache(p_atlas_coords); - int old_size = tiles[p_atlas_coords].animation_frames_durations.size(); tiles[p_atlas_coords].animation_frames_durations.resize(p_frames_count); for (int i = old_size; i < p_frames_count; i++) { tiles[p_atlas_coords].animation_frames_durations[i] = 1.0; } _create_coords_mapping_cache(p_atlas_coords); + _queue_update_padded_texture(); notify_property_list_changed(); @@ -4083,6 +4125,31 @@ Vector2i TileSetAtlasSource::get_tile_effective_texture_offset(Vector2i p_atlas_ return effective_texture_offset; } +// Getters for texture and tile region (padded or not) +Ref<Texture2D> TileSetAtlasSource::get_runtime_texture() const { + if (use_texture_padding) { + return padded_texture; + } else { + return texture; + } +} + +Rect2i TileSetAtlasSource::get_runtime_tile_texture_region(Vector2i p_atlas_coords, int p_frame) const { + ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), Rect2i(), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords))); + ERR_FAIL_INDEX_V(p_frame, (int)tiles[p_atlas_coords].animation_frames_durations.size(), Rect2i()); + + Rect2i src_rect = get_tile_texture_region(p_atlas_coords, p_frame); + if (use_texture_padding) { + const TileAlternativesData &tad = tiles[p_atlas_coords]; + Vector2i frame_coords = p_atlas_coords + (tad.size_in_atlas + tad.animation_separation) * ((tad.animation_columns > 0) ? Vector2i(p_frame % tad.animation_columns, p_frame / tad.animation_columns) : Vector2i(p_frame, 0)); + Vector2i base_pos = frame_coords * (texture_region_size + Vector2i(2, 2)) + Vector2i(1, 1); + + return Rect2i(base_pos, src_rect.size); + } else { + return src_rect; + } +} + void TileSetAtlasSource::move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_new_atlas_coords, Vector2i p_new_size) { ERR_FAIL_COND_MSG(!tiles.has(p_atlas_coords), vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords))); @@ -4113,6 +4180,7 @@ void TileSetAtlasSource::move_tile_in_atlas(Vector2i p_atlas_coords, Vector2i p_ tiles[new_atlas_coords].size_in_atlas = new_size; _create_coords_mapping_cache(new_atlas_coords); + _queue_update_padded_texture(); emit_signal(SNAME("changed")); } @@ -4204,11 +4272,14 @@ void TileSetAtlasSource::_bind_methods() { ClassDB::bind_method(D_METHOD("get_separation"), &TileSetAtlasSource::get_separation); ClassDB::bind_method(D_METHOD("set_texture_region_size", "texture_region_size"), &TileSetAtlasSource::set_texture_region_size); ClassDB::bind_method(D_METHOD("get_texture_region_size"), &TileSetAtlasSource::get_texture_region_size); + ClassDB::bind_method(D_METHOD("set_use_texture_padding", "use_texture_padding"), &TileSetAtlasSource::set_use_texture_padding); + ClassDB::bind_method(D_METHOD("get_use_texture_padding"), &TileSetAtlasSource::get_use_texture_padding); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_NO_EDITOR), "set_texture", "get_texture"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_margins", "get_margins"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_separation", "get_separation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_texture_region_size", "get_texture_region_size"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_texture_padding", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_texture_padding", "get_use_texture_padding"); // Base tiles ClassDB::bind_method(D_METHOD("create_tile", "atlas_coords", "size"), &TileSetAtlasSource::create_tile, DEFVAL(Vector2i(1, 1))); @@ -4243,6 +4314,11 @@ void TileSetAtlasSource::_bind_methods() { // Helpers. ClassDB::bind_method(D_METHOD("get_atlas_grid_size"), &TileSetAtlasSource::get_atlas_grid_size); ClassDB::bind_method(D_METHOD("get_tile_texture_region", "atlas_coords", "frame"), &TileSetAtlasSource::get_tile_texture_region, DEFVAL(0)); + + // Getters for texture and tile region (padded or not) + ClassDB::bind_method(D_METHOD("_update_padded_texture"), &TileSetAtlasSource::_update_padded_texture); + ClassDB::bind_method(D_METHOD("get_runtime_texture"), &TileSetAtlasSource::get_runtime_texture); + ClassDB::bind_method(D_METHOD("get_runtime_tile_texture_region", "atlas_coords", "frame"), &TileSetAtlasSource::get_runtime_tile_texture_region); } TileSetAtlasSource::~TileSetAtlasSource() { @@ -4329,6 +4405,69 @@ void TileSetAtlasSource::_clear_tiles_outside_texture() { } } +void TileSetAtlasSource::_queue_update_padded_texture() { + padded_texture_needs_update = true; + call_deferred("_update_padded_texture"); +} + +void TileSetAtlasSource::_update_padded_texture() { + if (!padded_texture_needs_update) { + return; + } + padded_texture_needs_update = false; + padded_texture = Ref<ImageTexture>(); + + if (!texture.is_valid()) { + return; + } + + if (!use_texture_padding) { + return; + } + + Size2 size = get_atlas_grid_size() * (texture_region_size + Vector2i(2, 2)); + + Ref<Image> src = texture->get_image(); + + Ref<Image> image; + image.instantiate(); + image->create(size.x, size.y, false, Image::FORMAT_RGBA8); + + for (KeyValue<Vector2i, TileAlternativesData> kv : tiles) { + for (int frame = 0; frame < (int)kv.value.animation_frames_durations.size(); frame++) { + // Compute the source rects. + Rect2i src_rect = get_tile_texture_region(kv.key, frame); + + Rect2i top_src_rect = Rect2i(src_rect.position, Vector2i(src_rect.size.x, 1)); + Rect2i bottom_src_rect = Rect2i(src_rect.position + Vector2i(0, src_rect.size.y - 1), Vector2i(src_rect.size.x, 1)); + Rect2i left_src_rect = Rect2i(src_rect.position, Vector2i(1, src_rect.size.y)); + Rect2i right_src_rect = Rect2i(src_rect.position + Vector2i(src_rect.size.x - 1, 0), Vector2i(1, src_rect.size.y)); + + // Copy the tile and the paddings. + Vector2i frame_coords = kv.key + (kv.value.size_in_atlas + kv.value.animation_separation) * ((kv.value.animation_columns > 0) ? Vector2i(frame % kv.value.animation_columns, frame / kv.value.animation_columns) : Vector2i(frame, 0)); + Vector2i base_pos = frame_coords * (texture_region_size + Vector2i(2, 2)) + Vector2i(1, 1); + + image->blit_rect(*src, src_rect, base_pos); + + image->blit_rect(*src, top_src_rect, base_pos + Vector2i(0, -1)); + image->blit_rect(*src, bottom_src_rect, base_pos + Vector2i(0, src_rect.size.y)); + image->blit_rect(*src, left_src_rect, base_pos + Vector2i(-1, 0)); + image->blit_rect(*src, right_src_rect, base_pos + Vector2i(src_rect.size.x, 0)); + + image->set_pixelv(base_pos + Vector2i(-1, -1), src->get_pixelv(src_rect.position)); + image->set_pixelv(base_pos + Vector2i(src_rect.size.x, -1), src->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, 0))); + image->set_pixelv(base_pos + Vector2i(-1, src_rect.size.y), src->get_pixelv(src_rect.position + Vector2i(0, src_rect.size.y - 1))); + image->set_pixelv(base_pos + Vector2i(src_rect.size.x, src_rect.size.y), src->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, src_rect.size.y - 1))); + } + } + + if (!padded_texture.is_valid()) { + padded_texture.instantiate(); + } + padded_texture->create_from_image(image); + emit_changed(); +} + /////////////////////////////// TileSetScenesCollectionSource ////////////////////////////////////// void TileSetScenesCollectionSource::_compute_next_alternative_id() { @@ -4858,6 +4997,9 @@ real_t TileData::get_constant_angular_velocity(int p_layer_id) const { void TileData::set_collision_polygons_count(int p_layer_id, int p_polygons_count) { ERR_FAIL_INDEX(p_layer_id, physics.size()); ERR_FAIL_COND(p_polygons_count < 0); + if (p_polygons_count == physics.write[p_layer_id].polygons.size()) { + return; + } physics.write[p_layer_id].polygons.resize(p_polygons_count); notify_property_list_changed(); emit_signal(SNAME("changed")); @@ -5063,9 +5205,6 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_COND_V(layer_index < 0, false); if (components[1] == "polygon") { Ref<OccluderPolygon2D> polygon = p_value; - if (!polygon.is_valid()) { - return false; - } if (layer_index >= occluders.size()) { if (tile_set) { @@ -5137,9 +5276,6 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_COND_V(layer_index < 0, false); if (components[1] == "polygon") { Ref<NavigationPolygon> polygon = p_value; - if (!polygon.is_valid()) { - return false; - } if (layer_index >= navigation.size()) { if (tile_set) { diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 71559074e7..d2238c26d2 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -603,6 +603,12 @@ private: void _clear_tiles_outside_texture(); + bool use_texture_padding = true; + Ref<ImageTexture> padded_texture; + bool padded_texture_needs_update = false; + void _queue_update_padded_texture(); + void _update_padded_texture(); + protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; @@ -613,6 +619,7 @@ protected: public: // Not exposed. virtual void set_tile_set(const TileSet *p_tile_set) override; + const TileSet *get_tile_set() const; virtual void notify_tile_data_properties_should_change() override; virtual void add_occlusion_layer(int p_index) override; virtual void move_occlusion_layer(int p_from_index, int p_to_pos) override; @@ -644,6 +651,10 @@ public: void set_texture_region_size(Vector2i p_tile_size); Vector2i get_texture_region_size() const; + // Padding. + void set_use_texture_padding(bool p_use_padding); + bool get_use_texture_padding() const; + // Base tiles. void create_tile(const Vector2i p_atlas_coords, const Vector2i p_size = Vector2i(1, 1)); void remove_tile(Vector2i p_atlas_coords); @@ -689,6 +700,10 @@ public: Rect2i get_tile_texture_region(Vector2i p_atlas_coords, int p_frame = 0) const; Vector2i get_tile_effective_texture_offset(Vector2i p_atlas_coords, int p_alternative_tile) const; + // Getters for texture and tile region (padded or not) + Ref<Texture2D> get_runtime_texture() const; + Rect2i get_runtime_tile_texture_region(Vector2i p_atlas_coords, int p_frame = 0) const; + ~TileSetAtlasSource(); }; @@ -766,7 +781,7 @@ private: }; Vector2 linear_velocity; - float angular_velocity = 0.0; + double angular_velocity = 0.0; Vector<PolygonShapeTileData> polygons; }; Vector<PhysicsLayerTileData> physics; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 0aa79b8ceb..0bdc81330e 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -36,6 +36,11 @@ #include "visual_shader_particle_nodes.h" #include "visual_shader_sdf_nodes.h" +String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) { + static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" }; + return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id); +} + bool VisualShaderNode::is_simple_decl() const { return simple_decl; } @@ -354,7 +359,7 @@ String VisualShaderNodeCustom::generate_code(Shader::Mode p_mode, VisualShader:: } String code = " {\n"; String _code; - GDVIRTUAL_CALL(_get_code, input_vars, output_vars, (int)p_mode, (int)p_type, _code); + GDVIRTUAL_CALL(_get_code, input_vars, output_vars, p_mode, p_type, _code); bool nend = _code.ends_with("\n"); _code = _code.insert(0, " "); _code = _code.replace("\n", "\n "); @@ -371,7 +376,7 @@ String VisualShaderNodeCustom::generate_code(Shader::Mode p_mode, VisualShader:: String VisualShaderNodeCustom::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String ret; - if (GDVIRTUAL_CALL(_get_global_code, (int)p_mode, ret)) { + if (GDVIRTUAL_CALL(_get_global_code, p_mode, ret)) { String code = "// " + get_caption() + "\n"; code += ret; code += "\n"; @@ -1829,6 +1834,7 @@ void VisualShader::_update_shader() const { code += " vec3 __vec3_buff2;\n"; code += " float __scalar_buff1;\n"; code += " float __scalar_buff2;\n"; + code += " int __scalar_ibuff;\n"; code += " vec3 __ndiff = normalize(__diff);\n\n"; } if (has_start) { @@ -1956,7 +1962,9 @@ void VisualShader::_update_shader() const { const_cast<VisualShader *>(this)->set_code(final_code); for (int i = 0; i < default_tex_params.size(); i++) { - const_cast<VisualShader *>(this)->set_default_texture_param(default_tex_params[i].name, default_tex_params[i].param); + for (int j = 0; j < default_tex_params[i].params.size(); j++) { + const_cast<VisualShader *>(this)->set_default_texture_param(default_tex_params[i].name, default_tex_params[i].params[j], j); + } } if (previous_code != final_code) { const_cast<VisualShader *>(this)->emit_signal(SNAME("changed")); @@ -3444,7 +3452,7 @@ void VisualShaderNodeGroupBase::add_input_port(int p_id, int p_type, const Strin count++; } - inputs.erase(index, count); + inputs = inputs.left(index) + inputs.substr(index + count); inputs = inputs.insert(index, itos(i)); index += inputs_strings[i].size(); } @@ -3467,7 +3475,7 @@ void VisualShaderNodeGroupBase::remove_input_port(int p_id) { } index += inputs_strings[i].size(); } - inputs.erase(index, count); + inputs = inputs.left(index) + inputs.substr(index + count); inputs_strings = inputs.split(";", false); inputs = inputs.substr(0, index); @@ -3520,7 +3528,7 @@ void VisualShaderNodeGroupBase::add_output_port(int p_id, int p_type, const Stri count++; } - outputs.erase(index, count); + outputs = outputs.left(index) + outputs.substr(index + count); outputs = outputs.insert(index, itos(i)); index += outputs_strings[i].size(); } @@ -3543,7 +3551,7 @@ void VisualShaderNodeGroupBase::remove_output_port(int p_id) { } index += outputs_strings[i].size(); } - outputs.erase(index, count); + outputs = outputs.left(index) + outputs.substr(index + count); outputs_strings = outputs.split(";", false); outputs = outputs.substr(0, index); @@ -3595,8 +3603,7 @@ void VisualShaderNodeGroupBase::set_input_port_type(int p_id, int p_type) { index += inputs_strings[i].size(); } - inputs.erase(index, count); - + inputs = inputs.left(index) + inputs.substr(index + count); inputs = inputs.insert(index, itos(p_type)); _apply_port_changes(); @@ -3631,8 +3638,7 @@ void VisualShaderNodeGroupBase::set_input_port_name(int p_id, const String &p_na index += inputs_strings[i].size(); } - inputs.erase(index, count); - + inputs = inputs.left(index) + inputs.substr(index + count); inputs = inputs.insert(index, p_name); _apply_port_changes(); @@ -3667,7 +3673,7 @@ void VisualShaderNodeGroupBase::set_output_port_type(int p_id, int p_type) { index += output_strings[i].size(); } - outputs.erase(index, count); + outputs = outputs.left(index) + outputs.substr(index + count); outputs = outputs.insert(index, itos(p_type)); @@ -3703,7 +3709,7 @@ void VisualShaderNodeGroupBase::set_output_port_name(int p_id, const String &p_n index += output_strings[i].size(); } - outputs.erase(index, count); + outputs = outputs.left(index) + outputs.substr(index + count); outputs = outputs.insert(index, p_name); diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 7743affba7..5bb9d45f39 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -70,7 +70,7 @@ public: struct DefaultTextureParam { StringName name; - Ref<Texture2D> param; + List<Ref<Texture2D>> params; }; private: @@ -328,8 +328,8 @@ protected: GDVIRTUAL0RC(int, _get_output_port_count) GDVIRTUAL1RC(int, _get_output_port_type, int) GDVIRTUAL1RC(String, _get_output_port_name, int) - GDVIRTUAL4RC(String, _get_code, Vector<String>, TypedArray<String>, int, int) - GDVIRTUAL1RC(String, _get_global_code, int) + GDVIRTUAL4RC(String, _get_code, Vector<String>, TypedArray<String>, Shader::Mode, VisualShader::Type) + GDVIRTUAL1RC(String, _get_global_code, Shader::Mode) GDVIRTUAL0RC(bool, _is_highend) protected: @@ -697,4 +697,6 @@ public: VisualShaderNodeGlobalExpression(); }; +extern String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name); + #endif // VISUAL_SHADER_H diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index c3d9ef7b04..951870fe34 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -494,15 +494,10 @@ String VisualShaderNodeTexture::get_input_port_default_hint(int p_port) const { return ""; } -static String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) { - static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt" }; - return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id); -} - Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { VisualShader::DefaultTextureParam dtp; dtp.name = make_unique_id(p_type, p_id, "tex"); - dtp.param = texture; + dtp.params.push_back(texture); Vector<VisualShader::DefaultTextureParam> ret; ret.push_back(dtp); return ret; @@ -900,7 +895,7 @@ String VisualShaderNodeCurveTexture::generate_code(Shader::Mode p_mode, VisualSh Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurveTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { VisualShader::DefaultTextureParam dtp; dtp.name = make_unique_id(p_type, p_id, "curve"); - dtp.param = texture; + dtp.params.push_back(texture); Vector<VisualShader::DefaultTextureParam> ret; ret.push_back(dtp); return ret; @@ -985,7 +980,7 @@ String VisualShaderNodeCurveXYZTexture::generate_code(Shader::Mode p_mode, Visua Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurveXYZTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { VisualShader::DefaultTextureParam dtp; dtp.name = make_unique_id(p_type, p_id, "curve3d"); - dtp.param = texture; + dtp.params.push_back(texture); Vector<VisualShader::DefaultTextureParam> ret; ret.push_back(dtp); return ret; @@ -1167,7 +1162,7 @@ String VisualShaderNodeTexture2DArray::get_input_port_name(int p_port) const { Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture2DArray::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { VisualShader::DefaultTextureParam dtp; dtp.name = make_unique_id(p_type, p_id, "tex3d"); - dtp.param = texture_array; + dtp.params.push_back(texture_array); Vector<VisualShader::DefaultTextureParam> ret; ret.push_back(dtp); return ret; @@ -1224,7 +1219,7 @@ String VisualShaderNodeTexture3D::get_input_port_name(int p_port) const { Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture3D::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { VisualShader::DefaultTextureParam dtp; dtp.name = make_unique_id(p_type, p_id, "tex3d"); - dtp.param = texture; + dtp.params.push_back(texture); Vector<VisualShader::DefaultTextureParam> ret; ret.push_back(dtp); return ret; @@ -1323,7 +1318,7 @@ bool VisualShaderNodeCubemap::is_output_port_expandable(int p_port) const { Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubemap::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { VisualShader::DefaultTextureParam dtp; dtp.name = make_unique_id(p_type, p_id, "cube"); - dtp.param = cube_map; + dtp.params.push_back(cube_map); Vector<VisualShader::DefaultTextureParam> ret; ret.push_back(dtp); return ret; diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index ada91cec1e..7dd4eed15b 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -30,6 +30,8 @@ #include "visual_shader_particle_nodes.h" +#include "core/core_string_names.h" + // VisualShaderNodeParticleEmitter int VisualShaderNodeParticleEmitter::get_output_port_count() const { @@ -255,6 +257,283 @@ VisualShaderNodeParticleRingEmitter::VisualShaderNodeParticleRingEmitter() { set_input_port_default_value(2, 0.0); } +// VisualShaderNodeParticleMeshEmitter + +String VisualShaderNodeParticleMeshEmitter::get_caption() const { + return "MeshEmitter"; +} + +int VisualShaderNodeParticleMeshEmitter::get_output_port_count() const { + return 2; +} + +VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter::get_output_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_VECTOR; // position + case 1: + return PORT_TYPE_VECTOR; // normal + } + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeParticleMeshEmitter::get_output_port_name(int p_port) const { + switch (p_port) { + case 0: + return "position"; + case 1: + return "normal"; + } + return String(); +} + +int VisualShaderNodeParticleMeshEmitter::get_input_port_count() const { + return 0; +} + +VisualShaderNodeParticleBoxEmitter::PortType VisualShaderNodeParticleMeshEmitter::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeParticleMeshEmitter::get_input_port_name(int p_port) const { + return String(); +} + +String VisualShaderNodeParticleMeshEmitter::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code; + + if (mesh.is_valid()) { + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n"; + code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n"; + } + + return code; +} + +String VisualShaderNodeParticleMeshEmitter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + + code += " __scalar_ibuff = int(__rand_from_seed(__seed) * 65535.0) % " + itos(position_texture->get_width()) + ";\n"; + + if (position_texture->get_width() == 0) { + code += " " + p_output_vars[0] + " = vec3(0.0);\n"; + } else { + if (mode_2d) { + code += " " + p_output_vars[0] + " = vec3("; + code += "texelFetch("; + code += make_unique_id(p_type, p_id, "mesh_vx") + ", "; + code += "ivec2(__scalar_ibuff, 0), 0).xy, 0.0);\n"; + } else { + code += " " + p_output_vars[0] + " = texelFetch("; + code += make_unique_id(p_type, p_id, "mesh_vx") + ", "; + code += "ivec2(__scalar_ibuff, 0), 0).xyz;\n"; + } + } + + if (normal_texture->get_width() == 0) { + code += " " + p_output_vars[1] + " = vec3(0.0);\n"; + } else { + if (mode_2d) { + code += " " + p_output_vars[1] + " = vec3("; + code += "texelFetch("; + code += make_unique_id(p_type, p_id, "mesh_nm") + ", "; + code += "ivec2(__scalar_ibuff, 0), 0).xy, 0.0);\n"; + } else { + code += " " + p_output_vars[1] + " = texelFetch("; + code += make_unique_id(p_type, p_id, "mesh_nm") + ", "; + code += "ivec2(__scalar_ibuff, 0), 0).xyz;\n"; + } + } + + return code; +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeParticleMeshEmitter::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { + VisualShader::DefaultTextureParam dtp_vx; + dtp_vx.name = make_unique_id(p_type, p_id, "mesh_vx"); + dtp_vx.params.push_back(position_texture); + + VisualShader::DefaultTextureParam dtp_nm; + dtp_nm.name = make_unique_id(p_type, p_id, "mesh_nm"); + dtp_nm.params.push_back(normal_texture); + + Vector<VisualShader::DefaultTextureParam> ret; + ret.push_back(dtp_vx); + ret.push_back(dtp_nm); + return ret; +} + +void VisualShaderNodeParticleMeshEmitter::update_texture() { + if (!mesh.is_valid()) { + return; + } + + Vector<Vector3> vertices; + Vector<Vector3> normals; + + if (use_all_surfaces) { + for (int i = 0; i < max_surface_index; i++) { + Array vertex_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_VERTEX]; + for (int j = 0; j < vertex_array.size(); j++) { + vertices.push_back((Vector3)vertex_array[j]); + } + + Array normal_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_NORMAL]; + for (int j = 0; j < vertex_array.size(); j++) { + normals.push_back((Vector3)vertex_array[j]); + } + } + } else { + Array vertex_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_VERTEX]; + for (int i = 0; i < vertex_array.size(); i++) { + vertices.push_back((Vector3)vertex_array[i]); + } + + Array normal_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_NORMAL]; + for (int i = 0; i < normal_array.size(); i++) { + normals.push_back((Vector3)normal_array[i]); + } + } + + // vertices + { + Ref<Image> image; + image.instantiate(); + image->create(vertices.size(), 1, false, Image::Format::FORMAT_RGBF); + + for (int i = 0; i < vertices.size(); i++) { + Vector3 v = vertices[i]; + image->set_pixel(i, 0, Color(v.x, v.y, v.z)); + } + if (position_texture->get_width() != vertices.size()) { + position_texture->create_from_image(image); + } else { + position_texture->update(image); + } + } + + // normals + { + Ref<Image> image; + image.instantiate(); + image->create(normals.size(), 1, false, Image::Format::FORMAT_RGBF); + + for (int i = 0; i < normals.size(); i++) { + Vector3 v = normals[i]; + image->set_pixel(i, 0, Color(v.x, v.y, v.z)); + } + if (normal_texture->get_width() != normals.size()) { + normal_texture->create_from_image(image); + } else { + normal_texture->update(image); + } + } +} + +void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) { + if (mesh == p_mesh) { + return; + } + + if (p_mesh.is_valid()) { + max_surface_index = p_mesh->get_surface_count(); + } else { + max_surface_index = 0; + } + + if (mesh.is_valid()) { + Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture); + + if (mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) { + mesh->disconnect(CoreStringNames::get_singleton()->changed, callable); + } + } + + mesh = p_mesh; + + if (mesh.is_valid()) { + Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture); + + if (!mesh->is_connected(CoreStringNames::get_singleton()->changed, callable)) { + mesh->connect(CoreStringNames::get_singleton()->changed, callable); + } + } + + emit_changed(); +} + +Ref<Mesh> VisualShaderNodeParticleMeshEmitter::get_mesh() const { + return mesh; +} + +void VisualShaderNodeParticleMeshEmitter::set_use_all_surfaces(bool p_enabled) { + if (use_all_surfaces == p_enabled) { + return; + } + use_all_surfaces = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeParticleMeshEmitter::is_use_all_surfaces() const { + return use_all_surfaces; +} + +void VisualShaderNodeParticleMeshEmitter::set_surface_index(int p_surface_index) { + if (p_surface_index == surface_index || p_surface_index < 0 || p_surface_index >= max_surface_index) { + return; + } + surface_index = p_surface_index; + emit_changed(); +} + +int VisualShaderNodeParticleMeshEmitter::get_surface_index() const { + return surface_index; +} + +Vector<StringName> VisualShaderNodeParticleMeshEmitter::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeParticleEmitter::get_editable_properties(); + + props.push_back("mesh"); + props.push_back("use_all_surfaces"); + if (!use_all_surfaces) { + props.push_back("surface_index"); + } + + return props; +} + +Map<StringName, String> VisualShaderNodeParticleMeshEmitter::get_editable_properties_names() const { + Map<StringName, String> names = VisualShaderNodeParticleEmitter::get_editable_properties_names(); + + names.insert("mesh", TTR("Mesh")); + names.insert("use_all_surfaces", TTR("Use All Surfaces")); + if (!use_all_surfaces) { + names.insert("surface_index", TTR("Surface Index")); + } + + return names; +} + +void VisualShaderNodeParticleMeshEmitter::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &VisualShaderNodeParticleMeshEmitter::set_mesh); + ClassDB::bind_method(D_METHOD("get_mesh"), &VisualShaderNodeParticleMeshEmitter::get_mesh); + ClassDB::bind_method(D_METHOD("set_use_all_surfaces", "enabled"), &VisualShaderNodeParticleMeshEmitter::set_use_all_surfaces); + ClassDB::bind_method(D_METHOD("is_use_all_surfaces"), &VisualShaderNodeParticleMeshEmitter::is_use_all_surfaces); + ClassDB::bind_method(D_METHOD("set_surface_index", "surface_index"), &VisualShaderNodeParticleMeshEmitter::set_surface_index); + ClassDB::bind_method(D_METHOD("get_surface_index"), &VisualShaderNodeParticleMeshEmitter::get_surface_index); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_all_surfaces"), "set_use_all_surfaces", "is_use_all_surfaces"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "surface_index"), "set_surface_index", "get_surface_index"); +} + +VisualShaderNodeParticleMeshEmitter::VisualShaderNodeParticleMeshEmitter() { + connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &VisualShaderNodeParticleMeshEmitter::update_texture)); + + position_texture.instantiate(); + normal_texture.instantiate(); +} + // VisualShaderNodeParticleMultiplyByAxisAngle void VisualShaderNodeParticleMultiplyByAxisAngle::_bind_methods() { @@ -334,7 +613,6 @@ bool VisualShaderNodeParticleMultiplyByAxisAngle::is_degrees_mode() const { Vector<StringName> VisualShaderNodeParticleMultiplyByAxisAngle::get_editable_properties() const { Vector<StringName> props; props.push_back("degrees_mode"); - props.push_back("axis_amount"); return props; } diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index 0b1fa277de..0d0f21e4bf 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -52,7 +52,7 @@ public: bool is_mode_2d() const; Vector<StringName> get_editable_properties() const override; - Map<StringName, String> get_editable_properties_names() const override; + virtual Map<StringName, String> get_editable_properties_names() const override; bool is_show_prop_names() const override; VisualShaderNodeParticleEmitter(); @@ -106,6 +106,51 @@ public: VisualShaderNodeParticleRingEmitter(); }; +class VisualShaderNodeParticleMeshEmitter : public VisualShaderNodeParticleEmitter { + GDCLASS(VisualShaderNodeParticleMeshEmitter, VisualShaderNodeParticleEmitter); + Ref<Mesh> mesh; + bool use_all_surfaces = true; + int surface_index = 0; + int max_surface_index = 0; + + Ref<ImageTexture> position_texture; + Ref<ImageTexture> normal_texture; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + void update_texture(); + + void set_mesh(Ref<Mesh> p_mesh); + Ref<Mesh> get_mesh() const; + + void set_use_all_surfaces(bool p_enabled); + bool is_use_all_surfaces() const; + + void set_surface_index(int p_surface_index); + int get_surface_index() const; + + Vector<StringName> get_editable_properties() const override; + Map<StringName, String> get_editable_properties_names() const override; + Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; + + VisualShaderNodeParticleMeshEmitter(); +}; + class VisualShaderNodeParticleMultiplyByAxisAngle : public VisualShaderNode { GDCLASS(VisualShaderNodeParticleMultiplyByAxisAngle, VisualShaderNode); bool degrees_mode = true; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 7bf5673663..8b5a965738 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -148,7 +148,7 @@ Point2i DisplayServer::mouse_get_position() const { } MouseButton DisplayServer::mouse_get_button_state() const { - ERR_FAIL_V_MSG(MOUSE_BUTTON_NONE, "Mouse is not supported by this display server."); + ERR_FAIL_V_MSG(MouseButton::NONE, "Mouse is not supported by this display server."); } void DisplayServer::clipboard_set(const String &p_text) { diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp index 6983e28841..fb9d38e7ea 100644 --- a/servers/physics_2d/godot_area_2d.cpp +++ b/servers/physics_2d/godot_area_2d.cpp @@ -121,18 +121,21 @@ void GodotArea2D::set_area_monitor_callback(const Callable &p_callback) { } } -void GodotArea2D::set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode) { - bool do_override = p_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; - if (do_override == (space_override_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) { +void GodotArea2D::_set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode) { + bool do_override = p_new_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + if (do_override == (r_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) { return; } _unregister_shapes(); - space_override_mode = p_mode; + r_mode = p_new_mode; _shape_changed(); } void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { + case PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE: + _set_space_override_mode(gravity_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer2D::AREA_PARAM_GRAVITY: gravity = p_value; break; @@ -148,9 +151,15 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation = p_value; break; + case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: + _set_space_override_mode(linear_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP: linear_damp = p_value; break; + case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE: + _set_space_override_mode(angular_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP: angular_damp = p_value; break; @@ -162,6 +171,8 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const { switch (p_param) { + case PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE: + return gravity_override_mode; case PhysicsServer2D::AREA_PARAM_GRAVITY: return gravity; case PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR: @@ -172,8 +183,12 @@ Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const { return gravity_distance_scale; case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; + case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: + return linear_damping_override_mode; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE: + return angular_damping_override_mode; case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP: return angular_damp; case PhysicsServer2D::AREA_PARAM_PRIORITY: diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h index 13b3ce1bf2..699c1c1bc8 100644 --- a/servers/physics_2d/godot_area_2d.h +++ b/servers/physics_2d/godot_area_2d.h @@ -41,7 +41,10 @@ class GodotBody2D; class GodotConstraint2D; class GodotArea2D : public GodotCollisionObject2D { - PhysicsServer2D::AreaSpaceOverrideMode space_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer2D::AreaSpaceOverrideMode gravity_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer2D::AreaSpaceOverrideMode linear_damping_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer2D::AreaSpaceOverrideMode angular_damping_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + real_t gravity = 9.80665; Vector2 gravity_vector = Vector2(0, -1); bool gravity_is_point = false; @@ -96,6 +99,8 @@ class GodotArea2D : public GodotCollisionObject2D { virtual void _shapes_changed(); void _queue_monitor_update(); + void _set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode); + public: void set_monitor_callback(const Callable &p_callback); _FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); } @@ -112,9 +117,6 @@ public: void set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value); Variant get_param(PhysicsServer2D::AreaParameter p_param) const; - void set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode); - PhysicsServer2D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } - _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; } _FORCE_INLINE_ real_t get_gravity() const { return gravity; } diff --git a/servers/physics_2d/godot_area_pair_2d.cpp b/servers/physics_2d/godot_area_pair_2d.cpp index fdb95aa262..a98513004d 100644 --- a/servers/physics_2d/godot_area_pair_2d.cpp +++ b/servers/physics_2d/godot_area_pair_2d.cpp @@ -38,10 +38,18 @@ bool GodotAreaPair2D::setup(real_t p_step) { } process_collision = false; + has_space_override = false; if (result != colliding) { - if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { - process_collision = true; - } else if (area->has_monitor_callback()) { + if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } + process_collision = has_space_override; + + if (area->has_monitor_callback()) { process_collision = true; } @@ -57,7 +65,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) { } if (colliding) { - if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->add_area(area); } @@ -65,7 +73,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) { area->add_body_to_query(body, body_shape, area_shape); } } else { - if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->remove_area(area); } @@ -95,7 +103,7 @@ GodotAreaPair2D::GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotAre GodotAreaPair2D::~GodotAreaPair2D() { if (colliding) { - if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->remove_area(area); } if (area->has_monitor_callback()) { diff --git a/servers/physics_2d/godot_area_pair_2d.h b/servers/physics_2d/godot_area_pair_2d.h index 7a9677f714..45bd3df1ed 100644 --- a/servers/physics_2d/godot_area_pair_2d.h +++ b/servers/physics_2d/godot_area_pair_2d.h @@ -41,6 +41,7 @@ class GodotAreaPair2D : public GodotConstraint2D { int body_shape = 0; int area_shape = 0; bool colliding = false; + bool has_space_override = false; bool process_collision = false; public: diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp index 442c580920..9b97583300 100644 --- a/servers/physics_2d/godot_body_2d.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -410,15 +410,6 @@ void GodotBody2D::set_space(GodotSpace2D *p_space) { } } -void GodotBody2D::_compute_area_gravity_and_damping(const GodotArea2D *p_area) { - Vector2 area_gravity; - p_area->compute_gravity(get_transform().get_origin(), area_gravity); - gravity += area_gravity; - - total_linear_damp += p_area->get_linear_damp(); - total_angular_damp += p_area->get_angular_damp(); -} - void GodotBody2D::_update_transform_dependent() { center_of_mass = get_transform().basis_xform(center_of_mass_local); } @@ -428,8 +419,16 @@ void GodotBody2D::integrate_forces(real_t p_step) { return; } + ERR_FAIL_COND(!get_space()); + int ac = areas.size(); + + bool gravity_done = false; + bool linear_damp_done = false; + bool angular_damp_done = false; + bool stopped = false; + gravity = Vector2(0, 0); total_linear_damp = 0.0; @@ -440,33 +439,89 @@ void GodotBody2D::integrate_forces(real_t p_step) { areas.sort(); const AreaCMP *aa = &areas[0]; for (int i = ac - 1; i >= 0 && !stopped; i--) { - PhysicsServer2D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - _compute_area_gravity_and_damping(aa[i].area); - stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - gravity = Vector2(0, 0); - total_linear_damp = 0.0; - total_angular_damp = 0.0; - _compute_area_gravity_and_damping(aa[i].area); - stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { + if (!gravity_done) { + PhysicsServer2D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE); + if (area_gravity_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + Vector2 area_gravity; + aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity); + switch (area_gravity_mode) { + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + gravity += area_gravity; + gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + gravity = area_gravity; + gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } } } + if (!linear_damp_done) { + PhysicsServer2D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); + if (area_linear_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + real_t area_linear_damp = aa[i].area->get_linear_damp(); + switch (area_linear_damp_mode) { + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + total_linear_damp += area_linear_damp; + linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + total_linear_damp = area_linear_damp; + linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + if (!angular_damp_done) { + PhysicsServer2D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); + if (area_angular_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + real_t area_angular_damp = aa[i].area->get_angular_damp(); + switch (area_angular_damp_mode) { + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + total_angular_damp += area_angular_damp; + angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + total_angular_damp = area_angular_damp; + angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + stopped = gravity_done && linear_damp_done && angular_damp_done; } } - // Override linear damping with body's value. + // Add default gravity and damping from space area. if (!stopped) { - GodotArea2D *def_area = get_space()->get_default_area(); - ERR_FAIL_COND(!def_area); + GodotArea2D *default_area = get_space()->get_default_area(); + ERR_FAIL_COND(!default_area); - _compute_area_gravity_and_damping(def_area); + if (!gravity_done) { + Vector2 default_gravity; + default_area->compute_gravity(get_transform().get_origin(), default_gravity); + gravity += default_gravity; + } + + if (!linear_damp_done) { + total_linear_damp += default_area->get_linear_damp(); + } + + if (!angular_damp_done) { + total_angular_damp += default_area->get_angular_damp(); + } } // Override linear damping with body's value. diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 7b11b50739..d1dbf92c1b 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -145,8 +145,6 @@ class GodotBody2D : public GodotCollisionObject2D { uint64_t island_step = 0; - void _compute_area_gravity_and_damping(const GodotArea2D *p_area); - void _update_transform_dependent(); friend class GodotPhysicsDirectBodyState2D; // i give up, too many functions to expose diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index cf66b80076..8ac27077fc 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -289,7 +289,7 @@ RID GodotPhysicsServer2D::area_create() { RID rid = area_owner.make_rid(area); area->set_self(rid); return rid; -}; +} void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) { GodotArea2D *area = area_owner.get_or_null(p_area); @@ -307,7 +307,7 @@ void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) { area->clear_constraints(); area->set_space(space); -}; +} RID GodotPhysicsServer2D::area_get_space(RID p_area) const { GodotArea2D *area = area_owner.get_or_null(p_area); @@ -318,20 +318,6 @@ RID GodotPhysicsServer2D::area_get_space(RID p_area) const { return RID(); } return space->get_self(); -}; - -void GodotPhysicsServer2D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { - GodotArea2D *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_space_override_mode(p_mode); -} - -PhysicsServer2D::AreaSpaceOverrideMode GodotPhysicsServer2D::area_get_space_override_mode(RID p_area) const { - const GodotArea2D *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); - - return area->get_space_override_mode(); } void GodotPhysicsServer2D::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) { @@ -963,10 +949,17 @@ bool GodotPhysicsServer2D::body_test_motion(RID p_body, const MotionParameters & PhysicsDirectBodyState2D *GodotPhysicsServer2D::body_get_direct_state(RID p_body) { ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + if (!body_owner.owns(p_body)) { + return nullptr; + } + GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_COND_V(!body, nullptr); - ERR_FAIL_COND_V(!body->get_space(), nullptr); + if (!body->get_space()) { + return nullptr; + } + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); return body->get_direct_state(); diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h index b03d78a1de..1f544fee72 100644 --- a/servers/physics_2d/godot_physics_server_2d.h +++ b/servers/physics_2d/godot_physics_server_2d.h @@ -124,9 +124,6 @@ public: virtual RID area_create() override; - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override; - virtual void area_set_space(RID p_area, RID p_space) override; virtual RID area_get_space(RID p_area) const override; diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 5c189aa06a..6465a5542c 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -153,6 +153,22 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parame Vector2 shape_point, shape_normal; + if (shape->contains_point(local_from)) { + if (p_parameters.hit_from_inside) { + // Hit shape at starting point. + min_d = 0; + res_point = local_from; + res_normal = Vector2(); + res_shape = shape_idx; + res_obj = col_obj; + collided = true; + break; + } else { + // Ignore shape when starting inside. + continue; + } + } + if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) { Transform2D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); shape_point = xform.xform(shape_point); diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 84ec0e3c63..00d11acdab 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -152,6 +152,9 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations) p_space->set_active_objects(active_count); + // Update the broadphase to register collision pairs. + p_space->update(); + { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); @@ -286,7 +289,6 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations) all_constraints.clear(); - p_space->update(); p_space->unlock(); _step++; } diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index 973fc50968..9cdad069fe 100644 --- a/servers/physics_3d/godot_area_3d.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -128,18 +128,21 @@ void GodotArea3D::set_area_monitor_callback(const Callable &p_callback) { } } -void GodotArea3D::set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) { - bool do_override = p_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; - if (do_override == (space_override_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) { +void GodotArea3D::_set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode) { + bool do_override = p_new_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + if (do_override == (r_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) { return; } _unregister_shapes(); - space_override_mode = p_mode; + r_mode = p_new_mode; _shape_changed(); } void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { + case PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE: + _set_space_override_mode(gravity_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer3D::AREA_PARAM_GRAVITY: gravity = p_value; break; @@ -155,9 +158,15 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation = p_value; break; + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: + _set_space_override_mode(linear_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: linear_damp = p_value; break; + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE: + _set_space_override_mode(angular_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: angular_damp = p_value; break; @@ -183,6 +192,8 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const { switch (p_param) { + case PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE: + return gravity_override_mode; case PhysicsServer3D::AREA_PARAM_GRAVITY: return gravity; case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: @@ -193,8 +204,12 @@ Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const { return gravity_distance_scale; case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: + return linear_damping_override_mode; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE: + return angular_damping_override_mode; case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: return angular_damp; case PhysicsServer3D::AREA_PARAM_PRIORITY: diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index b02fa1d5b9..0dcf89b2b4 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -42,7 +42,10 @@ class GodotSoftBody3D; class GodotConstraint3D; class GodotArea3D : public GodotCollisionObject3D { - PhysicsServer3D::AreaSpaceOverrideMode space_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer3D::AreaSpaceOverrideMode gravity_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer3D::AreaSpaceOverrideMode linear_damping_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer3D::AreaSpaceOverrideMode angular_damping_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + real_t gravity = 9.80665; Vector3 gravity_vector = Vector3(0, -1, 0); bool gravity_is_point = false; @@ -102,6 +105,8 @@ class GodotArea3D : public GodotCollisionObject3D { virtual void _shapes_changed(); void _queue_monitor_update(); + void _set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode); + public: void set_monitor_callback(const Callable &p_callback); _FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); } @@ -121,9 +126,6 @@ public: void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); Variant get_param(PhysicsServer3D::AreaParameter p_param) const; - void set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode); - PhysicsServer3D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } - _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; } _FORCE_INLINE_ real_t get_gravity() const { return gravity; } diff --git a/servers/physics_3d/godot_area_pair_3d.cpp b/servers/physics_3d/godot_area_pair_3d.cpp index 7453153de6..d3623178d5 100644 --- a/servers/physics_3d/godot_area_pair_3d.cpp +++ b/servers/physics_3d/godot_area_pair_3d.cpp @@ -39,10 +39,18 @@ bool GodotAreaPair3D::setup(real_t p_step) { } process_collision = false; + has_space_override = false; if (result != colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { - process_collision = true; - } else if (area->has_monitor_callback()) { + if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } + process_collision = has_space_override; + + if (area->has_monitor_callback()) { process_collision = true; } @@ -58,7 +66,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) { } if (colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->add_area(area); } @@ -66,7 +74,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) { area->add_body_to_query(body, body_shape, area_shape); } } else { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->remove_area(area); } @@ -96,7 +104,7 @@ GodotAreaPair3D::GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotAre GodotAreaPair3D::~GodotAreaPair3D() { if (colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->remove_area(area); } if (area->has_monitor_callback()) { @@ -207,10 +215,15 @@ bool GodotAreaSoftBodyPair3D::setup(real_t p_step) { } process_collision = false; + has_space_override = false; if (result != colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { - process_collision = true; - } else if (area->has_monitor_callback()) { + if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if (area->get_wind_force_magnitude() > CMP_EPSILON) { + has_space_override = true; + } + + if (area->has_monitor_callback()) { process_collision = true; } @@ -226,7 +239,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) { } if (colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { soft_body->add_area(area); } @@ -234,7 +247,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) { area->add_soft_body_to_query(soft_body, soft_body_shape, area_shape); } } else { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { soft_body->remove_area(area); } @@ -261,7 +274,7 @@ GodotAreaSoftBodyPair3D::GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_soft_body, i GodotAreaSoftBodyPair3D::~GodotAreaSoftBodyPair3D() { if (colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { soft_body->remove_area(area); } if (area->has_monitor_callback()) { diff --git a/servers/physics_3d/godot_area_pair_3d.h b/servers/physics_3d/godot_area_pair_3d.h index f55c03be03..16175e9fa8 100644 --- a/servers/physics_3d/godot_area_pair_3d.h +++ b/servers/physics_3d/godot_area_pair_3d.h @@ -43,6 +43,7 @@ class GodotAreaPair3D : public GodotConstraint3D { int area_shape; bool colliding = false; bool process_collision = false; + bool has_space_override = false; public: virtual bool setup(real_t p_step) override; @@ -79,6 +80,7 @@ class GodotAreaSoftBodyPair3D : public GodotConstraint3D { int area_shape; bool colliding = false; bool process_collision = false; + bool has_space_override = false; public: virtual bool setup(real_t p_step) override; diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp index acf60d61c2..0e21dd303f 100644 --- a/servers/physics_3d/godot_body_3d.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -457,15 +457,6 @@ void GodotBody3D::set_space(GodotSpace3D *p_space) { } } -void GodotBody3D::_compute_area_gravity_and_damping(const GodotArea3D *p_area) { - Vector3 area_gravity; - p_area->compute_gravity(get_transform().get_origin(), area_gravity); - gravity += area_gravity; - - total_linear_damp += p_area->get_linear_damp(); - total_angular_damp += p_area->get_angular_damp(); -} - void GodotBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) { if (lock) { locked_axis |= p_axis; @@ -483,8 +474,16 @@ void GodotBody3D::integrate_forces(real_t p_step) { return; } + ERR_FAIL_COND(!get_space()); + int ac = areas.size(); + + bool gravity_done = false; + bool linear_damp_done = false; + bool angular_damp_done = false; + bool stopped = false; + gravity = Vector3(0, 0, 0); total_linear_damp = 0.0; @@ -495,33 +494,89 @@ void GodotBody3D::integrate_forces(real_t p_step) { areas.sort(); const AreaCMP *aa = &areas[0]; for (int i = ac - 1; i >= 0 && !stopped; i--) { - PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - _compute_area_gravity_and_damping(aa[i].area); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - gravity = Vector3(0, 0, 0); - total_linear_damp = 0.0; - total_angular_damp = 0.0; - _compute_area_gravity_and_damping(aa[i].area); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { + if (!gravity_done) { + PhysicsServer3D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE); + if (area_gravity_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + Vector3 area_gravity; + aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity); + switch (area_gravity_mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + gravity += area_gravity; + gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + gravity = area_gravity; + gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + if (!linear_damp_done) { + PhysicsServer3D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); + if (area_linear_damp_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + real_t area_linear_damp = aa[i].area->get_linear_damp(); + switch (area_linear_damp_mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + total_linear_damp += area_linear_damp; + linear_damp_done = area_linear_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + total_linear_damp = area_linear_damp; + linear_damp_done = area_linear_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + if (!angular_damp_done) { + PhysicsServer3D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); + if (area_angular_damp_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + real_t area_angular_damp = aa[i].area->get_angular_damp(); + switch (area_angular_damp_mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + total_angular_damp += area_angular_damp; + angular_damp_done = area_angular_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + total_angular_damp = area_angular_damp; + angular_damp_done = area_angular_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } } } + stopped = gravity_done && linear_damp_done && angular_damp_done; } } // Add default gravity and damping from space area. if (!stopped) { - GodotArea3D *def_area = get_space()->get_default_area(); - ERR_FAIL_COND(!def_area); + GodotArea3D *default_area = get_space()->get_default_area(); + ERR_FAIL_COND(!default_area); - _compute_area_gravity_and_damping(def_area); + if (!gravity_done) { + Vector3 default_gravity; + default_area->compute_gravity(get_transform().get_origin(), default_gravity); + gravity += default_gravity; + } + + if (!linear_damp_done) { + total_linear_damp += default_area->get_linear_damp(); + } + + if (!angular_damp_done) { + total_angular_damp += default_area->get_angular_damp(); + } } // Override linear damping with body's value. diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index 7fc2f58168..ac3131ab44 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -139,8 +139,6 @@ class GodotBody3D : public GodotCollisionObject3D { uint64_t island_step = 0; - void _compute_area_gravity_and_damping(const GodotArea3D *p_area); - void _update_transform_dependent(); friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp index f7d9ed9ee9..f0002870ae 100644 --- a/servers/physics_3d/godot_body_pair_3d.cpp +++ b/servers/physics_3d/godot_body_pair_3d.cpp @@ -191,7 +191,7 @@ bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, Vector3 local_to = from_inv.xform(to); Vector3 rpos, rnorm; - if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm)) { + if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm, true)) { return false; } diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index b9f2f7506b..686f3e4d59 100644 --- a/servers/physics_3d/godot_collision_solver_3d.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -102,7 +102,7 @@ bool GodotCollisionSolver3D::solve_separation_ray(const GodotShape3D *p_shape_A, to = ai.xform(to); Vector3 p, n; - if (!p_shape_B->intersect_segment(from, to, p, n)) { + if (!p_shape_B->intersect_segment(from, to, p, n, true)) { return false; } diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index 73654939ca..9acae62382 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -219,7 +219,7 @@ RID GodotPhysicsServer3D::area_create() { RID rid = area_owner.make_rid(area); area->set_self(rid); return rid; -}; +} void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) { GodotArea3D *area = area_owner.get_or_null(p_area); @@ -237,7 +237,7 @@ void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) { area->clear_constraints(); area->set_space(space); -}; +} RID GodotPhysicsServer3D::area_get_space(RID p_area) const { GodotArea3D *area = area_owner.get_or_null(p_area); @@ -248,20 +248,6 @@ RID GodotPhysicsServer3D::area_get_space(RID p_area) const { return RID(); } return space->get_self(); -}; - -void GodotPhysicsServer3D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { - GodotArea3D *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_space_override_mode(p_mode); -} - -PhysicsServer3D::AreaSpaceOverrideMode GodotPhysicsServer3D::area_get_space_override_mode(RID p_area) const { - const GodotArea3D *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); - - return area->get_space_override_mode(); } void GodotPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) { @@ -881,10 +867,17 @@ bool GodotPhysicsServer3D::body_test_motion(RID p_body, const MotionParameters & PhysicsDirectBodyState3D *GodotPhysicsServer3D::body_get_direct_state(RID p_body) { ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + if (!body_owner.owns(p_body)) { + return nullptr; + } + GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, nullptr); - ERR_FAIL_NULL_V(body->get_space(), nullptr); + if (!body->get_space()) { + return nullptr; + } + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); return body->get_direct_state(); diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h index 4ddd10a4e0..f5c8e0f60d 100644 --- a/servers/physics_3d/godot_physics_server_3d.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -122,9 +122,6 @@ public: virtual RID area_create() override; - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override; - virtual void area_set_space(RID p_area, RID p_space) override; virtual RID area_get_space(RID p_area) const override; diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 4c12a5a948..d1e919ab6a 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -119,7 +119,7 @@ Vector3 GodotWorldBoundaryShape3D::get_support(const Vector3 &p_normal) const { return p_normal * 1e15; } -bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { bool inters = plane.intersects_segment(p_begin, p_end, &r_result); if (inters) { r_normal = plane.normal; @@ -200,7 +200,7 @@ void GodotSeparationRayShape3D::get_supports(const Vector3 &p_normal, int p_max, } } -bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { return false; //simply not possible } @@ -268,7 +268,7 @@ void GodotSphereShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector r_type = FEATURE_POINT; } -bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { return Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal); } @@ -410,7 +410,7 @@ void GodotBoxShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 * r_supports[0] = point; } -bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { AABB aabb(-half_extents, half_extents * 2.0); return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal); @@ -430,7 +430,7 @@ Vector3 GodotBoxShape3D::get_closest_point_to(const Vector3 &p_point) const { if (outside == 1) { //use plane if only one side matches Vector3 n; - n[i] = SGN(p_point[i]); + n[i] = SIGN(p_point[i]); Plane p(n, half_extents[i]); min_point = p.project(p_point); @@ -546,7 +546,7 @@ void GodotCapsuleShape3D::get_supports(const Vector3 &p_normal, int p_max, Vecto } } -bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { Vector3 norm = (p_end - p_begin).normalized(); real_t min_d = 1e20; @@ -761,7 +761,7 @@ void GodotCylinderShape3D::get_supports(const Vector3 &p_normal, int p_max, Vect } } -bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { return Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &r_result, &r_normal, 1); } @@ -954,7 +954,7 @@ void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max, r_type = FEATURE_POINT; } -bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { const Geometry3D::MeshData::Face *faces = mesh.faces.ptr(); int fc = mesh.faces.size(); @@ -1188,12 +1188,12 @@ void GodotFaceShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 r_supports[0] = vertex[vert_support_idx]; } -bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { bool c = Geometry3D::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result); if (c) { r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal; if (r_normal.dot(p_end - p_begin) > 0) { - if (backface_collision) { + if (backface_collision && p_hit_back_faces) { r_normal = -r_normal; } else { c = false; @@ -1304,7 +1304,7 @@ void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_ Vector3 res; Vector3 normal; - if (face->intersect_segment(p_params->from, p_params->to, res, normal)) { + if (face->intersect_segment(p_params->from, p_params->to, res, normal, true)) { real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from); if ((d > 0) && (d < p_params->min_d)) { p_params->min_d = d; @@ -1323,7 +1323,7 @@ void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_ } } -bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { if (faces.size() == 0) { return false; } @@ -1334,7 +1334,7 @@ bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const const BVH *br = bvh.ptr(); GodotFaceShape3D face; - face.backface_collision = backface_collision; + face.backface_collision = backface_collision && p_hit_back_faces; _SegmentCullParams params; params.from = p_begin; @@ -1675,7 +1675,7 @@ struct _HeightmapGridCullState { _FORCE_INLINE_ bool _heightmap_face_cull_segment(_HeightmapSegmentCullParams &p_params) { Vector3 res; Vector3 normal; - if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal)) { + if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal, true)) { p_params.result = res; p_params.normal = normal; return true; @@ -1881,7 +1881,7 @@ bool GodotHeightMapShape3D::_intersect_grid_segment(ProcessFunction &p_process, return false; } -bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const { +bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const { if (heights.is_empty()) { return false; } @@ -1899,7 +1899,7 @@ bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vect // Simple case for rays that don't traverse the grid horizontally. // Just perform a test on the given cell. GodotFaceShape3D face; - face.backface_collision = false; + face.backface_collision = p_hit_back_faces; _HeightmapSegmentCullParams params; params.from = p_begin; diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h index 1bbcd903f7..7a32b69166 100644 --- a/servers/physics_3d/godot_shape_3d.h +++ b/servers/physics_3d/godot_shape_3d.h @@ -80,7 +80,7 @@ public: virtual Vector3 get_support(const Vector3 &p_normal) const; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const = 0; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const = 0; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const = 0; virtual bool intersect_point(const Vector3 &p_point) const = 0; virtual Vector3 get_moment_of_inertia(real_t p_mass) const = 0; @@ -126,7 +126,7 @@ public: virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; } - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_moment_of_inertia(real_t p_mass) const override; @@ -153,7 +153,7 @@ public: virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -180,7 +180,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -205,7 +205,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -234,7 +234,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -263,7 +263,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -288,7 +288,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -366,7 +366,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -429,7 +429,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -456,7 +456,7 @@ struct GodotFaceShape3D : public GodotShape3D { virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -495,7 +495,7 @@ struct GodotMotionShape3D : public GodotShape3D { } virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; } - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override { return false; } + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override { return false; } virtual bool intersect_point(const Vector3 &p_point) const override { return false; } virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override { return p_point; } diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index 4b3e8cc0d9..b8e9ab4fb9 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -917,9 +917,7 @@ void GodotSoftBody3D::add_velocity(const Vector3 &p_velocity) { } } -void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) { - int ac = areas.size(); - +void GodotSoftBody3D::apply_forces(const LocalVector<GodotArea3D *> &p_wind_areas) { if (nodes.is_empty()) { return; } @@ -932,7 +930,6 @@ void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) { // Iterate over faces (try not to iterate elsewhere if possible). for (i = 0, ni = faces.size(); i < ni; ++i) { - bool stopped = false; const Face &face = faces[i]; Vector3 wind_force(0, 0, 0); @@ -941,24 +938,10 @@ void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) { volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org)); // Compute nodal forces from area winds. - if (ac && p_has_wind_forces) { - const AreaCMP *aa = &areas[0]; - for (j = ac - 1; j >= 0 && !stopped; j--) { - PhysicsServer3D::AreaSpaceOverrideMode mode = aa[j].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - wind_force += _compute_area_windforce(aa[j].area, &face); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - wind_force = _compute_area_windforce(aa[j].area, &face); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { - } - } + int wind_area_count = p_wind_areas.size(); + if (wind_area_count > 0) { + for (j = 0; j < wind_area_count; j++) { + wind_force += _compute_area_windforce(p_wind_areas[j], &face); } for (j = 0; j < 3; j++) { @@ -1004,44 +987,59 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) { ERR_FAIL_COND(!get_space()); - GodotArea3D *def_area = get_space()->get_default_area(); - ERR_FAIL_COND(!def_area); - gravity = def_area->get_gravity_vector() * def_area->get_gravity(); - int ac = areas.size(); - bool stopped = false; - bool has_wind_forces = false; + + bool gravity_done = false; + + LocalVector<GodotArea3D *> wind_areas; if (ac) { areas.sort(); const AreaCMP *aa = &areas[0]; - for (int i = ac - 1; i >= 0 && !stopped; i--) { - // Avoids unnecessary loop in apply_forces(). - has_wind_forces = has_wind_forces || aa[i].area->get_wind_force_magnitude() > CMP_EPSILON; - - PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - _compute_area_gravity(aa[i].area); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - gravity = Vector3(0, 0, 0); - _compute_area_gravity(aa[i].area); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { + for (int i = ac - 1; i >= 0; i--) { + if (!gravity_done) { + PhysicsServer3D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE); + if (area_gravity_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + Vector3 area_gravity; + aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity); + switch (area_gravity_mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + gravity += area_gravity; + gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + gravity = Vector3(0, 0, 0); + gravity = area_gravity; + gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } } } + + if (aa[i].area->get_wind_force_magnitude() > CMP_EPSILON) { + wind_areas.push_back(aa[i].area); + } } } + // Add default gravity and damping from space area. + if (!gravity_done) { + GodotArea3D *default_area = get_space()->get_default_area(); + ERR_FAIL_COND(!default_area); + + Vector3 default_gravity; + default_area->compute_gravity(get_transform().get_origin(), default_gravity); + gravity += default_gravity; + } + // Apply forces. add_velocity(gravity * p_delta); - if (pressure_coefficient > CMP_EPSILON || has_wind_forces) { - apply_forces(has_wind_forces); + if (pressure_coefficient > CMP_EPSILON || !wind_areas.is_empty()) { + apply_forces(wind_areas); } // Avoid soft body from 'exploding' so use some upper threshold of maximum motion @@ -1300,7 +1298,7 @@ struct _SoftBodyIntersectSegmentInfo { } }; -bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { _SoftBodyIntersectSegmentInfo query_info; query_info.soft_body = soft_body; query_info.from = p_begin; diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h index 008d5dddb8..c03951959f 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -232,7 +232,7 @@ private: void add_velocity(const Vector3 &p_velocity); - void apply_forces(bool p_has_wind_forces); + void apply_forces(const LocalVector<GodotArea3D *> &p_wind_areas); bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices); void generate_bending_constraints(int p_distance); @@ -257,18 +257,18 @@ class GodotSoftBodyShape3D : public GodotShape3D { public: GodotSoftBody3D *get_soft_body() const { return soft_body; } - virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SOFT_BODY; } - virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; } - virtual Vector3 get_support(const Vector3 &p_normal) const { return Vector3(); } - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; } + virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SOFT_BODY; } + virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override { r_min = r_max = 0.0; } + virtual Vector3 get_support(const Vector3 &p_normal) const override { return Vector3(); } + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; } - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - virtual Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); } + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; + virtual bool intersect_point(const Vector3 &p_point) const override; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const override { return Vector3(); } - virtual void set_data(const Variant &p_data) {} - virtual Variant get_data() const { return Variant(); } + virtual void set_data(const Variant &p_data) override {} + virtual Variant get_data() const override { return Variant(); } void update_bounds(); diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 77b37a2353..e2f90b90ad 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -148,7 +148,23 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame Vector3 shape_point, shape_normal; - if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) { + if (shape->intersect_point(local_from)) { + if (p_parameters.hit_from_inside) { + // Hit shape at starting point. + min_d = 0; + res_point = local_from; + res_normal = Vector3(); + res_shape = shape_idx; + res_obj = col_obj; + collided = true; + break; + } else { + // Ignore shape when starting inside. + continue; + } + } + + if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal, p_parameters.hit_back_faces)) { Transform3D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); shape_point = xform.xform(shape_point); diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index 331d65df49..5453c4415c 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -220,6 +220,9 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations) p_space->set_active_objects(active_count); + // Update the broadphase to register collision pairs. + p_space->update(); + { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); @@ -398,7 +401,6 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations) all_constraints.clear(); - p_space->update(); p_space->unlock(); _step++; } diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index fa89ccec65..76f0b74c72 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -172,12 +172,16 @@ void PhysicsRayQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_areas); ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_areas_enabled); + ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &PhysicsRayQueryParameters2D::set_hit_from_inside); + ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &PhysicsRayQueryParameters2D::is_hit_from_inside_enabled); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "from"), "set_from", "get_from"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "to"), "set_to", "get_to"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled"); } /////////////////////////////////////////////////////// @@ -605,9 +609,6 @@ void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer2D::area_set_space); ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer2D::area_get_space); - ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer2D::area_set_space_override_mode); - ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer2D::area_get_space_override_mode); - ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer2D::area_add_shape, DEFVAL(Transform2D()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer2D::area_set_shape); ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer2D::area_set_shape_transform); @@ -751,12 +752,15 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON); BIND_ENUM_CONSTANT(SHAPE_CUSTOM); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); + BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP); BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index fec03a8111..2bff8f5dcb 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -121,6 +121,8 @@ public: bool collide_with_bodies = true; bool collide_with_areas = false; + + bool hit_from_inside = false; }; struct RayResult { @@ -264,12 +266,15 @@ public: //missing attenuation? missing better override? enum AreaParameter { + AREA_PARAM_GRAVITY_OVERRIDE_MODE, AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, + AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, AREA_PARAM_ANGULAR_DAMP, AREA_PARAM_PRIORITY }; @@ -287,9 +292,6 @@ public: AREA_SPACE_OVERRIDE_REPLACE_COMBINE // Discards all previous calculations, then keeps combining }; - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; - virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) = 0; @@ -604,6 +606,9 @@ public: void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; } + bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; } + void set_exclude(const Vector<RID> &p_exclude); Vector<RID> get_exclude() const; }; diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index b133fa41aa..dda4eb6ffa 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -133,9 +133,6 @@ public: FUNC2(area_set_space, RID, RID); FUNC1RC(RID, area_get_space, RID); - FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode); - FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID); - FUNC4(area_add_shape, RID, RID, const Transform2D &, bool); FUNC3(area_set_shape, RID, int, RID); FUNC3(area_set_shape_transform, RID, int, const Transform2D &); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index eb52cbfe5a..373f216e01 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -175,12 +175,20 @@ void PhysicsRayQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_areas); ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_areas_enabled); + ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &PhysicsRayQueryParameters3D::set_hit_from_inside); + ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &PhysicsRayQueryParameters3D::is_hit_from_inside_enabled); + + ClassDB::bind_method(D_METHOD("set_hit_back_faces", "enable"), &PhysicsRayQueryParameters3D::set_hit_back_faces); + ClassDB::bind_method(D_METHOD("is_hit_back_faces_enabled"), &PhysicsRayQueryParameters3D::is_hit_back_faces_enabled); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "from"), "set_from", "get_from"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "to"), "set_to", "get_to"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_back_faces"), "set_hit_back_faces", "is_hit_back_faces_enabled"); } /////////////////////////////////////////////////////// @@ -653,9 +661,6 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer3D::area_set_space); ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer3D::area_get_space); - ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer3D::area_set_space_override_mode); - ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer3D::area_get_space_override_mode); - ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer3D::area_add_shape, DEFVAL(Transform3D()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer3D::area_set_shape); ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer3D::area_set_shape_transform); @@ -901,12 +906,15 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(SHAPE_SOFT_BODY); BIND_ENUM_CONSTANT(SHAPE_CUSTOM); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); + BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP); BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY); BIND_ENUM_CONSTANT(AREA_PARAM_WIND_FORCE_MAGNITUDE); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index b5113fd35f..89a7eeee96 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -125,6 +125,9 @@ public: bool collide_with_bodies = true; bool collide_with_areas = false; + bool hit_from_inside = false; + bool hit_back_faces = true; + bool pick_ray = false; }; @@ -285,12 +288,15 @@ public: //missing attenuation? missing better override? enum AreaParameter { + AREA_PARAM_GRAVITY_OVERRIDE_MODE, AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, + AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, AREA_PARAM_ANGULAR_DAMP, AREA_PARAM_PRIORITY, AREA_PARAM_WIND_FORCE_MAGNITUDE, @@ -312,9 +318,6 @@ public: AREA_SPACE_OVERRIDE_REPLACE_COMBINE }; - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; - virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) = 0; virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) = 0; @@ -805,6 +808,12 @@ public: void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; } + bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; } + + void set_hit_back_faces(bool p_enable) { parameters.hit_back_faces = p_enable; } + bool is_hit_back_faces_enabled() const { return parameters.hit_back_faces; } + void set_exclude(const Vector<RID> &p_exclude); Vector<RID> get_exclude() const; }; diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index df3dc279fe..507427ecec 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -137,9 +137,6 @@ public: FUNC2(area_set_space, RID, RID); FUNC1RC(RID, area_get_space, RID); - FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode); - FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID); - FUNC4(area_add_shape, RID, RID, const Transform3D &, bool); FUNC3(area_set_shape, RID, int, RID); FUNC3(area_set_shape_transform, RID, int, const Transform3D &); diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h index 44e07a1853..cecb009aa0 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -293,8 +293,8 @@ public: String shader_get_code(RID p_shader) const override { return ""; } void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override {} - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override { return RID(); } + void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} + RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); } RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 0f5af96417..22e3bbdb00 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -334,6 +334,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; const RenderElementInfo &element_info = p_params->element_info[i]; + if (surf->owner->instance_count == 0) { + continue; + } + push_constant.base_index = i + p_params->element_offset; RID material_uniform_set; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index b74d7f9c31..61f2031a70 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -336,11 +336,20 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { valid = true; } -void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } @@ -576,6 +585,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.renames["CUSTOM1"] = "custom1_attrib"; actions.renames["CUSTOM2"] = "custom2_attrib"; actions.renames["CUSTOM3"] = "custom3_attrib"; + actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; // not implemented but need these just in case code is in the shaders actions.renames["VIEW_INDEX"] = "0"; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index b09bd7e065..f2a55939f4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -135,7 +135,7 @@ public: uint32_t ubo_size; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -166,7 +166,7 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 95f5b46831..f23a386acf 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -1821,6 +1821,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr const RenderElementInfo &element_info = p_params->element_info[i]; const GeometryInstanceForwardMobile *inst = surf->owner; + if (inst->instance_count == 0) { + continue; + } + uint32_t base_spec_constants = p_params->spec_constant_base_flags; // GeometryInstanceForwardMobile::PushConstant push_constant = inst->push_constant; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 16d650a540..5d5cb7a6b7 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -325,11 +325,20 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { valid = true; } -void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } @@ -564,6 +573,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.renames["CUSTOM1"] = "custom1_attrib"; actions.renames["CUSTOM2"] = "custom2_attrib"; actions.renames["CUSTOM3"] = "custom3_attrib"; + actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index e1c10f0206..392fac1e3e 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -111,7 +111,7 @@ public: uint32_t ubo_size; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -141,7 +141,7 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 13a3e814f6..d013099cce 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -758,6 +758,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend instance_count = storage->multimesh_get_instances_to_draw(multimesh); + if (instance_count == 0) { + break; + } + RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET); push_constant.flags |= 1; //multimesh, trails disabled @@ -2120,11 +2124,20 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { valid = true; } -void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index ec7d7e2854..26ccbd3bf5 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -173,14 +173,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t ubo_size; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; bool uses_screen_texture = false; bool uses_sdf = false; bool uses_time = false; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 0ca2f051fa..b8e9f40bc4 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2086,7 +2086,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende ERR_FAIL_COND(!rb); RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); - //glow (if enabled) + // Glow and override exposure (if enabled). CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects); bool can_use_effects = rb->width >= 8 && rb->height >= 8; @@ -2102,7 +2102,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende EffectsRD::BokehBuffers buffers; - // textures we use + // Textures we use. buffers.base_texture_size = Size2i(rb->width, rb->height); buffers.base_texture = rb->texture; buffers.depth_texture = rb->depth_texture; @@ -2114,7 +2114,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (can_use_storage) { storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); } else { - // set framebuffers + // Set framebuffers. buffers.base_fb = rb->texture_fb; buffers.secondary_fb = rb->weight_buffers[1].fb; buffers.half_fb[0] = rb->weight_buffers[2].fb; @@ -2124,7 +2124,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende buffers.weight_texture[2] = rb->weight_buffers[2].weight; buffers.weight_texture[3] = rb->weight_buffers[3].weight; - // set weight buffers + // Set weight buffers. buffers.base_weight_fb = rb->base_weight_fb; storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); @@ -2147,13 +2147,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } else { storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); } - //swap final reduce with prev luminance + // Swap final reduce with prev luminance. SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); if (!can_use_storage) { SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]); } - RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on + RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on. RD::get_singleton()->draw_command_end_label(); } @@ -2207,7 +2207,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende { RD::get_singleton()->draw_command_begin_label("Tonemap"); - //tonemap EffectsRD::TonemapSettings tonemap; if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) { @@ -2246,6 +2245,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.exposure = env->exposure; } + if (camfx && camfx->override_exposure_enabled) { + tonemap.exposure = camfx->override_exposure; + } + tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); @@ -2280,6 +2283,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr ERR_FAIL_COND(!rb); RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); + // Override exposure (if enabled). + CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects); bool can_use_effects = rb->width >= 8 && rb->height >= 8; @@ -2293,6 +2298,10 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr tonemap.white = env->white; } + if (camfx && camfx->override_exposure_enabled) { + tonemap.exposure = camfx->override_exposure; + } + // We don't support glow or auto exposure here, if they are needed, don't use subpasses! // The problem is that we need to use the result so far and process them before we can // apply this to our results. @@ -3549,11 +3558,20 @@ void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) { valid = true; } -void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index baa0144d43..740e0e75ce 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -879,12 +879,12 @@ private: String path; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; bool uses_time; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index ce41e191e2..a9c39fb937 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -137,11 +137,20 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { valid = true; } -void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 7f563c9bc4..8689395bea 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -118,7 +118,7 @@ private: String path; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; bool uses_time; bool uses_position; @@ -127,7 +127,7 @@ private: bool uses_light; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 5c7fee7ec9..04753d7a9b 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -1440,8 +1440,10 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) { } if (shader->data) { - for (const KeyValue<StringName, RID> &E : shader->default_texture_parameter) { - shader->data->set_default_texture_param(E.key, E.value); + for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { + for (const KeyValue<int, RID> &E2 : E.value) { + shader->data->set_default_texture_param(E.key, E2.value, E2.key); + } } } } @@ -1471,17 +1473,26 @@ void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> * } } -void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { +void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); if (p_texture.is_valid() && texture_owner.owns(p_texture)) { - shader->default_texture_parameter[p_name] = p_texture; + if (!shader->default_texture_parameter.has(p_name)) { + shader->default_texture_parameter[p_name] = Map<int, RID>(); + } + shader->default_texture_parameter[p_name][p_index] = p_texture; } else { - shader->default_texture_parameter.erase(p_name); + if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { + shader->default_texture_parameter[p_name].erase(p_index); + + if (shader->default_texture_parameter[p_name].is_empty()) { + shader->default_texture_parameter.erase(p_name); + } + } } if (shader->data) { - shader->data->set_default_texture_param(p_name, p_texture); + shader->data->set_default_texture_param(p_name, p_texture, p_index); } for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); @@ -1489,11 +1500,11 @@ void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const Str } } -RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { +RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, RID()); - if (shader->default_texture_parameter.has(p_name)) { - return shader->default_texture_parameter[p_name]; + if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { + return shader->default_texture_parameter[p_name][p_index]; } return RID(); @@ -2610,7 +2621,7 @@ RendererStorageRD::MaterialData::~MaterialData() { } } -void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { +void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton; #ifdef TOOLS_ENABLED Texture *roughness_detect_texture = nullptr; @@ -2673,19 +2684,19 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari if (uniform_array_size > 0) { if (textures.size() < uniform_array_size) { - const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name); + const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); for (int j = textures.size(); j < uniform_array_size; j++) { - if (W) { - textures.push_back(W->get()); + if (W && W->get().has(j)) { + textures.push_back(W->get()[j]); } else { textures.push_back(RID()); } } } } else if (textures.is_empty()) { - const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name); - if (W) { - textures.push_back(W->get()); + const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + if (W && W->get().has(0)) { + textures.push_back(W->get()[0]); } } } @@ -2833,7 +2844,7 @@ void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_ } } -bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { +bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (uniform_buffer.is_valid()) { @@ -2857,7 +2868,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St //check whether buffer changed if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), false); + update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true); RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); } @@ -5748,11 +5759,20 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) { valid = true; } -void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index f13bd4a7f4..2cd3a01c66 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -135,7 +135,7 @@ public: struct ShaderData { virtual void set_code(const String &p_Code) = 0; - virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0; + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0; @@ -152,7 +152,7 @@ public: struct MaterialData { void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); virtual void set_render_priority(int p_priority) = 0; virtual void set_next_pass(RID p_pass) = 0; @@ -160,7 +160,7 @@ public: virtual ~MaterialData(); //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); void free_parameters_uniform_set(RID p_uniform_set); private: @@ -374,7 +374,7 @@ private: ShaderData *data; String code; ShaderType type; - Map<StringName, RID> default_texture_parameter; + Map<StringName, Map<int, RID>> default_texture_parameter; Set<Material *> owners; }; @@ -883,14 +883,14 @@ private: String path; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; RID pipeline; bool uses_time; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; @@ -1414,8 +1414,8 @@ public: String shader_get_code(RID p_shader) const; void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture); - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const; + void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index); + RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const; Variant shader_get_param_default(RID p_shader, const StringName &p_param) const; void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 4119e98d15..20982a466c 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -6,6 +6,8 @@ #include "scene_forward_clustered_inc.glsl" +#define SHADER_IS_SRGB false + /* INPUT ATTRIBS */ layout(location = 0) in vec3 vertex_attrib; @@ -358,6 +360,8 @@ void main() { #VERSION_DEFINES +#define SHADER_IS_SRGB false + /* Specialization Constants (Toggles) */ layout(constant_id = 0) const bool sc_use_forward_gi = false; @@ -1529,7 +1533,7 @@ void main() { float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0; - light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, + light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1540,7 +1544,7 @@ void main() { transmittance_z, #endif #ifdef LIGHT_RIM_USED - rim, rim_tint, albedo, + rim, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1548,9 +1552,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } @@ -1603,7 +1604,7 @@ void main() { shadow = blur_shadow(shadow); - light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, + light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1615,7 +1616,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1623,9 +1623,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } @@ -1679,7 +1676,7 @@ void main() { shadow = blur_shadow(shadow); - light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, + light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1691,7 +1688,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1699,9 +1695,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index b26489ddf1..d22f936a35 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -73,7 +73,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) { return mix(vec3(dielectric), albedo, vec3(metallic)); } -void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, +void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -84,7 +84,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float transmittance_z, #endif #ifdef LIGHT_RIM_USED - float rim, float rim_tint, vec3 rim_color, + float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED float clearcoat, float clearcoat_gloss, @@ -92,9 +92,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #ifdef LIGHT_ANISOTROPY_USED vec3 B, vec3 T, float anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif inout vec3 diffuse_light, inout vec3 specular_light) { vec4 orms_unpacked = unpackUnorm4x8(orms); @@ -171,7 +168,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #if defined(LIGHT_RIM_USED) float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); - diffuse_light += rim_light * rim * mix(vec3(1.0), rim_color, rim_tint) * light_color; + diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color; #endif #ifdef LIGHT_TRANSMITTANCE_USED @@ -577,7 +574,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { return 1.0; } -void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, +void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -587,7 +584,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float transmittance_boost, #endif #ifdef LIGHT_RIM_USED - float rim, float rim_tint, vec3 rim_color, + float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED float clearcoat, float clearcoat_gloss, @@ -595,9 +592,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED vec3 binormal, vec3 tangent, float anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = omni_lights.data[idx].position - vertex; float light_length = length(light_rel_vec); @@ -703,7 +697,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v light_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -714,7 +708,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v transmittance_z, #endif #ifdef LIGHT_RIM_USED - rim * omni_attenuation, rim_tint, rim_color, + rim * omni_attenuation, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -722,9 +716,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } @@ -823,7 +814,7 @@ vec2 normal_to_panorama(vec3 n) { return panorama_coords; } -void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, +void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -833,7 +824,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float transmittance_boost, #endif #ifdef LIGHT_RIM_USED - float rim, float rim_tint, vec3 rim_color, + float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED float clearcoat, float clearcoat_gloss, @@ -841,9 +832,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED vec3 binormal, vec3 tangent, float anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = spot_lights.data[idx].position - vertex; @@ -910,7 +898,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v } light_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -921,7 +909,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v transmittance_z, #endif #ifdef LIGHT_RIM_USED - rim * spot_attenuation, rim_tint, rim_color, + rim * spot_attenuation, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -929,9 +917,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 2f5cc58619..b6fd89d912 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -7,6 +7,8 @@ /* Include our forward mobile UBOs definitions etc. */ #include "scene_forward_mobile_inc.glsl" +#define SHADER_IS_SRGB false + /* INPUT ATTRIBS */ layout(location = 0) in vec3 vertex_attrib; @@ -370,6 +372,8 @@ void main() { #VERSION_DEFINES +#define SHADER_IS_SRGB false + /* Specialization Constants */ #if !defined(MODE_RENDER_DEPTH) @@ -1345,7 +1349,7 @@ void main() { #endif blur_shadow(shadow); - light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, + light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1358,7 +1362,7 @@ void main() { #endif */ #ifdef LIGHT_RIM_USED - rim, rim_tint, albedo, + rim, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1369,9 +1373,6 @@ void main() { #ifdef USE_SOFT_SHADOW directional_lights.data[i].size, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } @@ -1395,7 +1396,7 @@ void main() { shadow = blur_shadow(shadow); - light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, + light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1409,7 +1410,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1417,9 +1417,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } //omni lights @@ -1443,7 +1440,7 @@ void main() { shadow = blur_shadow(shadow); - light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, + light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1457,7 +1454,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1465,9 +1461,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } //spot lights diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index 2985e05e8f..8926bf24aa 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -183,8 +183,8 @@ public: virtual String shader_get_code(RID p_shader) const = 0; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0; virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 9a592a9265..f75bca600e 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -223,8 +223,8 @@ public: FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *) - FUNC3(shader_set_default_texture_param, RID, const StringName &, RID) - FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &) + FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int) + FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int) FUNC2RC(Variant, shader_get_param_default, RID, const StringName &) FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index cdf7fa530e..ae72f47a44 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1716,8 +1716,8 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list); ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default); - ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture"), &RenderingServer::shader_set_default_texture_param); - ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param"), &RenderingServer::shader_get_default_texture_param); + ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture", "index"), &RenderingServer::shader_set_default_texture_param, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param", "index"), &RenderingServer::shader_get_default_texture_param, DEFVAL(0)); BIND_ENUM_CONSTANT(SHADER_SPATIAL); BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index f35a633bf3..32ec0197ee 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -172,8 +172,8 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0; - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index = 0) const = 0; struct ShaderNativeSourceCode { struct Version { diff --git a/tests/SCsub b/tests/SCsub index 0f3c14f0bd..31466fffc1 100644 --- a/tests/SCsub +++ b/tests/SCsub @@ -22,6 +22,11 @@ if env_tests["platform"] == "windows": if env_tests.msvc: env_tests.Append(CCFLAGS=["/bigobj"]) +env_tests.add_source_files(env.tests_sources, "core/*.cpp") +env_tests.add_source_files(env.tests_sources, "core/math/*.cpp") +env_tests.add_source_files(env.tests_sources, "core/templates/*.cpp") +env_tests.add_source_files(env.tests_sources, "scene/*.cpp") +env_tests.add_source_files(env.tests_sources, "servers/*.cpp") env_tests.add_source_files(env.tests_sources, "*.cpp") lib = env_tests.add_library("tests", env.tests_sources) diff --git a/tests/test_config_file.h b/tests/core/io/test_config_file.h index e3f40e16fd..f6fbaf9a88 100644 --- a/tests/test_config_file.h +++ b/tests/core/io/test_config_file.h @@ -32,6 +32,7 @@ #define TEST_CONFIG_FILE_H #include "core/io/config_file.h" +#include "core/os/os.h" #include "tests/test_macros.h" diff --git a/tests/test_file_access.h b/tests/core/io/test_file_access.h index b3da16c1d1..4ffc57afe4 100644 --- a/tests/test_file_access.h +++ b/tests/core/io/test_file_access.h @@ -32,7 +32,8 @@ #define TEST_FILE_ACCESS_H #include "core/io/file_access.h" -#include "test_utils.h" +#include "tests/test_macros.h" +#include "tests/test_utils.h" namespace TestFileAccess { diff --git a/tests/test_image.h b/tests/core/io/test_image.h index 99c2a9380d..c4c5f1e18b 100644 --- a/tests/test_image.h +++ b/tests/core/io/test_image.h @@ -31,10 +31,10 @@ #ifndef TEST_IMAGE_H #define TEST_IMAGE_H -#include "core/io/file_access_pack.h" #include "core/io/image.h" -#include "test_utils.h" +#include "core/os/os.h" +#include "tests/test_utils.h" #include "thirdparty/doctest/doctest.h" namespace TestImage { diff --git a/tests/test_json.h b/tests/core/io/test_json.h index 3af58dfa1c..3af58dfa1c 100644 --- a/tests/test_json.h +++ b/tests/core/io/test_json.h diff --git a/tests/test_marshalls.h b/tests/core/io/test_marshalls.h index 6bd916164e..6bd916164e 100644 --- a/tests/test_marshalls.h +++ b/tests/core/io/test_marshalls.h diff --git a/tests/test_pck_packer.h b/tests/core/io/test_pck_packer.h index 06e4e64963..ae51d58522 100644 --- a/tests/test_pck_packer.h +++ b/tests/core/io/test_pck_packer.h @@ -35,6 +35,7 @@ #include "core/io/pck_packer.h" #include "core/os/os.h" +#include "tests/test_utils.h" #include "thirdparty/doctest/doctest.h" namespace TestPCKPacker { diff --git a/tests/test_resource.h b/tests/core/io/test_resource.h index cee3281995..cee3281995 100644 --- a/tests/test_resource.h +++ b/tests/core/io/test_resource.h diff --git a/tests/test_xml_parser.h b/tests/core/io/test_xml_parser.h index 55de048d6a..2d00f29ddf 100644 --- a/tests/test_xml_parser.h +++ b/tests/core/io/test_xml_parser.h @@ -31,10 +31,7 @@ #ifndef TEST_XML_PARSER_H #define TEST_XML_PARSER_H -#include <inttypes.h> - #include "core/io/xml_parser.h" -#include "core/string/ustring.h" #include "tests/test_macros.h" diff --git a/tests/test_aabb.h b/tests/core/math/test_aabb.h index 0312e185a1..b838bed171 100644 --- a/tests/test_aabb.h +++ b/tests/core/math/test_aabb.h @@ -32,10 +32,8 @@ #define TEST_AABB_H #include "core/math/aabb.h" -#include "core/string/print_string.h" -#include "tests/test_macros.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" namespace TestAABB { diff --git a/tests/test_astar.h b/tests/core/math/test_astar.h index 137c477946..2c183374ac 100644 --- a/tests/test_astar.h +++ b/tests/core/math/test_astar.h @@ -32,11 +32,6 @@ #define TEST_ASTAR_H #include "core/math/a_star.h" -#include "core/math/math_funcs.h" -#include "core/os/os.h" - -#include <math.h> -#include <stdio.h> #include "tests/test_macros.h" diff --git a/tests/test_basis.h b/tests/core/math/test_basis.h index b254d9fb7f..500c069a33 100644 --- a/tests/test_basis.h +++ b/tests/core/math/test_basis.h @@ -31,9 +31,8 @@ #ifndef TEST_BASIS_H #define TEST_BASIS_H +#include "core/math/basis.h" #include "core/math/random_number_generator.h" -#include "core/os/os.h" -#include "core/string/ustring.h" #include "tests/test_macros.h" diff --git a/tests/test_color.h b/tests/core/math/test_color.h index bffa890ae2..82cf786f7a 100644 --- a/tests/test_color.h +++ b/tests/core/math/test_color.h @@ -33,7 +33,7 @@ #include "core/math/color.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" namespace TestColor { diff --git a/tests/test_expression.h b/tests/core/math/test_expression.h index cb1d29389f..cb1d29389f 100644 --- a/tests/test_expression.h +++ b/tests/core/math/test_expression.h diff --git a/tests/test_geometry_2d.h b/tests/core/math/test_geometry_2d.h index 25af8c355e..8f6669b572 100644 --- a/tests/test_geometry_2d.h +++ b/tests/core/math/test_geometry_2d.h @@ -32,7 +32,6 @@ #define TEST_GEOMETRY_2D_H #include "core/math/geometry_2d.h" -#include "core/templates/vector.h" #include "thirdparty/doctest/doctest.h" diff --git a/tests/test_geometry_3d.h b/tests/core/math/test_geometry_3d.h index ae30737fe2..f42003ffcf 100644 --- a/tests/test_geometry_3d.h +++ b/tests/core/math/test_geometry_3d.h @@ -32,11 +32,7 @@ #define TEST_GEOMETRY_3D_H #include "core/math/geometry_3d.h" -#include "core/math/plane.h" -#include "core/math/random_number_generator.h" -#include "core/math/vector3.h" #include "tests/test_macros.h" -#include "vector" namespace TestGeometry3D { TEST_CASE("[Geometry3D] Closest Points Between Segments") { diff --git a/tests/test_math.cpp b/tests/core/math/test_math.cpp index 72272382ce..6ec9bc2473 100644 --- a/tests/test_math.cpp +++ b/tests/core/math/test_math.cpp @@ -30,23 +30,11 @@ #include "test_math.h" -#include "core/io/file_access.h" -#include "core/math/basis.h" #include "core/math/camera_matrix.h" #include "core/math/delaunay_3d.h" #include "core/math/geometry_2d.h" -#include "core/math/math_funcs.h" -#include "core/math/transform_3d.h" -#include "core/os/keyboard.h" +#include "core/os/main_loop.h" #include "core/os/os.h" -#include "core/string/print_string.h" -#include "core/string/ustring.h" -#include "core/templates/vmap.h" -#include "core/variant/method_ptrcall.h" -#include "core/variant/variant.h" -#include "scene/main/node.h" -#include "scene/resources/texture.h" -#include "servers/rendering/shader_language.h" namespace TestMath { diff --git a/tests/test_math.h b/tests/core/math/test_math.h index 4375925bd5..ab5fb6a050 100644 --- a/tests/test_math.h +++ b/tests/core/math/test_math.h @@ -31,7 +31,7 @@ #ifndef TEST_MATH_H #define TEST_MATH_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestMath { diff --git a/tests/test_random_number_generator.h b/tests/core/math/test_random_number_generator.h index 39c4771c19..39c4771c19 100644 --- a/tests/test_random_number_generator.h +++ b/tests/core/math/test_random_number_generator.h diff --git a/tests/test_rect2.h b/tests/core/math/test_rect2.h index 3d9fe5a32e..aabb950461 100644 --- a/tests/test_rect2.h +++ b/tests/core/math/test_rect2.h @@ -211,26 +211,74 @@ TEST_CASE("[Rect2] Growing") { } TEST_CASE("[Rect2] Has point") { + Rect2 rect = Rect2(0, 100, 1280, 720); CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).has_point(Vector2(500, 600)), + rect.has_point(Vector2(500, 600)), "has_point() with contained Vector2 should return the expected result."); CHECK_MESSAGE( - !Rect2(0, 100, 1280, 720).has_point(Vector2(0, 0)), + !rect.has_point(Vector2(0, 0)), "has_point() with non-contained Vector2 should return the expected result."); CHECK_MESSAGE( - Rect2(0, 100, 1280, 720).has_point(Vector2(0, 110)), - "has_point() with positive Vector2 on left edge should return the expected result."); + rect.has_point(rect.position), + "has_point() with positive size should include `position`."); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2(1, 1)), + "has_point() with positive size should include `position + (1, 1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2(1, -1)), + "has_point() with positive size should not include `position + (1, -1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size), + "has_point() with positive size should not include `position + size`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size + Vector2(1, 1)), + "has_point() with positive size should not include `position + size + (1, 1)`."); + CHECK_MESSAGE( + rect.has_point(rect.position + rect.size + Vector2(-1, -1)), + "has_point() with positive size should include `position + size + (-1, -1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size + Vector2(-1, 1)), + "has_point() with positive size should not include `position + size + (-1, 1)`."); + + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2(0, 10)), + "has_point() with point located on left edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2(rect.size.x, 10)), + "has_point() with point located on right edge should return false."); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2(10, 0)), + "has_point() with point located on top edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2(10, rect.size.y)), + "has_point() with point located on bottom edge should return false."); + + /* + // FIXME: Disabled for now until GH-37617 is fixed one way or another. + // More tests should then be written like for the positive size case. + rect = Rect2(0, 100, -1280, -720); + CHECK_MESSAGE( + rect.has_point(rect.position), + "has_point() with negative size should include `position`."); CHECK_MESSAGE( - !Rect2(0, 100, 1280, 720).has_point(Vector2(1280, 110)), - "has_point() with positive Vector2 on right edge should return the expected result."); + !rect.has_point(rect.position + rect.size), + "has_point() with negative size should not include `position + size`."); + */ + rect = Rect2(-4000, -200, 1280, 720); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2(0, 10)), + "has_point() with negative position and point located on left edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2(rect.size.x, 10)), + "has_point() with negative position and point located on right edge should return false."); CHECK_MESSAGE( - Rect2(-4000, 100, 1280, 720).has_point(Vector2(-4000, 110)), - "has_point() with negative Vector2 on left edge should return the expected result."); + rect.has_point(rect.position + Vector2(10, 0)), + "has_point() with negative position and point located on top edge should return true."); CHECK_MESSAGE( - !Rect2(-4000, 100, 1280, 720).has_point(Vector2(-2720, 110)), - "has_point() with negative Vector2 on right edge should return the expected result."); + !rect.has_point(rect.position + Vector2(10, rect.size.y)), + "has_point() with negative position and point located on bottom edge should return false."); } TEST_CASE("[Rect2] Intersection") { @@ -429,26 +477,74 @@ TEST_CASE("[Rect2i] Growing") { } TEST_CASE("[Rect2i] Has point") { + Rect2i rect = Rect2i(0, 100, 1280, 720); CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).has_point(Vector2i(500, 600)), + rect.has_point(Vector2i(500, 600)), "has_point() with contained Vector2i should return the expected result."); CHECK_MESSAGE( - !Rect2i(0, 100, 1280, 720).has_point(Vector2i(0, 0)), + !rect.has_point(Vector2i(0, 0)), "has_point() with non-contained Vector2i should return the expected result."); CHECK_MESSAGE( - Rect2i(0, 100, 1280, 720).has_point(Vector2(0, 110)), - "has_point() with positive Vector2 on left edge should return the expected result."); + rect.has_point(rect.position), + "has_point() with positive size should include `position`."); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(1, 1)), + "has_point() with positive size should include `position + (1, 1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(1, -1)), + "has_point() with positive size should not include `position + (1, -1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size), + "has_point() with positive size should not include `position + size`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size + Vector2i(1, 1)), + "has_point() with positive size should not include `position + size + (1, 1)`."); + CHECK_MESSAGE( + rect.has_point(rect.position + rect.size + Vector2i(-1, -1)), + "has_point() with positive size should include `position + size + (-1, -1)`."); + CHECK_MESSAGE( + !rect.has_point(rect.position + rect.size + Vector2i(-1, 1)), + "has_point() with positive size should not include `position + size + (-1, 1)`."); + + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(0, 10)), + "has_point() with point located on left edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(rect.size.x, 10)), + "has_point() with point located on right edge should return false."); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(10, 0)), + "has_point() with point located on top edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(10, rect.size.y)), + "has_point() with point located on bottom edge should return false."); + + /* + // FIXME: Disabled for now until GH-37617 is fixed one way or another. + // More tests should then be written like for the positive size case. + rect = Rect2i(0, 100, -1280, -720); + CHECK_MESSAGE( + rect.has_point(rect.position), + "has_point() with negative size should include `position`."); CHECK_MESSAGE( - !Rect2i(0, 100, 1280, 720).has_point(Vector2(1280, 110)), - "has_point() with positive Vector2 on right edge should return the expected result."); + !rect.has_point(rect.position + rect.size), + "has_point() with negative size should not include `position + size`."); + */ + rect = Rect2i(-4000, -200, 1280, 720); + CHECK_MESSAGE( + rect.has_point(rect.position + Vector2i(0, 10)), + "has_point() with negative position and point located on left edge should return true."); + CHECK_MESSAGE( + !rect.has_point(rect.position + Vector2i(rect.size.x, 10)), + "has_point() with negative position and point located on right edge should return false."); CHECK_MESSAGE( - Rect2i(-4000, 100, 1280, 720).has_point(Vector2(-4000, 110)), - "has_point() with negative Vector2 on left edge should return the expected result."); + rect.has_point(rect.position + Vector2i(10, 0)), + "has_point() with negative position and point located on top edge should return true."); CHECK_MESSAGE( - !Rect2i(-4000, 100, 1280, 720).has_point(Vector2(-2720, 110)), - "has_point() with negative Vector2 on right edge should return the expected result."); + !rect.has_point(rect.position + Vector2i(10, rect.size.y)), + "has_point() with negative position and point located on bottom edge should return false."); } TEST_CASE("[Rect2i] Intersection") { diff --git a/tests/test_class_db.h b/tests/core/object/test_class_db.h index 4b058a4c67..4b27905485 100644 --- a/tests/test_class_db.h +++ b/tests/core/object/test_class_db.h @@ -31,14 +31,9 @@ #ifndef TEST_CLASS_DB_H #define TEST_CLASS_DB_H -#include "core/register_core_types.h" - +#include "core/core_bind.h" #include "core/core_constants.h" -#include "core/os/os.h" -#include "core/string/string_name.h" -#include "core/string/ustring.h" -#include "core/templates/ordered_hash_map.h" -#include "core/variant/variant.h" +#include "core/object/class_db.h" #include "tests/test_macros.h" diff --git a/tests/test_method_bind.h b/tests/core/object/test_method_bind.h index 879e7949e2..c3a869a8a4 100644 --- a/tests/test_method_bind.h +++ b/tests/core/object/test_method_bind.h @@ -35,10 +35,6 @@ #include "tests/test_macros.h" -#include <inttypes.h> -#include <stdio.h> -#include <wchar.h> - namespace TestMethodBind { class MethodBindTester : public Object { diff --git a/tests/test_object.h b/tests/core/object/test_object.h index 8cb7116a20..4109ea521a 100644 --- a/tests/test_object.h +++ b/tests/core/object/test_object.h @@ -32,9 +32,11 @@ #define TEST_OBJECT_H #include "core/core_string_names.h" +#include "core/object/class_db.h" #include "core/object/object.h" +#include "core/object/script_language.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" // Declared in global namespace because of GDCLASS macro warning (Windows): // "Unqualified friend declaration referring to type outside of the nearest enclosing namespace diff --git a/tests/test_node_path.h b/tests/core/string/test_node_path.h index f30fe53c5a..0216a30f8f 100644 --- a/tests/test_node_path.h +++ b/tests/core/string/test_node_path.h @@ -33,7 +33,7 @@ #include "core/string/node_path.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" namespace TestNodePath { diff --git a/tests/test_string.h b/tests/core/string/test_string.h index 28d1089d2f..00a9a8779a 100644 --- a/tests/test_string.h +++ b/tests/core/string/test_string.h @@ -31,15 +31,7 @@ #ifndef TEST_STRING_H #define TEST_STRING_H -#include <inttypes.h> -#include <stdio.h> -#include <wchar.h> - -#include "core/io/ip_address.h" -#include "core/os/main_loop.h" -#include "core/os/os.h" #include "core/string/ustring.h" -#include "core/variant/variant.h" #include "tests/test_macros.h" @@ -498,12 +490,6 @@ TEST_CASE("[String] Splitting") { } } -TEST_CASE("[String] Erasing") { - String s = "Josephine is such a cute girl!"; - s.erase(s.find("cute "), String("cute ").length()); - CHECK(s == "Josephine is such a girl!"); -} - struct test_27_data { char const *data; char const *part; diff --git a/tests/test_translation.h b/tests/core/string/test_translation.h index 93c53bbbc9..47e06add40 100644 --- a/tests/test_translation.h +++ b/tests/core/string/test_translation.h @@ -39,7 +39,8 @@ #include "editor/import/resource_importer_csv_translation.h" #endif -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" +#include "tests/test_utils.h" namespace TestTranslation { diff --git a/tests/test_command_queue.h b/tests/core/templates/test_command_queue.h index f0d4569942..5d228f2bf6 100644 --- a/tests/test_command_queue.h +++ b/tests/core/templates/test_command_queue.h @@ -33,12 +33,10 @@ #include "core/config/project_settings.h" #include "core/math/random_number_generator.h" -#include "core/os/mutex.h" #include "core/os/os.h" -#include "core/os/semaphore.h" #include "core/os/thread.h" #include "core/templates/command_queue_mt.h" -#include "test_macros.h" +#include "tests/test_macros.h" #if !defined(NO_THREADS) diff --git a/tests/test_list.h b/tests/core/templates/test_list.h index 52d5edff70..52d5edff70 100644 --- a/tests/test_list.h +++ b/tests/core/templates/test_list.h diff --git a/tests/test_local_vector.h b/tests/core/templates/test_local_vector.h index eff2a16abc..eff2a16abc 100644 --- a/tests/test_local_vector.h +++ b/tests/core/templates/test_local_vector.h diff --git a/tests/test_lru.h b/tests/core/templates/test_lru.h index 2802754729..9359909c53 100644 --- a/tests/test_lru.h +++ b/tests/core/templates/test_lru.h @@ -32,7 +32,6 @@ #define TEST_LRU_H #include "core/templates/lru.h" -#include "core/templates/vector.h" #include "tests/test_macros.h" diff --git a/tests/test_oa_hash_map.cpp b/tests/core/templates/test_oa_hash_map.cpp index 904c01642d..904c01642d 100644 --- a/tests/test_oa_hash_map.cpp +++ b/tests/core/templates/test_oa_hash_map.cpp diff --git a/tests/test_oa_hash_map.h b/tests/core/templates/test_oa_hash_map.h index 9745802cc0..f229ac94ea 100644 --- a/tests/test_oa_hash_map.h +++ b/tests/core/templates/test_oa_hash_map.h @@ -31,7 +31,7 @@ #ifndef TEST_OA_HASH_MAP_H #define TEST_OA_HASH_MAP_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestOAHashMap { diff --git a/tests/test_ordered_hash_map.h b/tests/core/templates/test_ordered_hash_map.h index fbaaa224cf..35ce0fc656 100644 --- a/tests/test_ordered_hash_map.h +++ b/tests/core/templates/test_ordered_hash_map.h @@ -31,10 +31,7 @@ #ifndef TEST_ORDERED_HASH_MAP_H #define TEST_ORDERED_HASH_MAP_H -#include "core/os/os.h" #include "core/templates/ordered_hash_map.h" -#include "core/templates/pair.h" -#include "core/templates/vector.h" #include "tests/test_macros.h" diff --git a/tests/test_paged_array.h b/tests/core/templates/test_paged_array.h index 7efd3799f3..7efd3799f3 100644 --- a/tests/test_paged_array.h +++ b/tests/core/templates/test_paged_array.h diff --git a/tests/test_vector.h b/tests/core/templates/test_vector.h index bfdf389aa7..bfdf389aa7 100644 --- a/tests/test_vector.h +++ b/tests/core/templates/test_vector.h diff --git a/tests/test_crypto.h b/tests/core/test_crypto.h index 8da8c75544..3b909c7df8 100644 --- a/tests/test_crypto.h +++ b/tests/core/test_crypto.h @@ -33,7 +33,6 @@ #include "core/crypto/crypto.h" #include "tests/test_macros.h" -#include <stdio.h> namespace TestCrypto { diff --git a/tests/test_hashing_context.h b/tests/core/test_hashing_context.h index 728a5f2cfa..728a5f2cfa 100644 --- a/tests/test_hashing_context.h +++ b/tests/core/test_hashing_context.h diff --git a/tests/test_time.h b/tests/core/test_time.h index 28f1cb2f20..28f1cb2f20 100644 --- a/tests/test_time.h +++ b/tests/core/test_time.h diff --git a/tests/test_array.h b/tests/core/variant/test_array.h index 05b4eaea2a..298bd2ff63 100644 --- a/tests/test_array.h +++ b/tests/core/variant/test_array.h @@ -31,13 +31,7 @@ #ifndef TEST_ARRAY_H #define TEST_ARRAY_H -#include "core/object/class_db.h" -#include "core/object/script_language.h" -#include "core/templates/hashfuncs.h" -#include "core/templates/vector.h" #include "core/variant/array.h" -#include "core/variant/container_type_validate.h" -#include "core/variant/variant.h" #include "tests/test_macros.h" #include "tests/test_tools.h" diff --git a/tests/test_dictionary.h b/tests/core/variant/test_dictionary.h index 64d1d68e21..65079698a3 100644 --- a/tests/test_dictionary.h +++ b/tests/core/variant/test_dictionary.h @@ -31,10 +31,7 @@ #ifndef TEST_DICTIONARY_H #define TEST_DICTIONARY_H -#include "core/templates/ordered_hash_map.h" -#include "core/templates/safe_refcount.h" #include "core/variant/dictionary.h" -#include "core/variant/variant.h" #include "tests/test_macros.h" namespace TestDictionary { diff --git a/tests/test_variant.h b/tests/core/variant/test_variant.h index 0d16fa092c..0d16fa092c 100644 --- a/tests/test_variant.h +++ b/tests/core/variant/test_variant.h diff --git a/tests/test_code_edit.h b/tests/scene/test_code_edit.h index 62235ed0ae..a95dd02ba5 100644 --- a/tests/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -31,12 +31,7 @@ #ifndef TEST_CODE_EDIT_H #define TEST_CODE_EDIT_H -#include "core/input/input_map.h" -#include "core/object/message_queue.h" -#include "core/os/keyboard.h" -#include "core/string/string_builder.h" #include "scene/gui/code_edit.h" -#include "scene/resources/default_theme/default_theme.h" #include "tests/test_macros.h" @@ -2678,18 +2673,18 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { /* Check typing inserts closing pair. */ code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETLEFT); + SEND_GUI_KEY_EVENT(code_edit, Key::BRACKETLEFT); CHECK(code_edit->get_line(0) == "[]"); /* Should first match and insert smaller key. */ code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); CHECK(code_edit->get_line(0) == "''"); CHECK(code_edit->get_caret_column() == 1); /* Move out from centre, Should match and insert larger key. */ SEND_GUI_ACTION(code_edit, "ui_text_caret_right"); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); CHECK(code_edit->get_line(0) == "''''''"); CHECK(code_edit->get_caret_column() == 3); @@ -2698,30 +2693,30 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { CHECK(code_edit->get_line(0).is_empty()); /* If in between and typing close key should "skip". */ - SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETLEFT); + SEND_GUI_KEY_EVENT(code_edit, Key::BRACKETLEFT); CHECK(code_edit->get_line(0) == "[]"); CHECK(code_edit->get_caret_column() == 1); - SEND_GUI_KEY_EVENT(code_edit, KEY_BRACKETRIGHT); + SEND_GUI_KEY_EVENT(code_edit, Key::BRACKETRIGHT); CHECK(code_edit->get_line(0) == "[]"); CHECK(code_edit->get_caret_column() == 2); /* If current is char and inserting a string, do not autocomplete. */ code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_A); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::A); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); CHECK(code_edit->get_line(0) == "A'"); /* If in comment, do not complete. */ code_edit->add_comment_delimiter("#", ""); code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_NUMBERSIGN); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::NUMBERSIGN); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); CHECK(code_edit->get_line(0) == "#'"); /* If in string, and inserting string do not complete. */ code_edit->clear(); - SEND_GUI_KEY_EVENT(code_edit, KEY_APOSTROPHE); - SEND_GUI_KEY_EVENT(code_edit, KEY_QUOTEDBL); + SEND_GUI_KEY_EVENT(code_edit, Key::APOSTROPHE); + SEND_GUI_KEY_EVENT(code_edit, Key::QUOTEDBL); CHECK(code_edit->get_line(0) == "'\"'"); } @@ -2867,7 +2862,7 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { SEND_GUI_ACTION(code_edit, "ui_down"); CHECK(code_edit->get_code_completion_selected_index() == 0); - SEND_GUI_KEY_EVENT(code_edit, KEY_T); + SEND_GUI_KEY_EVENT(code_edit, Key::T); CHECK(code_edit->get_code_completion_selected_index() == 0); SEND_GUI_ACTION(code_edit, "ui_left"); @@ -2881,14 +2876,14 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { Point2 caret_pos = code_edit->get_caret_draw_pos(); caret_pos.y -= code_edit->get_line_height(); - SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_WHEEL_DOWN, MOUSE_BUTTON_NONE); + SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::WHEEL_DOWN, MouseButton::NONE); CHECK(code_edit->get_code_completion_selected_index() == 1); - SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_WHEEL_UP, MOUSE_BUTTON_NONE); + SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::WHEEL_UP, MouseButton::NONE); CHECK(code_edit->get_code_completion_selected_index() == 0); /* Single click selects. */ - SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT); + SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::LEFT, MouseButton::MASK_LEFT); CHECK(code_edit->get_code_completion_selected_index() == 2); /* Double click inserts. */ @@ -3096,15 +3091,15 @@ TEST_CASE("[SceneTree][CodeEdit] symbol lookup") { Point2 caret_pos = code_edit->get_caret_draw_pos(); caret_pos.x += 55; - SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE); + SEND_GUI_MOUSE_EVENT(code_edit, caret_pos, MouseButton::NONE, MouseButton::NONE); CHECK(code_edit->get_text_for_symbol_lookup() == "this is s" + String::chr(0xFFFF) + "ome text"); SIGNAL_WATCH(code_edit, "symbol_validate"); #ifdef OSX_ENABLED - SEND_GUI_KEY_EVENT(code_edit, KEY_META); + SEND_GUI_KEY_EVENT(code_edit, Key::META); #else - SEND_GUI_KEY_EVENT(code_edit, KEY_CTRL); + SEND_GUI_KEY_EVENT(code_edit, Key::CTRL); #endif Array signal_args; diff --git a/tests/test_curve.h b/tests/scene/test_curve.h index e079905e35..60eafad460 100644 --- a/tests/test_curve.h +++ b/tests/scene/test_curve.h @@ -33,7 +33,7 @@ #include "scene/resources/curve.h" -#include "thirdparty/doctest/doctest.h" +#include "tests/test_macros.h" namespace TestCurve { diff --git a/tests/test_gradient.h b/tests/scene/test_gradient.h index 8eaa6b2b64..fc595b02f2 100644 --- a/tests/test_gradient.h +++ b/tests/scene/test_gradient.h @@ -31,8 +31,6 @@ #ifndef TEST_GRADIENT_H #define TEST_GRADIENT_H -#include "core/math/color.h" -#include "core/object/class_db.h" #include "scene/resources/gradient.h" #include "thirdparty/doctest/doctest.h" diff --git a/tests/test_gui.cpp b/tests/scene/test_gui.cpp index 0ec8aa78c4..5bd9390cb7 100644 --- a/tests/test_gui.cpp +++ b/tests/scene/test_gui.cpp @@ -32,29 +32,18 @@ #include "test_gui.h" -#include "core/io/image_loader.h" -#include "core/os/os.h" -#include "core/string/print_string.h" -#include "scene/2d/sprite_2d.h" #include "scene/gui/button.h" -#include "scene/gui/control.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" #include "scene/gui/panel.h" -#include "scene/gui/popup_menu.h" #include "scene/gui/progress_bar.h" #include "scene/gui/rich_text_label.h" #include "scene/gui/scroll_bar.h" #include "scene/gui/spin_box.h" #include "scene/gui/tab_container.h" -#include "scene/gui/texture_rect.h" #include "scene/gui/tree.h" -#include "scene/main/scene_tree.h" - -#include "scene/3d/camera_3d.h" -#include "scene/main/window.h" namespace TestGUI { @@ -267,4 +256,4 @@ MainLoop *test() { } } // namespace TestGUI -#endif +#endif // _3D_DISABLED diff --git a/tests/test_gui.h b/tests/scene/test_gui.h index e5c40de7e8..84bce620e2 100644 --- a/tests/test_gui.h +++ b/tests/scene/test_gui.h @@ -31,7 +31,7 @@ #ifndef TEST_GUI_H #define TEST_GUI_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestGUI { diff --git a/tests/test_path_3d.h b/tests/scene/test_path_3d.h index 9961ae6e97..1fcef3adde 100644 --- a/tests/test_path_3d.h +++ b/tests/scene/test_path_3d.h @@ -32,7 +32,6 @@ #define TEST_PATH_3D_H #include "scene/3d/path_3d.h" -#include "scene/resources/curve.h" #include "tests/test_macros.h" diff --git a/tests/test_path_follow_2d.h b/tests/scene/test_path_follow_2d.h index 388b690060..ddfcc5552a 100644 --- a/tests/test_path_follow_2d.h +++ b/tests/scene/test_path_follow_2d.h @@ -32,7 +32,6 @@ #define TEST_PATH_FOLLOW_2D_H #include "scene/2d/path_2d.h" -#include "scene/resources/curve.h" #include "tests/test_macros.h" diff --git a/tests/test_path_follow_3d.h b/tests/scene/test_path_follow_3d.h index b6b4c88222..6a505dbb39 100644 --- a/tests/test_path_follow_3d.h +++ b/tests/scene/test_path_follow_3d.h @@ -32,7 +32,6 @@ #define TEST_PATH_FOLLOW_3D_H #include "scene/3d/path_3d.h" -#include "scene/resources/curve.h" #include "tests/test_macros.h" diff --git a/tests/test_physics_2d.cpp b/tests/servers/test_physics_2d.cpp index f6619db8fd..06aa88b5c0 100644 --- a/tests/test_physics_2d.cpp +++ b/tests/servers/test_physics_2d.cpp @@ -31,11 +31,6 @@ #include "test_physics_2d.h" #include "core/os/main_loop.h" -#include "core/os/os.h" -#include "core/string/print_string.h" -#include "core/templates/map.h" -#include "scene/resources/texture.h" -#include "servers/display_server.h" #include "servers/physics_server_2d.h" #include "servers/rendering_server.h" @@ -201,10 +196,10 @@ protected: if (mb->is_pressed()) { Point2 p = mb->get_position(); - if (mb->get_button_index() == 1) { + if (mb->get_button_index() == MouseButton::LEFT) { ray_to = p; _do_ray_query(); - } else if (mb->get_button_index() == 2) { + } else if (mb->get_button_index() == MouseButton::RIGHT) { ray_from = p; _do_ray_query(); } @@ -216,10 +211,10 @@ protected: if (mm.is_valid()) { Point2 p = mm->get_position(); - if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT) { + if ((mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { ray_to = p; _do_ray_query(); - } else if (mm->get_button_mask() & MOUSE_BUTTON_MASK_RIGHT) { + } else if ((mm->get_button_mask() & MouseButton::MASK_RIGHT) != MouseButton::NONE) { ray_from = p; _do_ray_query(); } diff --git a/tests/test_physics_2d.h b/tests/servers/test_physics_2d.h index 966d49200a..2ae1053a03 100644 --- a/tests/test_physics_2d.h +++ b/tests/servers/test_physics_2d.h @@ -31,7 +31,7 @@ #ifndef TEST_PHYSICS_2D_H #define TEST_PHYSICS_2D_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestPhysics2D { diff --git a/tests/test_physics_3d.cpp b/tests/servers/test_physics_3d.cpp index d839ae26b7..7cb74b1ee3 100644 --- a/tests/test_physics_3d.cpp +++ b/tests/servers/test_physics_3d.cpp @@ -31,12 +31,8 @@ #include "test_physics_3d.h" #include "core/math/convex_hull.h" -#include "core/math/math_funcs.h" +#include "core/math/geometry_3d.h" #include "core/os/main_loop.h" -#include "core/os/os.h" -#include "core/string/print_string.h" -#include "core/templates/map.h" -#include "servers/display_server.h" #include "servers/physics_server_3d.h" #include "servers/rendering_server.h" @@ -249,12 +245,12 @@ protected: public: virtual void input_event(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> mm = p_event; - if (mm.is_valid() && mm->get_button_mask() & 4) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { ofs_y -= mm->get_relative().y / 200.0; ofs_x += mm->get_relative().x / 200.0; } - if (mm.is_valid() && mm->get_button_mask() & 1) { + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) { real_t y = -mm->get_relative().y / 20.0; real_t x = mm->get_relative().x / 20.0; diff --git a/tests/test_physics_3d.h b/tests/servers/test_physics_3d.h index b6b66f350e..b86327cdb4 100644 --- a/tests/test_physics_3d.h +++ b/tests/servers/test_physics_3d.h @@ -31,7 +31,7 @@ #ifndef TEST_PHYSICS_H #define TEST_PHYSICS_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestPhysics3D { diff --git a/tests/test_render.cpp b/tests/servers/test_render.cpp index 21b4da9b3b..183f049238 100644 --- a/tests/test_render.cpp +++ b/tests/servers/test_render.cpp @@ -31,12 +31,7 @@ #include "test_render.h" #include "core/math/convex_hull.h" -#include "core/math/math_funcs.h" -#include "core/os/keyboard.h" #include "core/os/main_loop.h" -#include "core/os/os.h" -#include "core/string/print_string.h" -#include "servers/display_server.h" #include "servers/rendering_server.h" #define OBJECT_COUNT 50 diff --git a/tests/test_render.h b/tests/servers/test_render.h index 35bb383773..1d773cb347 100644 --- a/tests/test_render.h +++ b/tests/servers/test_render.h @@ -31,11 +31,11 @@ #ifndef TEST_RENDER_H #define TEST_RENDER_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestRender { MainLoop *test(); } -#endif +#endif // TEST_RENDER_H diff --git a/tests/test_shader_lang.cpp b/tests/servers/test_shader_lang.cpp index 5598852f29..0591bf6adf 100644 --- a/tests/test_shader_lang.cpp +++ b/tests/servers/test_shader_lang.cpp @@ -30,13 +30,8 @@ #include "test_shader_lang.h" -#include "core/io/file_access.h" #include "core/os/main_loop.h" #include "core/os/os.h" - -#include "core/string/print_string.h" -#include "scene/gui/control.h" -#include "scene/gui/text_edit.h" #include "servers/rendering/shader_language.h" typedef ShaderLanguage SL; diff --git a/tests/test_shader_lang.h b/tests/servers/test_shader_lang.h index 46a2e6af35..de7ec002b6 100644 --- a/tests/test_shader_lang.h +++ b/tests/servers/test_shader_lang.h @@ -31,7 +31,7 @@ #ifndef TEST_SHADER_LANG_H #define TEST_SHADER_LANG_H -#include "core/os/main_loop.h" +class MainLoop; namespace TestShaderLang { diff --git a/tests/test_text_server.h b/tests/servers/test_text_server.h index 4edffe3711..4edffe3711 100644 --- a/tests/test_text_server.h +++ b/tests/servers/test_text_server.h diff --git a/tests/test_macros.h b/tests/test_macros.h index 6968f9df1f..b04c2117b7 100644 --- a/tests/test_macros.h +++ b/tests/test_macros.h @@ -31,10 +31,8 @@ #ifndef TEST_MACROS_H #define TEST_MACROS_H -#include "core/object/callable_method_pointer.h" -#include "core/object/class_db.h" -#include "core/string/print_string.h" -#include "core/templates/map.h" +#include "core/input/input_map.h" +#include "core/object/message_queue.h" #include "core/variant/variant.h" // See documentation for doctest at: @@ -135,7 +133,7 @@ int register_test_command(String p_command, TestFunc p_function); // Utility macros to send an event actions to a given object // Requires Message Queue and InputMap to be setup. // SEND_GUI_ACTION - takes an object and a input map key. e.g SEND_GUI_ACTION(code_edit, "ui_text_newline"). -// SEND_GUI_KEY_EVENT - takes an object and a keycode set. e.g SEND_GUI_KEY_EVENT(code_edit, KEY_A | KEY_MASK_CMD). +// SEND_GUI_KEY_EVENT - takes an object and a keycode set. e.g SEND_GUI_KEY_EVENT(code_edit, Key::A | KeyModifierMask::CMD). // SEND_GUI_MOUSE_EVENT - takes an object, position, mouse button and mouse mask e.g SEND_GUI_MOUSE_EVENT(code_edit, Vector2(50, 50), MOUSE_BUTTON_NONE, MOUSE_BUTTON_NONE); // SEND_GUI_DOUBLE_CLICK - takes an object and a postion. e.g SEND_GUI_DOUBLE_CLICK(code_edit, Vector2(50, 50)); @@ -174,7 +172,7 @@ int register_test_command(String p_command, TestFunc p_function); #define SEND_GUI_DOUBLE_CLICK(m_object, m_local_pos) \ { \ - _CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_LEFT); \ + _CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, MouseButton::LEFT, MouseButton::LEFT); \ event->set_double_click(true); \ m_object->get_viewport()->push_input(event); \ MessageQueue::get_singleton()->flush(); \ diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 341fb1af61..a09be08de8 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -30,62 +30,62 @@ #include "test_main.h" -#include "core/templates/list.h" - -#include "test_aabb.h" -#include "test_array.h" -#include "test_astar.h" -#include "test_basis.h" -#include "test_class_db.h" -#include "test_code_edit.h" -#include "test_color.h" -#include "test_command_queue.h" -#include "test_config_file.h" -#include "test_crypto.h" -#include "test_curve.h" -#include "test_dictionary.h" -#include "test_expression.h" -#include "test_file_access.h" -#include "test_geometry_2d.h" -#include "test_geometry_3d.h" -#include "test_gradient.h" -#include "test_gui.h" -#include "test_hashing_context.h" -#include "test_image.h" -#include "test_json.h" -#include "test_list.h" -#include "test_local_vector.h" -#include "test_lru.h" -#include "test_marshalls.h" -#include "test_math.h" -#include "test_method_bind.h" -#include "test_node_path.h" -#include "test_oa_hash_map.h" -#include "test_object.h" -#include "test_ordered_hash_map.h" -#include "test_paged_array.h" -#include "test_path_3d.h" -#include "test_pck_packer.h" -#include "test_physics_2d.h" -#include "test_physics_3d.h" -#include "test_random_number_generator.h" -#include "test_rect2.h" -#include "test_render.h" -#include "test_resource.h" -#include "test_shader_lang.h" -#include "test_string.h" -#include "test_text_server.h" -#include "test_time.h" -#include "test_translation.h" -#include "test_validate_testing.h" -#include "test_variant.h" -#include "test_vector.h" -#include "test_xml_parser.h" +#include "tests/core/io/test_config_file.h" +#include "tests/core/io/test_file_access.h" +#include "tests/core/io/test_image.h" +#include "tests/core/io/test_json.h" +#include "tests/core/io/test_marshalls.h" +#include "tests/core/io/test_pck_packer.h" +#include "tests/core/io/test_resource.h" +#include "tests/core/io/test_xml_parser.h" +#include "tests/core/math/test_aabb.h" +#include "tests/core/math/test_astar.h" +#include "tests/core/math/test_basis.h" +#include "tests/core/math/test_color.h" +#include "tests/core/math/test_expression.h" +#include "tests/core/math/test_geometry_2d.h" +#include "tests/core/math/test_geometry_3d.h" +#include "tests/core/math/test_math.h" +#include "tests/core/math/test_random_number_generator.h" +#include "tests/core/math/test_rect2.h" +#include "tests/core/object/test_class_db.h" +#include "tests/core/object/test_method_bind.h" +#include "tests/core/object/test_object.h" +#include "tests/core/string/test_node_path.h" +#include "tests/core/string/test_string.h" +#include "tests/core/string/test_translation.h" +#include "tests/core/templates/test_command_queue.h" +#include "tests/core/templates/test_list.h" +#include "tests/core/templates/test_local_vector.h" +#include "tests/core/templates/test_lru.h" +#include "tests/core/templates/test_oa_hash_map.h" +#include "tests/core/templates/test_ordered_hash_map.h" +#include "tests/core/templates/test_paged_array.h" +#include "tests/core/templates/test_vector.h" +#include "tests/core/test_crypto.h" +#include "tests/core/test_hashing_context.h" +#include "tests/core/test_time.h" +#include "tests/core/variant/test_array.h" +#include "tests/core/variant/test_dictionary.h" +#include "tests/core/variant/test_variant.h" +#include "tests/scene/test_code_edit.h" +#include "tests/scene/test_curve.h" +#include "tests/scene/test_gradient.h" +#include "tests/scene/test_gui.h" +#include "tests/scene/test_path_3d.h" +#include "tests/servers/test_physics_2d.h" +#include "tests/servers/test_physics_3d.h" +#include "tests/servers/test_render.h" +#include "tests/servers/test_shader_lang.h" +#include "tests/servers/test_text_server.h" +#include "tests/test_validate_testing.h" #include "modules/modules_tests.gen.h" #include "tests/test_macros.h" +#include "scene/resources/default_theme/default_theme.h" + int test_main(int argc, char *argv[]) { bool run_tests = true; diff --git a/tests/test_tools.h b/tests/test_tools.h index ec18610f04..e1192458d0 100644 --- a/tests/test_tools.h +++ b/tests/test_tools.h @@ -31,8 +31,6 @@ #ifndef TEST_TOOLS_H #define TEST_TOOLS_H -#include "core/error/error_macros.h" - struct ErrorDetector { ErrorDetector() { eh.errfunc = _detect_error; diff --git a/tests/test_utils.cpp b/tests/test_utils.cpp index 1666a257a9..890dea3ee1 100644 --- a/tests/test_utils.cpp +++ b/tests/test_utils.cpp @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "test_utils.h" +#include "tests/test_utils.h" #include "core/os/os.h" diff --git a/tests/test_utils.h b/tests/test_utils.h index f05ab0bdb1..ccebe2e449 100644 --- a/tests/test_utils.h +++ b/tests/test_utils.h @@ -31,7 +31,7 @@ #ifndef TEST_UTILS_H #define TEST_UTILS_H -#include "core/string/ustring.h" +class String; namespace TestUtils { diff --git a/version.py b/version.py index 517a47f568..663f90b942 100644 --- a/version.py +++ b/version.py @@ -7,3 +7,4 @@ status = "dev" module_config = "" year = 2021 website = "https://godotengine.org" +docs = "latest" |