diff options
123 files changed, 4685 insertions, 1928 deletions
diff --git a/core/color.cpp b/core/color.cpp index dd8b13c047..78b11a84df 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -250,6 +250,14 @@ Color Color::html(const String &p_color) { return Color(); if (color[0] == '#') color = color.substr(1, color.length() - 1); + if (color.length() == 3 || color.length() == 4) { + String exp_color; + for (int i = 0; i < color.length(); i++) { + exp_color += color[i]; + exp_color += color[i]; + } + color = exp_color; + } bool alpha = false; diff --git a/core/hash_map.h b/core/hash_map.h index 37391a4c83..e100d7a904 100644 --- a/core/hash_map.h +++ b/core/hash_map.h @@ -37,39 +37,6 @@ #include "os/memory.h" #include "ustring.h" -struct HashMapHasherDefault { - static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } - static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } - static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } - - static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } - static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); } - static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; } - //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); } -}; - -template <typename T> -struct HashMapComparatorDefault { - static bool compare(const T &p_lhs, const T &p_rhs) { - return p_lhs == p_rhs; - } - - bool compare(const float &p_lhs, const float &p_rhs) { - return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); - } - - bool compare(const double &p_lhs, const double &p_rhs) { - return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); - } -}; - /** * @class HashMap * @author Juan Linietsky <reduzio@gmail.com> diff --git a/core/hashfuncs.h b/core/hashfuncs.h index 56d40f1dd7..2880cc451e 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -33,6 +33,7 @@ #include "math_defs.h" #include "math_funcs.h" #include "typedefs.h" +#include "ustring.h" /** * Hashing functions @@ -128,4 +129,37 @@ static inline uint64_t make_uint64_t(T p_in) { return _u._u64; } +struct HashMapHasherDefault { + static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } + static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } + static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } + + static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); } + static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } + static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); } + static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; } + static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; } + static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; } + static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; } + static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; } + static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; } + static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; } + //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); } +}; + +template <typename T> +struct HashMapComparatorDefault { + static bool compare(const T &p_lhs, const T &p_rhs) { + return p_lhs == p_rhs; + } + + bool compare(const float &p_lhs, const float &p_rhs) { + return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); + } + + bool compare(const double &p_lhs, const double &p_rhs) { + return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); + } +}; + #endif diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 7132b6573e..2c587762e8 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -577,7 +577,7 @@ real_t CameraMatrix::get_fov() const { if ((matrix[8] == 0) && (matrix[9] == 0)) { return Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0; } else { - // our frustum is asymetrical need to calculate the left planes angle seperately.. + // our frustum is asymmetrical need to calculate the left planes angle separately.. Plane left_plane = Plane(matrix[3] + matrix[0], matrix[7] + matrix[4], matrix[11] + matrix[8], diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h new file mode 100644 index 0000000000..66a1e348a1 --- /dev/null +++ b/core/oa_hash_map.h @@ -0,0 +1,593 @@ +/*************************************************************************/ +/* oa_hash_map.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 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 OA_HASH_MAP_H +#define OA_HASH_MAP_H + +#include "hashfuncs.h" +#include "math_funcs.h" +#include "os/copymem.h" +#include "os/memory.h" + +// uncomment this to disable intial local storage. +#define OA_HASH_MAP_INITIAL_LOCAL_STORAGE + +/** + * This class implements a hash map datastructure that uses open addressing with + * local probing. + * + * It can give huge performance improvements over a chained HashMap because of + * the increased data locality. + * + * Because of that locality property it's important to not use "large" value + * types as the "TData" type. If TData values are too big it can cause more + * cache misses then chaining. If larger values are needed then storing those + * in a separate array and using pointers or indices to reference them is the + * better solution. + * + * This hash map also implements real-time incremental rehashing. + * + */ +template <class TKey, class TData, + uint16_t INITIAL_NUM_ELEMENTS = 64, + class Hasher = HashMapHasherDefault, + class Comparator = HashMapComparatorDefault<TKey> > +class OAHashMap { + +private: +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + TData local_data[INITIAL_NUM_ELEMENTS]; + TKey local_keys[INITIAL_NUM_ELEMENTS]; + uint32_t local_hashes[INITIAL_NUM_ELEMENTS]; + uint8_t local_flags[INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0)]; +#endif + + struct { + TData *data; + TKey *keys; + uint32_t *hashes; + + // This is actually an array of bits, 4 bit pairs per octet. + // | ba ba ba ba | ba ba ba ba | .... + // + // if a is set it means that there is an element present. + // if b is set it means that an element was deleted. This is needed for + // the local probing to work without relocating any succeeding and + // colliding entries. + uint8_t *flags; + + uint32_t capacity; + } table, old_table; + + bool is_rehashing; + uint32_t rehash_position; + uint32_t rehash_amount; + + uint32_t elements; + + /* Methods */ + + // returns true if the value already existed, false if it's a new entry + bool _raw_set_with_hash(uint32_t p_hash, const TKey &p_key, const TData &p_data) { + for (int i = 0; i < table.capacity; i++) { + + int pos = (p_hash + i) % table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset)); + bool is_deleted_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1)); + + if (is_filled_flag) { + if (table.hashes[pos] == p_hash && Comparator::compare(table.keys[pos], p_key)) { + table.data[pos] = p_data; + return true; + } + continue; + } + + table.keys[pos] = p_key; + table.data[pos] = p_data; + table.hashes[pos] = p_hash; + + table.flags[flags_pos] |= (1 << (2 * flags_pos_offset)); + table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset + 1)); + + return false; + } + return false; + } + +public: + _FORCE_INLINE_ uint32_t get_capacity() const { return table.capacity; } + _FORCE_INLINE_ uint32_t get_num_elements() const { return elements; } + + void set(const TKey &p_key, const TData &p_data) { + + uint32_t hash = Hasher::hash(p_key); + + // We don't progress the rehashing if the table just got resized + // to keep the cost of this function low. + if (is_rehashing) { + + // rehash progress + + for (int i = 0; i <= rehash_amount && rehash_position < old_table.capacity; rehash_position++) { + + int flags_pos = rehash_position / 4; + int flags_pos_offset = rehash_position % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + _raw_set_with_hash(old_table.hashes[rehash_position], old_table.keys[rehash_position], old_table.data[rehash_position]); + + old_table.keys[rehash_position].~TKey(); + old_table.data[rehash_position].~TData(); + + memnew_placement(&old_table.keys[rehash_position], TKey); + memnew_placement(&old_table.data[rehash_position], TData); + + old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); + old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); + } + } + + if (rehash_position >= old_table.capacity) { + + // wohooo, we can get rid of the old table. + is_rehashing = false; + +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + if (old_table.data == local_data) { + // Everything is local, so no cleanup :P + } else +#endif + { + memdelete_arr(old_table.data); + memdelete_arr(old_table.keys); + memdelete_arr(old_table.hashes); + memdelete_arr(old_table.flags); + } + } + } + + // Table is almost full, resize and start rehashing process. + if (elements >= table.capacity * 0.7) { + + old_table.capacity = table.capacity; + old_table.data = table.data; + old_table.flags = table.flags; + old_table.hashes = table.hashes; + old_table.keys = table.keys; + + table.capacity = old_table.capacity * 2; + + table.data = memnew_arr(TData, table.capacity); + table.flags = memnew_arr(uint8_t, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0)); + table.hashes = memnew_arr(uint32_t, table.capacity); + table.keys = memnew_arr(TKey, table.capacity); + + zeromem(table.flags, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0)); + + is_rehashing = true; + rehash_position = 0; + rehash_amount = (elements * 2) / (table.capacity * 0.7 - old_table.capacity); + } + + if (!_raw_set_with_hash(hash, p_key, p_data)) + elements++; + } + + /** + * returns true if the value was found, false otherwise. + * + * if r_data is not NULL then the value will be written to the object + * it points to. + */ + bool lookup(const TKey &p_key, TData *r_data) { + + uint32_t hash = Hasher::hash(p_key); + + bool check_old_table = is_rehashing; + bool check_new_table = true; + + // search for the key and return the value associated with it + // + // if we're rehashing we need to check both the old and the + // current table. If we find a value in the old table we still + // need to continue searching in the new table as it might have + // been added after + + TData *value = NULL; + + for (int i = 0; i < table.capacity; i++) { + + if (!check_new_table && !check_old_table) { + + break; + } + + // if we're rehashing check the old table + if (check_old_table && i < old_table.capacity) { + + int pos = (hash + i) % old_table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + // found our entry? + if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) { + value = &old_table.data[pos]; + check_old_table = false; + } + } else if (!is_deleted_flag) { + + // we hit an empty field here, we don't + // need to further check this old table + // because we know it's not in here. + + check_old_table = false; + } + } + + if (check_new_table) { + + int pos = (hash + i) % table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + // found our entry? + if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) { + if (r_data != NULL) + *r_data = table.data[pos]; + return true; + } + continue; + } else if (is_deleted_flag) { + continue; + } else if (value != NULL) { + + // We found a value in the old table + if (r_data != NULL) + *r_data = *value; + return true; + } else { + check_new_table = false; + } + } + } + + if (value != NULL) { + if (r_data != NULL) + *r_data = *value; + return true; + } + return false; + } + + _FORCE_INLINE_ bool has(const TKey &p_key) { + return lookup(p_key, NULL); + } + + void remove(const TKey &p_key) { + uint32_t hash = Hasher::hash(p_key); + + bool check_old_table = is_rehashing; + bool check_new_table = true; + + for (int i = 0; i < table.capacity; i++) { + + if (!check_new_table && !check_old_table) { + return; + } + + // if we're rehashing check the old table + if (check_old_table && i < old_table.capacity) { + + int pos = (hash + i) % old_table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + // found our entry? + if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) { + old_table.keys[pos].~TKey(); + old_table.data[pos].~TData(); + + memnew_placement(&old_table.keys[pos], TKey); + memnew_placement(&old_table.data[pos], TData); + + old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); + old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); + + elements--; + return; + } + } else if (!is_deleted_flag) { + + // we hit an empty field here, we don't + // need to further check this old table + // because we know it's not in here. + + check_old_table = false; + } + } + + if (check_new_table) { + + int pos = (hash + i) % table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + // found our entry? + if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) { + table.keys[pos].~TKey(); + table.data[pos].~TData(); + + memnew_placement(&table.keys[pos], TKey); + memnew_placement(&table.data[pos], TData); + + table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); + table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); + + // don't return here, this value might still be in the old table + // if it was already relocated. + + elements--; + return; + } + continue; + } else if (is_deleted_flag) { + continue; + } else { + check_new_table = false; + } + } + } + } + + struct Iterator { + bool valid; + + uint32_t hash; + + const TKey *key; + const TData *data; + + private: + friend class OAHashMap; + bool was_from_old_table; + }; + + Iterator iter() const { + Iterator it; + + it.valid = false; + it.was_from_old_table = false; + + bool check_old_table = is_rehashing; + + for (int i = 0; i < table.capacity; i++) { + + // if we're rehashing check the old table first + if (check_old_table && i < old_table.capacity) { + + int pos = i; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + + if (is_filled_flag) { + it.valid = true; + it.hash = old_table.hashes[pos]; + it.data = &old_table.data[pos]; + it.key = &old_table.keys[pos]; + + it.was_from_old_table = true; + + return it; + } + } + + { + + int pos = i; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + + if (is_filled_flag) { + it.valid = true; + it.hash = table.hashes[pos]; + it.data = &table.data[pos]; + it.key = &table.keys[pos]; + + return it; + } + } + } + + return it; + } + + Iterator next_iter(const Iterator &p_iter) const { + if (!p_iter.valid) { + return p_iter; + } + + Iterator it; + + it.valid = false; + it.was_from_old_table = false; + + bool check_old_table = is_rehashing; + + // we use this to skip the first check or not + bool was_from_old_table = p_iter.was_from_old_table; + + int prev_index = (p_iter.data - (p_iter.was_from_old_table ? old_table.data : table.data)); + + if (!was_from_old_table) { + prev_index++; + } + + for (int i = prev_index; i < table.capacity; i++) { + + // if we're rehashing check the old table first + if (check_old_table && i < old_table.capacity && !was_from_old_table) { + + int pos = i; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + + if (is_filled_flag) { + it.valid = true; + it.hash = old_table.hashes[pos]; + it.data = &old_table.data[pos]; + it.key = &old_table.keys[pos]; + + it.was_from_old_table = true; + + return it; + } + } + + was_from_old_table = false; + + { + int pos = i; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + + if (is_filled_flag) { + it.valid = true; + it.hash = table.hashes[pos]; + it.data = &table.data[pos]; + it.key = &table.keys[pos]; + + return it; + } + } + } + + return it; + } + + OAHashMap(uint32_t p_initial_capacity = INITIAL_NUM_ELEMENTS) { + +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + + if (p_initial_capacity <= INITIAL_NUM_ELEMENTS) { + table.data = local_data; + table.keys = local_keys; + table.hashes = local_hashes; + table.flags = local_flags; + + zeromem(table.flags, INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0)); + + table.capacity = INITIAL_NUM_ELEMENTS; + elements = 0; + } else +#endif + { + table.data = memnew_arr(TData, p_initial_capacity); + table.keys = memnew_arr(TKey, p_initial_capacity); + table.hashes = memnew_arr(uint32_t, p_initial_capacity); + table.flags = memnew_arr(uint8_t, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0)); + + zeromem(table.flags, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0)); + + table.capacity = p_initial_capacity; + elements = 0; + } + + is_rehashing = false; + rehash_position = 0; + } + + ~OAHashMap() { +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + if (table.capacity <= INITIAL_NUM_ELEMENTS) { + return; // Everything is local, so no cleanup :P + } +#endif + if (is_rehashing) { + +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + if (old_table.data == local_data) { + // Everything is local, so no cleanup :P + } else +#endif + { + memdelete_arr(old_table.data); + memdelete_arr(old_table.keys); + memdelete_arr(old_table.hashes); + memdelete_arr(old_table.flags); + } + } + + memdelete_arr(table.data); + memdelete_arr(table.keys); + memdelete_arr(table.hashes); + memdelete_arr(table.flags); + } +}; + +#endif diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index f24d6d16ca..1437e7cdfc 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -292,7 +292,7 @@ String DirAccess::get_full_path(const String &p_path, AccessType p_access) { return full; } -Error DirAccess::copy(String p_from, String p_to) { +Error DirAccess::copy(String p_from, String p_to, int chmod_flags) { //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data()); Error err; @@ -329,6 +329,11 @@ Error DirAccess::copy(String p_from, String p_to) { fdst->store_8(fsrc->get_8()); } + if (err == OK && chmod_flags != -1) { + fdst->close(); + err = fdst->_chmod(p_to, chmod_flags); + } + memdelete(fsrc); memdelete(fdst); diff --git a/core/os/dir_access.h b/core/os/dir_access.h index 6ad8b4c49b..7fa3ce5cf1 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -89,7 +89,7 @@ public: static bool exists(String p_dir); virtual size_t get_space_left() = 0; - virtual Error copy(String p_from, String p_to); + virtual Error copy(String p_from, String p_to, int chmod_flags = -1); virtual Error rename(String p_from, String p_to) = 0; virtual Error remove(String p_name) = 0; diff --git a/core/os/file_access.h b/core/os/file_access.h index 8e5728f525..63692cb290 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -140,6 +140,8 @@ public: virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType + virtual Error _chmod(const String &p_path, int p_mod) { return FAILED; } + static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files. static FileAccess *create_for_path(const String &p_path); static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = NULL); /// Create a file access (for the current platform) this is the only portable way of accessing files. diff --git a/core/set.h b/core/set.h index f68d78cea1..d91dd9b3ea 100644 --- a/core/set.h +++ b/core/set.h @@ -135,7 +135,6 @@ private: #ifdef GLOBALNIL_DISABLED memdelete_allocator<Element, A>(_nil); #endif - //memdelete_allocator<Element,A>(_root); } }; @@ -146,6 +145,7 @@ private: ERR_FAIL_COND(p_node == _data._nil && p_color == RED); p_node->color = p_color; } + inline void _rotate_left(Element *p_node) { Element *r = p_node->right; @@ -194,8 +194,9 @@ private: while (node == node->parent->right) { node = node->parent; } + if (node->parent == _data._root) - return NULL; + return NULL; // No successor, as p_node is the last node. return node->parent; } } @@ -213,11 +214,11 @@ private: } else { while (node == node->parent->left) { - if (node->parent == _data._root) - return NULL; - node = node->parent; } + + if (node == _data._root) + return NULL; // No predecessor, as p_node is the first node. return node->parent; } } @@ -228,16 +229,15 @@ private: C less; while (node != _data._nil) { - if (less(p_value, node->value)) node = node->left; else if (less(node->value, p_value)) node = node->right; else - break; // found + return node; // found } - return (node != _data._nil) ? node : NULL; + return NULL; } Element *_lower_bound(const T &p_value) const { @@ -254,21 +254,16 @@ private: else if (less(node->value, p_value)) node = node->right; else - break; // found + return node; // found } - if (node == _data._nil) { - if (prev == NULL) - return NULL; - if (less(prev->value, p_value)) { - - prev = prev->_next; - } + if (prev == NULL) + return NULL; // tree empty - return prev; + if (less(prev->value, p_value)) + prev = prev->_next; - } else - return node; + return prev; } Element *_insert(const T &p_value, bool &r_exists) { @@ -291,22 +286,21 @@ private: } } - Element *new_node = memnew_allocator(Element, A); + r_exists = false; + Element *new_node = memnew_allocator(Element, A); new_node->parent = new_parent; new_node->right = _data._nil; new_node->left = _data._nil; new_node->value = p_value; //new_node->data=_data; - if (new_parent == _data._root || less(p_value, new_parent->value)) { + if (new_parent == _data._root || less(p_value, new_parent->value)) { new_parent->left = new_node; } else { new_parent->right = new_node; } - r_exists = false; - new_node->_next = _successor(new_node); new_node->_prev = _predecessor(new_node); if (new_node->_next) @@ -324,154 +318,159 @@ private: if (exists) return new_node; - Element *node = new_node; _data.size_cache++; + Element *node = new_node; + Element *nparent = node->parent; + Element *ngrand_parent; - while (node->parent->color == RED) { - - if (node->parent == node->parent->parent->left) { + while (nparent->color == RED) { - Element *aux = node->parent->parent->right; + ngrand_parent = nparent->parent; - if (aux->color == RED) { - _set_color(node->parent, BLACK); - _set_color(aux, BLACK); - _set_color(node->parent->parent, RED); - node = node->parent->parent; + if (nparent == ngrand_parent->left) { + if (ngrand_parent->right->color == RED) { + _set_color(nparent, BLACK); + _set_color(ngrand_parent->right, BLACK); + _set_color(ngrand_parent, RED); + node = ngrand_parent; + nparent = node->parent; } else { - if (node == node->parent->right) { - node = node->parent; - _rotate_left(node); + if (node == nparent->right) { + _rotate_left(nparent); + node = nparent; + nparent = node->parent; } - _set_color(node->parent, BLACK); - _set_color(node->parent->parent, RED); - _rotate_right(node->parent->parent); + _set_color(nparent, BLACK); + _set_color(ngrand_parent, RED); + _rotate_right(ngrand_parent); } } else { - Element *aux = node->parent->parent->left; - - if (aux->color == RED) { - _set_color(node->parent, BLACK); - _set_color(aux, BLACK); - _set_color(node->parent->parent, RED); - node = node->parent->parent; + if (ngrand_parent->left->color == RED) { + _set_color(nparent, BLACK); + _set_color(ngrand_parent->left, BLACK); + _set_color(ngrand_parent, RED); + node = ngrand_parent; + nparent = node->parent; } else { - if (node == node->parent->left) { - node = node->parent; - _rotate_right(node); + if (node == nparent->left) { + _rotate_right(nparent); + node = nparent; + nparent = node->parent; } - _set_color(node->parent, BLACK); - _set_color(node->parent->parent, RED); - _rotate_left(node->parent->parent); + _set_color(nparent, BLACK); + _set_color(ngrand_parent, RED); + _rotate_left(ngrand_parent); } } } + _set_color(_data._root->left, BLACK); + return new_node; } void _erase_fix(Element *p_node) { Element *root = _data._root->left; - Element *node = p_node; - - while ((node->color == BLACK) && (root != node)) { - if (node == node->parent->left) { - Element *aux = node->parent->right; - if (aux->color == RED) { - _set_color(aux, BLACK); - _set_color(node->parent, RED); - _rotate_left(node->parent); - aux = node->parent->right; - } - if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) { - _set_color(aux, RED); - node = node->parent; + Element *node = _data._nil; + Element *sibling = p_node; + Element *parent = sibling->parent; + + while (node != root) { // If red node found, will exit at a break + if (sibling->color == RED) { + _set_color(sibling, BLACK); + _set_color(parent, RED); + if (sibling == parent->right) { + sibling = sibling->left; + _rotate_left(parent); } else { - if (aux->right->color == BLACK) { - _set_color(aux->left, BLACK); - _set_color(aux, RED); - _rotate_right(aux); - aux = node->parent->right; - } - _set_color(aux, node->parent->color); - _set_color(node->parent, BLACK); - _set_color(aux->right, BLACK); - _rotate_left(node->parent); - node = root; /* this is to exit while loop */ + sibling = sibling->right; + _rotate_right(parent); } - } else { /* the code below is has left and right switched from above */ - Element *aux = node->parent->left; - if (aux->color == RED) { - _set_color(aux, BLACK); - _set_color(node->parent, RED); - _rotate_right(node->parent); - aux = node->parent->left; + } + if ((sibling->left->color == BLACK) && (sibling->right->color == BLACK)) { + _set_color(sibling, RED); + if (parent->color == RED) { + _set_color(parent, BLACK); + break; + } else { // loop: haven't found any red nodes yet + node = parent; + parent = node->parent; + sibling = (node == parent->left) ? parent->right : parent->left; } - if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) { - _set_color(aux, RED); - node = node->parent; + } else { + if (sibling == parent->right) { + if (sibling->right->color == BLACK) { + _set_color(sibling->left, BLACK); + _set_color(sibling, RED); + _rotate_right(sibling); + sibling = sibling->parent; + } + _set_color(sibling, parent->color); + _set_color(parent, BLACK); + _set_color(sibling->right, BLACK); + _rotate_left(parent); + break; } else { - if (aux->left->color == BLACK) { - _set_color(aux->right, BLACK); - _set_color(aux, RED); - _rotate_left(aux); - aux = node->parent->left; + if (sibling->left->color == BLACK) { + _set_color(sibling->right, BLACK); + _set_color(sibling, RED); + _rotate_left(sibling); + sibling = sibling->parent; } - _set_color(aux, node->parent->color); - _set_color(node->parent, BLACK); - _set_color(aux->left, BLACK); - _rotate_right(node->parent); - node = root; + + _set_color(sibling, parent->color); + _set_color(parent, BLACK); + _set_color(sibling->left, BLACK); + _rotate_right(parent); + break; } } } - _set_color(node, BLACK); - ERR_FAIL_COND(_data._nil->color != BLACK); } void _erase(Element *p_node) { - Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : _successor(p_node); - if (!rp) - rp = _data._nil; + Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next; Element *node = (rp->left == _data._nil) ? rp->right : rp->left; node->parent = rp->parent; - if (_data._root == node->parent) { - _data._root->left = node; + Element *sibling; + if (rp == rp->parent->left) { + rp->parent->left = node; + sibling = rp->parent->right; } else { - if (rp == rp->parent->left) { - rp->parent->left = node; - } else { - rp->parent->right = node; - } + rp->parent->right = node; + sibling = rp->parent->left; + } + + if (node->color == RED) { + node->parent = rp->parent; + _set_color(node, BLACK); + } else if (rp->color == BLACK && rp->parent != _data._root) { + _erase_fix(sibling); } if (rp != p_node) { ERR_FAIL_COND(rp == _data._nil); - if (rp->color == BLACK) - _erase_fix(node); - rp->left = p_node->left; rp->right = p_node->right; rp->parent = p_node->parent; rp->color = p_node->color; - p_node->left->parent = rp; - p_node->right->parent = rp; + if (p_node->left != _data._nil) + p_node->left->parent = rp; + if (p_node->right != _data._nil) + p_node->right->parent = rp; if (p_node == p_node->parent->left) { p_node->parent->left = rp; } else { p_node->parent->right = rp; } - } else { - if (p_node->color == BLACK) - _erase_fix(node); } if (p_node->_next) @@ -529,6 +528,7 @@ public: if (!_data._root) return NULL; + Element *res = _find(p_value); return res; } @@ -549,8 +549,9 @@ public: void erase(Element *p_element) { - if (!_data._root) + if (!_data._root || !p_element) return; + _erase(p_element); if (_data.size_cache == 0 && _data._root) _data._free_root(); @@ -560,9 +561,11 @@ public: if (!_data._root) return false; + Element *e = find(p_value); if (!e) return false; + _erase(e); if (_data.size_cache == 0 && _data._root) _data._free_root(); @@ -573,6 +576,7 @@ public: if (!_data._root) return NULL; + Element *e = _data._root->left; if (e == _data._nil) return NULL; @@ -587,6 +591,7 @@ public: if (!_data._root) return NULL; + Element *e = _data._root->left; if (e == _data._nil) return NULL; @@ -603,10 +608,12 @@ public: } inline int size() const { return _data.size_cache; } + int calculate_depth() const { // used for debug mostly if (!_data._root) return 0; + int max_d = 0; _calculate_depth(_data._root->left, max_d, 0); return max_d; @@ -620,7 +627,6 @@ public: _cleanup_tree(_data._root->left); _data._root->left = _data._nil; _data.size_cache = 0; - _data._nil->parent = _data._nil; _data._free_root(); } @@ -633,6 +639,7 @@ public: _copy_from(p_set); } + _FORCE_INLINE_ Set() { } diff --git a/core/variant.cpp b/core/variant.cpp index 10d86152ee..52bdd4e22d 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -903,9 +903,6 @@ bool Variant::is_one() const { void Variant::reference(const Variant &p_variant) { - if (this == &p_variant) - return; - clear(); type = p_variant.type; @@ -924,17 +921,14 @@ void Variant::reference(const Variant &p_variant) { case INT: { _data._int = p_variant._data._int; - } break; case REAL: { _data._real = p_variant._data._real; - } break; case STRING: { memnew_placement(_data._mem, String(*reinterpret_cast<const String *>(p_variant._data._mem))); - } break; // math types @@ -942,33 +936,24 @@ void Variant::reference(const Variant &p_variant) { case VECTOR2: { memnew_placement(_data._mem, Vector2(*reinterpret_cast<const Vector2 *>(p_variant._data._mem))); - } break; case RECT2: { memnew_placement(_data._mem, Rect2(*reinterpret_cast<const Rect2 *>(p_variant._data._mem))); - } break; case TRANSFORM2D: { _data._transform2d = memnew(Transform2D(*p_variant._data._transform2d)); - } break; case VECTOR3: { memnew_placement(_data._mem, Vector3(*reinterpret_cast<const Vector3 *>(p_variant._data._mem))); - } break; case PLANE: { memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem))); - } break; - /* - case QUAT: { - - } break;*/ case RECT3: { _data._rect3 = memnew(Rect3(*p_variant._data._rect3)); @@ -986,7 +971,6 @@ void Variant::reference(const Variant &p_variant) { case TRANSFORM: { _data._transform = memnew(Transform(*p_variant._data._transform)); - } break; // misc types @@ -1058,6 +1042,7 @@ void Variant::reference(const Variant &p_variant) { default: {} } } + void Variant::zero() { switch (type) { case NIL: break; @@ -1073,6 +1058,7 @@ void Variant::zero() { default: this->clear(); break; } } + void Variant::clear() { switch (type) { @@ -1092,12 +1078,10 @@ void Variant::clear() { case TRANSFORM2D: { memdelete(_data._transform2d); - } break; case RECT3: { memdelete(_data._rect3); - } break; case BASIS: { @@ -1106,14 +1090,12 @@ void Variant::clear() { case TRANSFORM: { memdelete(_data._transform); - } break; // misc types case NODE_PATH: { reinterpret_cast<NodePath *>(_data._mem)->~NodePath(); - } break; case OBJECT: { @@ -1127,48 +1109,39 @@ void Variant::clear() { case DICTIONARY: { reinterpret_cast<Dictionary *>(_data._mem)->~Dictionary(); - } break; case ARRAY: { reinterpret_cast<Array *>(_data._mem)->~Array(); - } break; // arrays case POOL_BYTE_ARRAY: { reinterpret_cast<PoolVector<uint8_t> *>(_data._mem)->~PoolVector<uint8_t>(); - } break; case POOL_INT_ARRAY: { reinterpret_cast<PoolVector<int> *>(_data._mem)->~PoolVector<int>(); - } break; case POOL_REAL_ARRAY: { reinterpret_cast<PoolVector<real_t> *>(_data._mem)->~PoolVector<real_t>(); - } break; case POOL_STRING_ARRAY: { reinterpret_cast<PoolVector<String> *>(_data._mem)->~PoolVector<String>(); - } break; case POOL_VECTOR2_ARRAY: { reinterpret_cast<PoolVector<Vector2> *>(_data._mem)->~PoolVector<Vector2>(); - } break; case POOL_VECTOR3_ARRAY: { reinterpret_cast<PoolVector<Vector3> *>(_data._mem)->~PoolVector<Vector3>(); - } break; case POOL_COLOR_ARRAY: { reinterpret_cast<PoolVector<Color> *>(_data._mem)->~PoolVector<Color>(); - } break; default: {} /* not needed */ } @@ -2496,7 +2469,135 @@ Variant::Variant(const Vector<Color> &p_array) { void Variant::operator=(const Variant &p_variant) { - reference(p_variant); + if (this == &p_variant) + return; + + if (type != p_variant.type) { + reference(p_variant); + return; + } + + switch (p_variant.type) { + case NIL: { + + // none + } break; + + // atomic types + case BOOL: { + + _data._bool = p_variant._data._bool; + } break; + case INT: { + + _data._int = p_variant._data._int; + } break; + case REAL: { + + _data._real = p_variant._data._real; + } break; + case STRING: { + + *reinterpret_cast<String *>(_data._mem) = *reinterpret_cast<const String *>(p_variant._data._mem); + } break; + + // math types + + case VECTOR2: { + + *reinterpret_cast<Vector2 *>(_data._mem) = *reinterpret_cast<const Vector2 *>(p_variant._data._mem); + } break; + case RECT2: { + + *reinterpret_cast<Rect2 *>(_data._mem) = *reinterpret_cast<const Rect2 *>(p_variant._data._mem); + } break; + case TRANSFORM2D: { + + *_data._transform2d = *(p_variant._data._transform2d); + } break; + case VECTOR3: { + + *reinterpret_cast<Vector3 *>(_data._mem) = *reinterpret_cast<const Vector3 *>(p_variant._data._mem); + } break; + case PLANE: { + + *reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem); + } break; + + case RECT3: { + + *_data._rect3 = *(p_variant._data._rect3); + } break; + case QUAT: { + + *reinterpret_cast<Quat *>(_data._mem) = *reinterpret_cast<const Quat *>(p_variant._data._mem); + } break; + case BASIS: { + + *_data._basis = *(p_variant._data._basis); + } break; + case TRANSFORM: { + + *_data._transform = *(p_variant._data._transform); + } break; + + // misc types + case COLOR: { + + *reinterpret_cast<Color *>(_data._mem) = *reinterpret_cast<const Color *>(p_variant._data._mem); + } break; + case _RID: { + + *reinterpret_cast<RID *>(_data._mem) = *reinterpret_cast<const RID *>(p_variant._data._mem); + } break; + case OBJECT: { + + *reinterpret_cast<ObjData *>(_data._mem) = p_variant._get_obj(); + } break; + case NODE_PATH: { + + *reinterpret_cast<NodePath *>(_data._mem) = *reinterpret_cast<const NodePath *>(p_variant._data._mem); + } break; + case DICTIONARY: { + + *reinterpret_cast<Dictionary *>(_data._mem) = *reinterpret_cast<const Dictionary *>(p_variant._data._mem); + } break; + case ARRAY: { + + *reinterpret_cast<Array *>(_data._mem) = *reinterpret_cast<const Array *>(p_variant._data._mem); + } break; + + // arrays + case POOL_BYTE_ARRAY: { + + *reinterpret_cast<PoolVector<uint8_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<uint8_t> *>(p_variant._data._mem); + } break; + case POOL_INT_ARRAY: { + + *reinterpret_cast<PoolVector<int> *>(_data._mem) = *reinterpret_cast<const PoolVector<int> *>(p_variant._data._mem); + } break; + case POOL_REAL_ARRAY: { + + *reinterpret_cast<PoolVector<real_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<real_t> *>(p_variant._data._mem); + } break; + case POOL_STRING_ARRAY: { + + *reinterpret_cast<PoolVector<String> *>(_data._mem) = *reinterpret_cast<const PoolVector<String> *>(p_variant._data._mem); + } break; + case POOL_VECTOR2_ARRAY: { + + *reinterpret_cast<PoolVector<Vector2> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector2> *>(p_variant._data._mem); + } break; + case POOL_VECTOR3_ARRAY: { + + *reinterpret_cast<PoolVector<Vector3> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector3> *>(p_variant._data._mem); + } break; + case POOL_COLOR_ARRAY: { + + *reinterpret_cast<PoolVector<Color> *>(_data._mem) = *reinterpret_cast<const PoolVector<Color> *>(p_variant._data._mem); + } break; + default: {} + } } Variant::Variant(const IP_Address &p_address) { diff --git a/core/variant.h b/core/variant.h index e77e2e93c4..5ea540a63f 100644 --- a/core/variant.h +++ b/core/variant.h @@ -70,6 +70,7 @@ typedef PoolVector<Color> PoolColorArray; class Variant { public: + // If this changes the table in variant_op must be updated enum Type { NIL, @@ -288,6 +289,7 @@ public: Variant(const IP_Address &p_address); + // If this changes the table in variant_op must be updated enum Operator { //comparation @@ -299,7 +301,7 @@ public: OP_GREATER_EQUAL, //mathematic OP_ADD, - OP_SUBSTRACT, + OP_SUBTRACT, OP_MULTIPLY, OP_DIVIDE, OP_NEGATE, @@ -388,7 +390,7 @@ public: uint32_t hash() const; bool hash_compare(const Variant &p_variant) const; - bool booleanize(bool &valid) const; + bool booleanize() const; void static_assign(const Variant &p_variant); static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index a11169eb8f..5d47936679 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -33,49 +33,123 @@ #include "object.h" #include "script_language.h" -Variant::operator bool() const { - - bool b; - return booleanize(b); +#define CASE_TYPE_ALL(PREFIX, OP) \ + CASE_TYPE(PREFIX, OP, INT) \ + CASE_TYPE_ALL_BUT_INT(PREFIX, OP) + +#define CASE_TYPE_ALL_BUT_INT(PREFIX, OP) \ + CASE_TYPE(PREFIX, OP, NIL) \ + CASE_TYPE(PREFIX, OP, BOOL) \ + CASE_TYPE(PREFIX, OP, REAL) \ + CASE_TYPE(PREFIX, OP, STRING) \ + CASE_TYPE(PREFIX, OP, VECTOR2) \ + CASE_TYPE(PREFIX, OP, RECT2) \ + CASE_TYPE(PREFIX, OP, VECTOR3) \ + CASE_TYPE(PREFIX, OP, TRANSFORM2D) \ + CASE_TYPE(PREFIX, OP, PLANE) \ + CASE_TYPE(PREFIX, OP, QUAT) \ + CASE_TYPE(PREFIX, OP, RECT3) \ + CASE_TYPE(PREFIX, OP, BASIS) \ + CASE_TYPE(PREFIX, OP, TRANSFORM) \ + CASE_TYPE(PREFIX, OP, COLOR) \ + CASE_TYPE(PREFIX, OP, NODE_PATH) \ + CASE_TYPE(PREFIX, OP, _RID) \ + CASE_TYPE(PREFIX, OP, OBJECT) \ + CASE_TYPE(PREFIX, OP, DICTIONARY) \ + CASE_TYPE(PREFIX, OP, ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_BYTE_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_INT_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_REAL_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_STRING_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_COLOR_ARRAY) + +#ifdef __GNUC__ +#define TYPE(PREFIX, OP, TYPE) &&PREFIX##_##OP##_##TYPE + +/* clang-format off */ +#define TYPES(PREFIX, OP) { \ + TYPE(PREFIX, OP, NIL), \ + TYPE(PREFIX, OP, BOOL), \ + TYPE(PREFIX, OP, INT), \ + TYPE(PREFIX, OP, REAL), \ + TYPE(PREFIX, OP, STRING), \ + TYPE(PREFIX, OP, VECTOR2), \ + TYPE(PREFIX, OP, RECT2), \ + TYPE(PREFIX, OP, VECTOR3), \ + TYPE(PREFIX, OP, TRANSFORM2D), \ + TYPE(PREFIX, OP, PLANE), \ + TYPE(PREFIX, OP, QUAT), \ + TYPE(PREFIX, OP, RECT3), \ + TYPE(PREFIX, OP, BASIS), \ + TYPE(PREFIX, OP, TRANSFORM), \ + TYPE(PREFIX, OP, COLOR), \ + TYPE(PREFIX, OP, NODE_PATH), \ + TYPE(PREFIX, OP, _RID), \ + TYPE(PREFIX, OP, OBJECT), \ + TYPE(PREFIX, OP, DICTIONARY), \ + TYPE(PREFIX, OP, ARRAY), \ + TYPE(PREFIX, OP, POOL_BYTE_ARRAY), \ + TYPE(PREFIX, OP, POOL_INT_ARRAY), \ + TYPE(PREFIX, OP, POOL_REAL_ARRAY), \ + TYPE(PREFIX, OP, POOL_STRING_ARRAY), \ + TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY), \ + TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY), \ + TYPE(PREFIX, OP, POOL_COLOR_ARRAY), \ +} +/* clang-format on */ + +#define CASES(PREFIX) static void *switch_table_##PREFIX[25][27] = { \ + TYPES(PREFIX, OP_EQUAL), \ + TYPES(PREFIX, OP_NOT_EQUAL), \ + TYPES(PREFIX, OP_LESS), \ + TYPES(PREFIX, OP_LESS_EQUAL), \ + TYPES(PREFIX, OP_GREATER), \ + TYPES(PREFIX, OP_GREATER_EQUAL), \ + TYPES(PREFIX, OP_ADD), \ + TYPES(PREFIX, OP_SUBTRACT), \ + TYPES(PREFIX, OP_MULTIPLY), \ + TYPES(PREFIX, OP_DIVIDE), \ + TYPES(PREFIX, OP_NEGATE), \ + TYPES(PREFIX, OP_POSITIVE), \ + TYPES(PREFIX, OP_MODULE), \ + TYPES(PREFIX, OP_STRING_CONCAT), \ + TYPES(PREFIX, OP_SHIFT_LEFT), \ + TYPES(PREFIX, OP_SHIFT_RIGHT), \ + TYPES(PREFIX, OP_BIT_AND), \ + TYPES(PREFIX, OP_BIT_OR), \ + TYPES(PREFIX, OP_BIT_XOR), \ + TYPES(PREFIX, OP_BIT_NEGATE), \ + TYPES(PREFIX, OP_AND), \ + TYPES(PREFIX, OP_OR), \ + TYPES(PREFIX, OP_XOR), \ + TYPES(PREFIX, OP_NOT), \ + TYPES(PREFIX, OP_IN), \ } -bool Variant::booleanize(bool &r_valid) const { +#define SWITCH(PREFIX, op, val) goto *switch_table_##PREFIX[op][val]; +#define SWITCH_OP(PREFIX, OP, val) +#define CASE_TYPE(PREFIX, OP, TYPE) PREFIX##_##OP##_##TYPE: + +#else +#define CASES(PREFIX) +#define SWITCH(PREFIX, op, val) switch (op) +#define SWITCH_OP(PREFIX, OP, val) \ + case OP: \ + switch (val) +#define CASE_TYPE(PREFIX, OP, TYPE) case TYPE: +#endif - r_valid = true; - switch (type) { - case NIL: return false; - case BOOL: return _data._bool; - case INT: return _data._int; - case REAL: return _data._real; - case STRING: return (*reinterpret_cast<const String *>(_data._mem)) != ""; - case VECTOR2: - case RECT2: - case TRANSFORM2D: - case VECTOR3: - case PLANE: - case RECT3: - case QUAT: - case BASIS: - case TRANSFORM: - case COLOR: - case _RID: return (*reinterpret_cast<const RID *>(_data._mem)).is_valid(); - case OBJECT: return _get_obj().obj; - case NODE_PATH: return (*reinterpret_cast<const NodePath *>(_data._mem)) != NodePath(); - case DICTIONARY: - case ARRAY: - case POOL_BYTE_ARRAY: - case POOL_INT_ARRAY: - case POOL_REAL_ARRAY: - case POOL_STRING_ARRAY: - case POOL_VECTOR2_ARRAY: - case POOL_VECTOR3_ARRAY: - case POOL_COLOR_ARRAY: - r_valid = false; - return false; - default: {} - } +Variant::operator bool() const { - return false; + return booleanize(); +} + +// We consider all unitialized or empty types to be false based on the type's +// zeroiness. +bool Variant::booleanize() const { + return !is_zero(); } #define _RETURN(m_what) \ @@ -84,10 +158,15 @@ bool Variant::booleanize(bool &r_valid) const { return; \ } -#define DEFAULT_OP_NUM(m_op, m_name, m_type) \ - case m_name: { \ +#define _RETURN_FAIL \ + { \ + r_valid = false; \ + return; \ + } + +#define DEFAULT_OP_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ switch (p_b.type) { \ - case BOOL: _RETURN(p_a._data.m_type m_op p_b._data._bool); \ case INT: _RETURN(p_a._data.m_type m_op p_b._data._int); \ case REAL: _RETURN(p_a._data.m_type m_op p_b._data._real); \ default: {} \ @@ -96,22 +175,55 @@ bool Variant::booleanize(bool &r_valid) const { return; \ }; -#define DEFAULT_OP_NUM_NEG(m_name, m_type) \ - case m_name: { \ - \ - _RETURN(-p_a._data.m_type); \ +#ifdef DEBUG_ENABLED +#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + switch (p_b.type) { \ + case INT: { \ + if (p_b._data._int == 0) { \ + r_valid = false; \ + _RETURN("Division By Zero"); \ + } \ + _RETURN(p_a._data.m_type / p_b._data._int); \ + } \ + case REAL: { \ + if (p_b._data._real == 0) { \ + r_valid = false; \ + _RETURN("Division By Zero"); \ + } \ + _RETURN(p_a._data.m_type / p_b._data._real); \ + } \ + default: {} \ + } \ + r_valid = false; \ + return; \ + }; +#else +#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + switch (p_b.type) { \ + case INT: _RETURN(p_a._data.m_type / p_b._data._int); \ + case REAL: _RETURN(p_a._data.m_type / p_b._data._real); \ + default: {} \ + } \ + r_valid = false; \ + return; \ }; +#endif -#define DEFAULT_OP_NUM_POS(m_name, m_type) \ - case m_name: { \ - \ - _RETURN(p_a._data.m_type); \ +#define DEFAULT_OP_NUM_NEG(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + _RETURN(-p_a._data.m_type); \ }; -#define DEFAULT_OP_NUM_VEC(m_op, m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_NUM_POS(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + _RETURN(p_a._data.m_type); \ + }; + +#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ switch (p_b.type) { \ - case BOOL: _RETURN(p_a._data.m_type m_op p_b._data._bool); \ case INT: _RETURN(p_a._data.m_type m_op p_b._data._int); \ case REAL: _RETURN(p_a._data.m_type m_op p_b._data._real); \ case VECTOR2: _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ @@ -122,8 +234,19 @@ bool Variant::booleanize(bool &r_valid) const { return; \ }; -#define DEFAULT_OP_STR(m_op, m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + switch (p_b.type) { \ + case STRING: _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \ + case NODE_PATH: _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \ + default: {} \ + } \ + r_valid = false; \ + return; \ + }; + +#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ switch (p_b.type) { \ case STRING: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ case NODE_PATH: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ @@ -133,31 +256,36 @@ bool Variant::booleanize(bool &r_valid) const { return; \ }; -#define DEFAULT_OP_LOCALMEM(m_op, m_name, m_type) \ - case m_name: { \ - switch (p_b.type) { \ - case m_name: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ - default: {} \ - } \ - r_valid = false; \ - return; \ - } +#define DEFAULT_OP_LOCALMEM_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == m_name) \ + _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const m_type *>(p_a._data._mem)); \ + r_valid = false; \ + return; \ + }; + +#define DEFAULT_OP_LOCALMEM(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == m_name) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ + r_valid = false; \ + return; \ + }; -#define DEFAULT_OP_LOCALMEM_NEG(m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_LOCALMEM_NEG(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ _RETURN(-*reinterpret_cast<const m_type *>(p_a._data._mem)); \ } -#define DEFAULT_OP_LOCALMEM_POS(m_name, m_type) \ - case m_name: { \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \ +#define DEFAULT_OP_LOCALMEM_POS(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \ } -#define DEFAULT_OP_LOCALMEM_NUM(m_op, m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_LOCALMEM_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ switch (p_b.type) { \ case m_name: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ - case BOOL: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._bool); \ case INT: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \ case REAL: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._real); \ default: {} \ @@ -176,50 +304,51 @@ bool Variant::booleanize(bool &r_valid) const { return; \ } -#define DEFAULT_OP_PTRREF(m_op, m_name, m_sub) \ - case m_name: { \ - switch (p_b.type) { \ - case m_name: _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \ - default: {} \ - } \ - r_valid = false; \ - return; \ +#define DEFAULT_OP_PTRREF(m_prefix, m_op_name, m_name, m_op, m_sub) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == m_name) \ + _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \ + r_valid = false; \ + return; \ } -#define DEFAULT_OP_ARRAY_EQ(m_name, m_type) \ - DEFAULT_OP_ARRAY_OP(m_name, m_type, !=, !=, true, false, false) - -#define DEFAULT_OP_ARRAY_LT(m_name, m_type) \ - DEFAULT_OP_ARRAY_OP(m_name, m_type, <, !=, false, a_len < array_b.size(), true) - -#define DEFAULT_OP_ARRAY_OP(m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \ - case m_name: { \ - if (p_a.type != p_b.type) { \ - r_valid = false; \ - return; \ - } \ - const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \ - const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \ - \ - int a_len = array_a.size(); \ - if (a_len m_opa array_b.size()) { \ - _RETURN(m_ret_s); \ - } else { \ - \ - PoolVector<m_type>::Read ra = array_a.read(); \ - PoolVector<m_type>::Read rb = array_b.read(); \ - \ - for (int i = 0; i < a_len; i++) { \ - if (ra[i] m_opb rb[i]) \ - _RETURN(m_ret_f); \ - } \ - \ - _RETURN(m_ret_def); \ - } \ +#define DEFAULT_OP_ARRAY_EQ(m_prefix, m_op_name, m_name, m_type) \ + DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, !=, !=, true, false, false) + +#define DEFAULT_OP_ARRAY_LT(m_prefix, m_op_name, m_name, m_type) \ + DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, <, !=, false, a_len < array_b.size(), true) + +#define DEFAULT_OP_ARRAY_GT(m_prefix, m_op_name, m_name, m_type) \ + DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, >, !=, false, a_len < array_b.size(), true) + +#define DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_a.type != p_b.type) { \ + r_valid = false; \ + return; \ + } \ + const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \ + const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \ + \ + int a_len = array_a.size(); \ + if (a_len m_opa array_b.size()) { \ + _RETURN(m_ret_s); \ + } else { \ + \ + PoolVector<m_type>::Read ra = array_a.read(); \ + PoolVector<m_type>::Read rb = array_b.read(); \ + \ + for (int i = 0; i < a_len; i++) { \ + if (ra[i] m_opb rb[i]) \ + _RETURN(m_ret_f); \ + } \ + \ + _RETURN(m_ret_def); \ + } \ } -#define DEFAULT_OP_ARRAY_ADD(m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_ARRAY_ADD(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ if (p_a.type != p_b.type) { \ r_valid = false; \ _RETURN(NIL); \ @@ -231,595 +360,646 @@ bool Variant::booleanize(bool &r_valid) const { _RETURN(sum); \ } -#define DEFAULT_OP_FAIL(m_name) \ - case m_name: { \ - r_valid = false; \ - return; \ - } - -void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid) { +void Variant::evaluate(const Operator &p_op, const Variant &p_a, + const Variant &p_b, Variant &r_ret, bool &r_valid) { + CASES(math); r_valid = true; - switch (p_op) { + SWITCH(math, p_op, p_a.type) { + SWITCH_OP(math, OP_EQUAL, p_a.type) { + CASE_TYPE(math, OP_EQUAL, NIL) { + if (p_b.type == NIL) _RETURN(true); + if (p_b.type == OBJECT) + _RETURN(p_b._get_obj().obj == NULL); + _RETURN_FAIL; + } - case OP_EQUAL: { + CASE_TYPE(math, OP_EQUAL, BOOL) { + if (p_b.type != BOOL) + _RETURN_FAIL; + _RETURN(p_a._data._bool == p_b._data._bool); + } - if ((int(p_a.type) * int(p_b.type)) == 0) { - //null case is an exception, one of both is null - if (p_a.type == p_b.type) //null against null is true - _RETURN(true); - //only against object is allowed - if (p_a.type == Variant::OBJECT) { + CASE_TYPE(math, OP_EQUAL, OBJECT) { + if (p_b.type == OBJECT) + _RETURN((p_a._get_obj().obj == p_b._get_obj().obj)); + if (p_b.type == NIL) _RETURN(p_a._get_obj().obj == NULL); - } else if (p_b.type == Variant::OBJECT) { - _RETURN(p_b._get_obj().obj == NULL); - } - //otherwise, always false - _RETURN(false); + _RETURN_FAIL; } - switch (p_a.type) { + CASE_TYPE(math, OP_EQUAL, DICTIONARY) { + if (p_b.type != DICTIONARY) + _RETURN_FAIL; + + const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); + const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); + + _RETURN(*arr_a == *arr_b); + } - case NIL: { + CASE_TYPE(math, OP_EQUAL, ARRAY) { + if (p_b.type != ARRAY) + _RETURN_FAIL; - _RETURN(p_b.type == NIL || (p_b.type == Variant::OBJECT && !p_b._get_obj().obj)); - } break; + const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); + const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - DEFAULT_OP_NUM(==, BOOL, _bool); - DEFAULT_OP_NUM(==, INT, _int); - DEFAULT_OP_NUM(==, REAL, _real); - DEFAULT_OP_STR(==, STRING, String); - DEFAULT_OP_LOCALMEM(==, VECTOR2, Vector2); - DEFAULT_OP_LOCALMEM(==, RECT2, Rect2); - DEFAULT_OP_PTRREF(==, TRANSFORM2D, _transform2d); - DEFAULT_OP_LOCALMEM(==, VECTOR3, Vector3); - DEFAULT_OP_LOCALMEM(==, PLANE, Plane); - DEFAULT_OP_LOCALMEM(==, QUAT, Quat); - DEFAULT_OP_PTRREF(==, RECT3, _rect3); - DEFAULT_OP_PTRREF(==, BASIS, _basis); - DEFAULT_OP_PTRREF(==, TRANSFORM, _transform); + int l = arr_a->size(); + if (arr_b->size() != l) + _RETURN(false); + for (int i = 0; i < l; i++) { + if (!((*arr_a)[i] == (*arr_b)[i])) { + _RETURN(false); + } + } - DEFAULT_OP_LOCALMEM(==, COLOR, Color); - DEFAULT_OP_STR(==, NODE_PATH, NodePath); - DEFAULT_OP_LOCALMEM(==, _RID, RID); - case OBJECT: { + _RETURN(true); + } + + DEFAULT_OP_NUM(math, OP_EQUAL, INT, ==, _int); + DEFAULT_OP_NUM(math, OP_EQUAL, REAL, ==, _real); + DEFAULT_OP_STR(math, OP_EQUAL, STRING, ==, String); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, VECTOR2, ==, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, RECT2, ==, Rect2); + DEFAULT_OP_PTRREF(math, OP_EQUAL, TRANSFORM2D, ==, _transform2d); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, VECTOR3, ==, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, PLANE, ==, Plane); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, QUAT, ==, Quat); + DEFAULT_OP_PTRREF(math, OP_EQUAL, RECT3, ==, _rect3); + DEFAULT_OP_PTRREF(math, OP_EQUAL, BASIS, ==, _basis); + DEFAULT_OP_PTRREF(math, OP_EQUAL, TRANSFORM, ==, _transform); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, COLOR, ==, Color); + DEFAULT_OP_STR(math, OP_EQUAL, NODE_PATH, ==, NodePath); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, _RID, ==, RID); + + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_INT_ARRAY, int); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR2_ARRAY, Vector2); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_COLOR_ARRAY, Color); + } - if (p_b.type == OBJECT) - _RETURN((p_a._get_obj().obj == p_b._get_obj().obj)); - if (p_b.type == NIL) - _RETURN(!p_a._get_obj().obj); - } break; + SWITCH_OP(math, OP_NOT_EQUAL, p_a.type) { + CASE_TYPE(math, OP_NOT_EQUAL, NIL) { + if (p_b.type == NIL) _RETURN(false); + if (p_b.type == OBJECT) + _RETURN(p_b._get_obj().obj != NULL); + _RETURN_FAIL; + } - case DICTIONARY: { + CASE_TYPE(math, OP_NOT_EQUAL, BOOL) { + if (p_b.type != BOOL) + _RETURN_FAIL; + _RETURN(p_a._data._bool != p_b._data._bool); + } - if (p_b.type != DICTIONARY) - _RETURN(false); + CASE_TYPE(math, OP_NOT_EQUAL, OBJECT) { + if (p_b.type == OBJECT) + _RETURN((p_a._get_obj().obj != p_b._get_obj().obj)); + if (p_b.type == NIL) + _RETURN(p_a._get_obj().obj != NULL); + _RETURN_FAIL; + } - const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); - const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); + CASE_TYPE(math, OP_NOT_EQUAL, DICTIONARY) { + if (p_b.type != DICTIONARY) + _RETURN_FAIL; - _RETURN(*arr_a == *arr_b); + const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); + const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); - } break; - case ARRAY: { + _RETURN((*arr_a == *arr_b) == false); + } - if (p_b.type != ARRAY) - _RETURN(false); + CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) { + if (p_b.type != ARRAY) + _RETURN_FAIL; - const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); - const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); + const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); + const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - int l = arr_a->size(); - if (arr_b->size() != l) + int l = arr_a->size(); + if (arr_b->size() != l) + _RETURN(true); + for (int i = 0; i < l; i++) { + if (((*arr_a)[i] == (*arr_b)[i])) { _RETURN(false); - for (int i = 0; i < l; i++) { - if (!((*arr_a)[i] == (*arr_b)[i])) { - _RETURN(false); - } } + } - _RETURN(true); + _RETURN(true); + } + + DEFAULT_OP_NUM(math, OP_NOT_EQUAL, INT, !=, _int); + DEFAULT_OP_NUM(math, OP_NOT_EQUAL, REAL, !=, _real); + DEFAULT_OP_STR(math, OP_NOT_EQUAL, STRING, !=, String); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, VECTOR2, !=, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, RECT2, !=, Rect2); + DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, TRANSFORM2D, !=, _transform2d); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, PLANE, !=, Plane); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, QUAT, !=, Quat); + DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, RECT3, !=, _rect3); + DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, BASIS, !=, _basis); + DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, TRANSFORM, !=, _transform); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, COLOR, !=, Color); + DEFAULT_OP_STR(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, _RID, !=, RID); + + CASE_TYPE(math, OP_NOT_EQUAL, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_INT_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; + SWITCH_OP(math, OP_LESS, p_a.type) { + CASE_TYPE(math, OP_LESS, BOOL) { + if (p_b.type != BOOL) + _RETURN_FAIL; - DEFAULT_OP_ARRAY_EQ(POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_EQ(POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_EQ(POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_EQ(POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_EQ(POOL_VECTOR2_ARRAY, Vector3); - DEFAULT_OP_ARRAY_EQ(POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_EQ(POOL_COLOR_ARRAY, Color); + if (p_a._data._bool == p_b._data._bool) + _RETURN(false); - case VARIANT_MAX: { - r_valid = false; - return; + if (p_a._data._bool && !p_b._data._bool) + _RETURN(false); - } break; + _RETURN(true); } - } break; - case OP_NOT_EQUAL: { - Variant res; - evaluate(OP_EQUAL, p_a, p_b, res, r_valid); - if (!r_valid) - return; - if (res.type == BOOL) - res._data._bool = !res._data._bool; - _RETURN(res); - - } break; - case OP_LESS: { - - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(<, BOOL, _bool); - DEFAULT_OP_NUM(<, INT, _int); - DEFAULT_OP_NUM(<, REAL, _real); - DEFAULT_OP_STR(<, STRING, String); - DEFAULT_OP_LOCALMEM(<, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM(<, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - DEFAULT_OP_FAIL(QUAT); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_LOCALMEM(<, _RID, RID); - case OBJECT: { - - if (p_b.type == OBJECT) - _RETURN((p_a._get_obj().obj < p_b._get_obj().obj)); - } break; - DEFAULT_OP_FAIL(DICTIONARY); - case ARRAY: { - - if (p_b.type != ARRAY) - _RETURN(false); - const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); - const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - - int l = arr_a->size(); - if (arr_b->size() < l) - _RETURN(false); - for (int i = 0; i < l; i++) { - if (!((*arr_a)[i] < (*arr_b)[i])) { - _RETURN(true); - } - } + CASE_TYPE(math, OP_LESS, OBJECT) { + if (p_b.type != OBJECT) + _RETURN_FAIL; + _RETURN((p_a._get_obj().obj < p_b._get_obj().obj)); + } - _RETURN(false); + CASE_TYPE(math, OP_LESS, ARRAY) { + if (p_b.type != ARRAY) + _RETURN_FAIL; - } break; - DEFAULT_OP_ARRAY_LT(POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_LT(POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_LT(POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_LT(POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_LT(POOL_VECTOR2_ARRAY, Vector3); - DEFAULT_OP_ARRAY_LT(POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_LT(POOL_COLOR_ARRAY, Color); - case VARIANT_MAX: { - r_valid = false; - return; + const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); + const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - } break; - } - - } break; - case OP_LESS_EQUAL: { - - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(<=, BOOL, _bool); - DEFAULT_OP_NUM(<=, INT, _int); - DEFAULT_OP_NUM(<=, REAL, _real); - DEFAULT_OP_STR(<=, STRING, String); - DEFAULT_OP_LOCALMEM(<=, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM(<=, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - DEFAULT_OP_FAIL(QUAT); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_LOCALMEM(<=, _RID, RID); - case OBJECT: { - - if (p_b.type == OBJECT) - _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj)); - } break; - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + int l = arr_a->size(); + if (arr_b->size() < l) + _RETURN(false); + for (int i = 0; i < l; i++) { + if (!((*arr_a)[i] < (*arr_b)[i])) { + _RETURN(true); + } + } - } break; + _RETURN(false); } - } break; - case OP_GREATER: { + DEFAULT_OP_NUM(math, OP_LESS, INT, <, _int); + DEFAULT_OP_NUM(math, OP_LESS, REAL, <, _real); + DEFAULT_OP_STR(math, OP_LESS, STRING, <, String); + DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2, <, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3, <, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_LESS, _RID, <, RID); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_INT_ARRAY, int); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR2_ARRAY, Vector3); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_COLOR_ARRAY, Color); + + CASE_TYPE(math, OP_LESS, NIL) + CASE_TYPE(math, OP_LESS, RECT2) + CASE_TYPE(math, OP_LESS, TRANSFORM2D) + CASE_TYPE(math, OP_LESS, PLANE) + CASE_TYPE(math, OP_LESS, QUAT) + CASE_TYPE(math, OP_LESS, RECT3) + CASE_TYPE(math, OP_LESS, BASIS) + CASE_TYPE(math, OP_LESS, TRANSFORM) + CASE_TYPE(math, OP_LESS, COLOR) + CASE_TYPE(math, OP_LESS, NODE_PATH) + CASE_TYPE(math, OP_LESS, DICTIONARY) + _RETURN_FAIL; + } - Variant res; - evaluate(OP_LESS, p_b, p_a, res, r_valid); - if (!r_valid) - return; - _RETURN(res); + SWITCH_OP(math, OP_LESS_EQUAL, p_a.type) { + CASE_TYPE(math, OP_LESS_EQUAL, OBJECT) { + if (p_b.type != OBJECT) + _RETURN_FAIL; + _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj)); + } + + DEFAULT_OP_NUM(math, OP_LESS_EQUAL, INT, <=, _int); + DEFAULT_OP_NUM(math, OP_LESS_EQUAL, REAL, <=, _real); + DEFAULT_OP_STR(math, OP_LESS_EQUAL, STRING, <=, String); + DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2, <=, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3, <=, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, _RID, <=, RID); + + CASE_TYPE(math, OP_LESS_EQUAL, NIL) + CASE_TYPE(math, OP_LESS_EQUAL, BOOL) + CASE_TYPE(math, OP_LESS_EQUAL, RECT2) + CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM2D) + CASE_TYPE(math, OP_LESS_EQUAL, PLANE) + CASE_TYPE(math, OP_LESS_EQUAL, QUAT) + CASE_TYPE(math, OP_LESS_EQUAL, RECT3) + CASE_TYPE(math, OP_LESS_EQUAL, BASIS) + CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM) + CASE_TYPE(math, OP_LESS_EQUAL, COLOR) + CASE_TYPE(math, OP_LESS_EQUAL, NODE_PATH) + CASE_TYPE(math, OP_LESS_EQUAL, DICTIONARY) + CASE_TYPE(math, OP_LESS_EQUAL, ARRAY) + CASE_TYPE(math, OP_LESS_EQUAL, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_INT_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; - case OP_GREATER_EQUAL: { + SWITCH_OP(math, OP_GREATER, p_a.type) { + CASE_TYPE(math, OP_GREATER, BOOL) { + if (p_b.type != BOOL) + _RETURN_FAIL; - Variant res; - evaluate(OP_LESS_EQUAL, p_b, p_a, res, r_valid); - if (!r_valid) - return; - _RETURN(res); - } break; - //mathematic - case OP_ADD: { - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(+, BOOL, _bool); - DEFAULT_OP_NUM(+, INT, _int); - DEFAULT_OP_NUM(+, REAL, _real); - DEFAULT_OP_STR(+, STRING, String); - DEFAULT_OP_LOCALMEM(+, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM(+, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - DEFAULT_OP_LOCALMEM(+, QUAT, Quat); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_LOCALMEM(+, COLOR, Color); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - - case ARRAY: { - if (p_a.type != p_b.type) { - r_valid = false; - return; - } - const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem); - const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem); - Array sum; - int asize = array_a.size(); - int bsize = array_b.size(); - sum.resize(asize + bsize); - for (int i = 0; i < asize; i++) - sum[i] = array_a[i]; - for (int i = 0; i < bsize; i++) - sum[i + asize] = array_b[i]; - _RETURN(sum); - } - DEFAULT_OP_ARRAY_ADD(POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_ADD(POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_ADD(POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_ADD(POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_ADD(POOL_VECTOR2_ARRAY, Vector2); - DEFAULT_OP_ARRAY_ADD(POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_ADD(POOL_COLOR_ARRAY, Color); - case VARIANT_MAX: { - r_valid = false; - return; + if (p_a._data._bool == p_b._data._bool) + _RETURN(false); - } break; - } - } break; - case OP_SUBSTRACT: { - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(-, BOOL, _bool); - DEFAULT_OP_NUM(-, INT, _int); - DEFAULT_OP_NUM(-, REAL, _real); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_LOCALMEM(-, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM(-, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - DEFAULT_OP_LOCALMEM(-, QUAT, Quat); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_LOCALMEM(-, COLOR, Color); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + if (!p_a._data._bool && p_b._data._bool) + _RETURN(false); - } break; + _RETURN(true); } - } break; - case OP_MULTIPLY: { - switch (p_a.type) { - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(*, BOOL, _bool); - DEFAULT_OP_NUM_VEC(*, INT, _int); - DEFAULT_OP_NUM_VEC(*, REAL, _real); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_LOCALMEM_NUM(*, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - case TRANSFORM2D: { + CASE_TYPE(math, OP_GREATER, OBJECT) { + if (p_b.type != OBJECT) + _RETURN_FAIL; + _RETURN((p_a._get_obj().obj > p_b._get_obj().obj)); + } - if (p_b.type == TRANSFORM2D) { - _RETURN(*p_a._data._transform2d * *p_b._data._transform2d); - }; - if (p_b.type == VECTOR2) { - _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem)); - }; - r_valid = false; - return; - } break; - DEFAULT_OP_LOCALMEM_NUM(*, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - case QUAT: { - - switch (p_b.type) { - case VECTOR3: { - - _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem)); - } break; - case QUAT: { - - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem)); - } break; - case REAL: { - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real); - } break; - default: {} - }; - r_valid = false; - return; - } break; - DEFAULT_OP_FAIL(RECT3); - case BASIS: { + CASE_TYPE(math, OP_GREATER, ARRAY) { + if (p_b.type != ARRAY) + _RETURN_FAIL; - switch (p_b.type) { - case VECTOR3: { + const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); + const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem)); - }; - case BASIS: { + int l = arr_a->size(); + if (arr_b->size() > l) + _RETURN(false); + for (int i = 0; i < l; i++) { + if (((*arr_a)[i] < (*arr_b)[i])) { + _RETURN(false); + } + } - _RETURN(*p_a._data._basis * *p_b._data._basis); - }; - default: {} - }; - r_valid = false; - return; - } break; - case TRANSFORM: { + _RETURN(true); + } + + DEFAULT_OP_NUM(math, OP_GREATER, INT, >, _int); + DEFAULT_OP_NUM(math, OP_GREATER, REAL, >, _real); + DEFAULT_OP_STR_REV(math, OP_GREATER, STRING, <, String); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2, <, Vector2); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3, <, Vector3); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, _RID, <, RID); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_INT_ARRAY, int); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR2_ARRAY, Vector3); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_COLOR_ARRAY, Color); + + CASE_TYPE(math, OP_GREATER, NIL) + CASE_TYPE(math, OP_GREATER, RECT2) + CASE_TYPE(math, OP_GREATER, TRANSFORM2D) + CASE_TYPE(math, OP_GREATER, PLANE) + CASE_TYPE(math, OP_GREATER, QUAT) + CASE_TYPE(math, OP_GREATER, RECT3) + CASE_TYPE(math, OP_GREATER, BASIS) + CASE_TYPE(math, OP_GREATER, TRANSFORM) + CASE_TYPE(math, OP_GREATER, COLOR) + CASE_TYPE(math, OP_GREATER, NODE_PATH) + CASE_TYPE(math, OP_GREATER, DICTIONARY) + _RETURN_FAIL; + } - switch (p_b.type) { - case VECTOR3: { + SWITCH_OP(math, OP_GREATER_EQUAL, p_a.type) { + CASE_TYPE(math, OP_GREATER_EQUAL, OBJECT) { + if (p_b.type != OBJECT) + _RETURN_FAIL; + _RETURN((p_a._get_obj().obj >= p_b._get_obj().obj)); + } + + DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, INT, >=, _int); + DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, REAL, >=, _real); + DEFAULT_OP_STR_REV(math, OP_GREATER_EQUAL, STRING, <=, String); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2, <=, Vector2); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3, <=, Vector3); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, _RID, <=, RID); + + CASE_TYPE(math, OP_GREATER_EQUAL, NIL) + CASE_TYPE(math, OP_GREATER_EQUAL, BOOL) + CASE_TYPE(math, OP_GREATER_EQUAL, RECT2) + CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM2D) + CASE_TYPE(math, OP_GREATER_EQUAL, PLANE) + CASE_TYPE(math, OP_GREATER_EQUAL, QUAT) + CASE_TYPE(math, OP_GREATER_EQUAL, RECT3) + CASE_TYPE(math, OP_GREATER_EQUAL, BASIS) + CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM) + CASE_TYPE(math, OP_GREATER_EQUAL, COLOR) + CASE_TYPE(math, OP_GREATER_EQUAL, NODE_PATH) + CASE_TYPE(math, OP_GREATER_EQUAL, DICTIONARY) + CASE_TYPE(math, OP_GREATER_EQUAL, ARRAY) + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_INT_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem)); - }; - case TRANSFORM: { + SWITCH_OP(math, OP_ADD, p_a.type) { + CASE_TYPE(math, OP_ADD, ARRAY) { + if (p_a.type != p_b.type) + _RETURN_FAIL; + + const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem); + const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem); + Array sum; + int asize = array_a.size(); + int bsize = array_b.size(); + sum.resize(asize + bsize); + for (int i = 0; i < asize; i++) + sum[i] = array_a[i]; + for (int i = 0; i < bsize; i++) + sum[i + asize] = array_b[i]; + _RETURN(sum); + } + + DEFAULT_OP_NUM(math, OP_ADD, INT, +, _int); + DEFAULT_OP_NUM(math, OP_ADD, REAL, +, _real); + DEFAULT_OP_STR(math, OP_ADD, STRING, +, String); + DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2, +, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3, +, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_ADD, QUAT, +, Quat); + DEFAULT_OP_LOCALMEM(math, OP_ADD, COLOR, +, Color); + + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_INT_ARRAY, int); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR2_ARRAY, Vector2); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_COLOR_ARRAY, Color); + + CASE_TYPE(math, OP_ADD, NIL) + CASE_TYPE(math, OP_ADD, BOOL) + CASE_TYPE(math, OP_ADD, RECT2) + CASE_TYPE(math, OP_ADD, TRANSFORM2D) + CASE_TYPE(math, OP_ADD, PLANE) + CASE_TYPE(math, OP_ADD, RECT3) + CASE_TYPE(math, OP_ADD, BASIS) + CASE_TYPE(math, OP_ADD, TRANSFORM) + CASE_TYPE(math, OP_ADD, NODE_PATH) + CASE_TYPE(math, OP_ADD, _RID) + CASE_TYPE(math, OP_ADD, OBJECT) + CASE_TYPE(math, OP_ADD, DICTIONARY) + _RETURN_FAIL; + } - _RETURN(*p_a._data._transform * *p_b._data._transform); - }; - default: {} - }; - r_valid = false; - return; - } break; - DEFAULT_OP_LOCALMEM_NUM(*, COLOR, Color); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + SWITCH_OP(math, OP_SUBTRACT, p_a.type) { + DEFAULT_OP_NUM(math, OP_SUBTRACT, INT, -, _int); + DEFAULT_OP_NUM(math, OP_SUBTRACT, REAL, -, _real); + DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2, -, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3, -, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, QUAT, -, Quat); + DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, COLOR, -, Color); + + CASE_TYPE(math, OP_SUBTRACT, NIL) + CASE_TYPE(math, OP_SUBTRACT, BOOL) + CASE_TYPE(math, OP_SUBTRACT, STRING) + CASE_TYPE(math, OP_SUBTRACT, RECT2) + CASE_TYPE(math, OP_SUBTRACT, TRANSFORM2D) + CASE_TYPE(math, OP_SUBTRACT, PLANE) + CASE_TYPE(math, OP_SUBTRACT, RECT3) + CASE_TYPE(math, OP_SUBTRACT, BASIS) + CASE_TYPE(math, OP_SUBTRACT, TRANSFORM) + CASE_TYPE(math, OP_SUBTRACT, NODE_PATH) + CASE_TYPE(math, OP_SUBTRACT, _RID) + CASE_TYPE(math, OP_SUBTRACT, OBJECT) + CASE_TYPE(math, OP_SUBTRACT, DICTIONARY) + CASE_TYPE(math, OP_SUBTRACT, ARRAY) + CASE_TYPE(math, OP_SUBTRACT, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_INT_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; + SWITCH_OP(math, OP_MULTIPLY, p_a.type) { + CASE_TYPE(math, OP_MULTIPLY, TRANSFORM2D) { + switch (p_b.type) { + case TRANSFORM2D: { + _RETURN(*p_a._data._transform2d * *p_b._data._transform2d); + } + case VECTOR2: { + _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem)); + } + default: _RETURN_FAIL; + } } - } break; - case OP_DIVIDE: { - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(/, BOOL, _bool); - case INT: { - switch (p_b.type) { - case BOOL: { - int64_t b = p_b._data._bool; - if (b == 0) { - r_valid = false; - _RETURN("Division By False"); - } - _RETURN(p_a._data._int / b); - - } break; - case INT: { - int64_t b = p_b._data._int; - if (b == 0) { + CASE_TYPE(math, OP_MULTIPLY, QUAT) { + switch (p_b.type) { + case VECTOR3: { + _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem)); + } + case QUAT: { + _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem)); + } + case REAL: { + _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real); + } + default: _RETURN_FAIL; + } + } - r_valid = false; - _RETURN("Division By Zero"); - } - _RETURN(p_a._data._int / b); + CASE_TYPE(math, OP_MULTIPLY, BASIS) { + switch (p_b.type) { + case VECTOR3: { + _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem)); + } + case BASIS: { + _RETURN(*p_a._data._basis * *p_b._data._basis); + } + default: _RETURN_FAIL; + } + } - } break; - case REAL: _RETURN(p_a._data._int / p_b._data._real); - default: {} + CASE_TYPE(math, OP_MULTIPLY, TRANSFORM) { + switch (p_b.type) { + case VECTOR3: { + _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem)); } - r_valid = false; - return; - }; - DEFAULT_OP_NUM(/, REAL, _real); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_LOCALMEM_NUM(/, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM_NUM(/, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - case QUAT: { - if (p_b.type != REAL) { - r_valid = false; - return; + case TRANSFORM: { + _RETURN(*p_a._data._transform * *p_b._data._transform); } - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real); - } break; - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_LOCALMEM_NUM(/, COLOR, Color); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + default: _RETURN_FAIL; + } + } - } break; - } - - } break; - case OP_POSITIVE: { - // Simple case when user defines variable as +value. - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - DEFAULT_OP_NUM_POS(BOOL, _bool); - DEFAULT_OP_NUM_POS(INT, _int); - DEFAULT_OP_NUM_POS(REAL, _real); - DEFAULT_OP_LOCALMEM_POS(VECTOR3, Vector3); - DEFAULT_OP_LOCALMEM_POS(PLANE, Plane); - DEFAULT_OP_LOCALMEM_POS(QUAT, Quat); - DEFAULT_OP_LOCALMEM_POS(VECTOR2, Vector2); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int); + DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, REAL, *, _real); + DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2, *, Vector2); + DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3, *, Vector3); + DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, COLOR, *, Color); + + CASE_TYPE(math, OP_MULTIPLY, NIL) + CASE_TYPE(math, OP_MULTIPLY, BOOL) + CASE_TYPE(math, OP_MULTIPLY, STRING) + CASE_TYPE(math, OP_MULTIPLY, RECT2) + CASE_TYPE(math, OP_MULTIPLY, PLANE) + CASE_TYPE(math, OP_MULTIPLY, RECT3) + CASE_TYPE(math, OP_MULTIPLY, NODE_PATH) + CASE_TYPE(math, OP_MULTIPLY, _RID) + CASE_TYPE(math, OP_MULTIPLY, OBJECT) + CASE_TYPE(math, OP_MULTIPLY, DICTIONARY) + CASE_TYPE(math, OP_MULTIPLY, ARRAY) + CASE_TYPE(math, OP_MULTIPLY, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_INT_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; - } - } break; - case OP_NEGATE: { - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM_NEG(BOOL, _bool); - DEFAULT_OP_NUM_NEG(INT, _int); - DEFAULT_OP_NUM_NEG(REAL, _real); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_LOCALMEM_NEG(VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM_NEG(VECTOR3, Vector3); - DEFAULT_OP_LOCALMEM_NEG(PLANE, Plane); - DEFAULT_OP_LOCALMEM_NEG(QUAT, Quat); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_LOCALMEM_NEG(COLOR, Color); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { + SWITCH_OP(math, OP_DIVIDE, p_a.type) { + CASE_TYPE(math, OP_DIVIDE, QUAT) { + if (p_b.type != REAL) + _RETURN_FAIL; +#ifdef DEBUG_ENABLED + if (p_b._data._real == 0) { r_valid = false; - return; + _RETURN("Division By Zero"); + } +#endif + _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real); + } + + DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int); + DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, REAL, _real); + DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2, /, Vector2); + DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3, /, Vector3); + DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, COLOR, /, Color); + + CASE_TYPE(math, OP_DIVIDE, NIL) + CASE_TYPE(math, OP_DIVIDE, BOOL) + CASE_TYPE(math, OP_DIVIDE, STRING) + CASE_TYPE(math, OP_DIVIDE, RECT2) + CASE_TYPE(math, OP_DIVIDE, TRANSFORM2D) + CASE_TYPE(math, OP_DIVIDE, PLANE) + CASE_TYPE(math, OP_DIVIDE, RECT3) + CASE_TYPE(math, OP_DIVIDE, BASIS) + CASE_TYPE(math, OP_DIVIDE, TRANSFORM) + CASE_TYPE(math, OP_DIVIDE, NODE_PATH) + CASE_TYPE(math, OP_DIVIDE, _RID) + CASE_TYPE(math, OP_DIVIDE, OBJECT) + CASE_TYPE(math, OP_DIVIDE, DICTIONARY) + CASE_TYPE(math, OP_DIVIDE, ARRAY) + CASE_TYPE(math, OP_DIVIDE, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_INT_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; - } - } break; - case OP_MODULE: { - if (p_a.type == INT && p_b.type == INT) { + SWITCH_OP(math, OP_POSITIVE, p_a.type) { + DEFAULT_OP_NUM_POS(math, OP_POSITIVE, INT, _int); + DEFAULT_OP_NUM_POS(math, OP_POSITIVE, REAL, _real); + DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3, Vector3); + DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, PLANE, Plane); + DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, QUAT, Quat); + DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2, Vector2); + + CASE_TYPE(math, OP_POSITIVE, NIL) + CASE_TYPE(math, OP_POSITIVE, BOOL) + CASE_TYPE(math, OP_POSITIVE, STRING) + CASE_TYPE(math, OP_POSITIVE, RECT2) + CASE_TYPE(math, OP_POSITIVE, TRANSFORM2D) + CASE_TYPE(math, OP_POSITIVE, RECT3) + CASE_TYPE(math, OP_POSITIVE, BASIS) + CASE_TYPE(math, OP_POSITIVE, TRANSFORM) + CASE_TYPE(math, OP_POSITIVE, COLOR) + CASE_TYPE(math, OP_POSITIVE, NODE_PATH) + CASE_TYPE(math, OP_POSITIVE, _RID) + CASE_TYPE(math, OP_POSITIVE, OBJECT) + CASE_TYPE(math, OP_POSITIVE, DICTIONARY) + CASE_TYPE(math, OP_POSITIVE, ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_BYTE_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_INT_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_REAL_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_STRING_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR2_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR3_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_COLOR_ARRAY) + _RETURN_FAIL; + } + + SWITCH_OP(math, OP_NEGATE, p_a.type) { + DEFAULT_OP_NUM_NEG(math, OP_NEGATE, INT, _int); + DEFAULT_OP_NUM_NEG(math, OP_NEGATE, REAL, _real); + + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2, Vector2); + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3, Vector3); + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, PLANE, Plane); + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, QUAT, Quat); + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, COLOR, Color); + + CASE_TYPE(math, OP_NEGATE, NIL) + CASE_TYPE(math, OP_NEGATE, BOOL) + CASE_TYPE(math, OP_NEGATE, STRING) + CASE_TYPE(math, OP_NEGATE, RECT2) + CASE_TYPE(math, OP_NEGATE, TRANSFORM2D) + CASE_TYPE(math, OP_NEGATE, RECT3) + CASE_TYPE(math, OP_NEGATE, BASIS) + CASE_TYPE(math, OP_NEGATE, TRANSFORM) + CASE_TYPE(math, OP_NEGATE, NODE_PATH) + CASE_TYPE(math, OP_NEGATE, _RID) + CASE_TYPE(math, OP_NEGATE, OBJECT) + CASE_TYPE(math, OP_NEGATE, DICTIONARY) + CASE_TYPE(math, OP_NEGATE, ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_BYTE_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_INT_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_REAL_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_STRING_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_VECTOR2_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_VECTOR3_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_COLOR_ARRAY) + _RETURN_FAIL; + } + + SWITCH_OP(math, OP_MODULE, p_a.type) { + CASE_TYPE(math, OP_MODULE, INT) { + if (p_b.type != INT) + _RETURN_FAIL; #ifdef DEBUG_ENABLED if (p_b._data._int == 0) { r_valid = false; @@ -827,8 +1007,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant & } #endif _RETURN(p_a._data._int % p_b._data._int); + } - } else if (p_a.type == STRING) { + CASE_TYPE(math, OP_MODULE, STRING) { const String *format = reinterpret_cast<const String *>(p_a._data._mem); String result; @@ -847,119 +1028,143 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant & _RETURN(result); } - r_valid = false; - return; + CASE_TYPE(math, OP_MODULE, NIL) + CASE_TYPE(math, OP_MODULE, BOOL) + CASE_TYPE(math, OP_MODULE, REAL) + CASE_TYPE(math, OP_MODULE, VECTOR2) + CASE_TYPE(math, OP_MODULE, RECT2) + CASE_TYPE(math, OP_MODULE, VECTOR3) + CASE_TYPE(math, OP_MODULE, TRANSFORM2D) + CASE_TYPE(math, OP_MODULE, PLANE) + CASE_TYPE(math, OP_MODULE, QUAT) + CASE_TYPE(math, OP_MODULE, RECT3) + CASE_TYPE(math, OP_MODULE, BASIS) + CASE_TYPE(math, OP_MODULE, TRANSFORM) + CASE_TYPE(math, OP_MODULE, COLOR) + CASE_TYPE(math, OP_MODULE, NODE_PATH) + CASE_TYPE(math, OP_MODULE, _RID) + CASE_TYPE(math, OP_MODULE, OBJECT) + CASE_TYPE(math, OP_MODULE, DICTIONARY) + CASE_TYPE(math, OP_MODULE, ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_BYTE_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_INT_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_REAL_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_STRING_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_VECTOR2_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_VECTOR3_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_COLOR_ARRAY) + _RETURN_FAIL; + } - } break; - case OP_STRING_CONCAT: { + SWITCH_OP(math, OP_STRING_CONCAT, p_a.type) { + CASE_TYPE_ALL(math, OP_STRING_CONCAT) _RETURN(p_a.operator String() + p_b.operator String()); - } break; - //bitwise - case OP_SHIFT_LEFT: { - if (p_a.type == INT && p_b.type == INT) + } + + SWITCH_OP(math, OP_SHIFT_LEFT, p_a.type) { + CASE_TYPE(math, OP_SHIFT_LEFT, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int << p_b._data._int); + } - r_valid = false; - return; + CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_LEFT) + _RETURN_FAIL; + } - } break; - case OP_SHIFT_RIGHT: { - if (p_a.type == INT && p_b.type == INT) + SWITCH_OP(math, OP_SHIFT_RIGHT, p_a.type) { + CASE_TYPE(math, OP_SHIFT_RIGHT, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int >> p_b._data._int); + } - r_valid = false; - return; + CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_RIGHT) + _RETURN_FAIL; + } - } break; - case OP_BIT_AND: { - if (p_a.type == INT && p_b.type == INT) + SWITCH_OP(math, OP_BIT_AND, p_a.type) { + CASE_TYPE(math, OP_BIT_AND, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int & p_b._data._int); + } - r_valid = false; - return; - - } break; - case OP_BIT_OR: { + CASE_TYPE_ALL_BUT_INT(math, OP_BIT_AND) + _RETURN_FAIL; + } - if (p_a.type == INT && p_b.type == INT) + SWITCH_OP(math, OP_BIT_OR, p_a.type) { + CASE_TYPE(math, OP_BIT_OR, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int | p_b._data._int); + } - r_valid = false; - return; - - } break; - case OP_BIT_XOR: { + CASE_TYPE_ALL_BUT_INT(math, OP_BIT_OR) + _RETURN_FAIL; + } - if (p_a.type == INT && p_b.type == INT) + SWITCH_OP(math, OP_BIT_XOR, p_a.type) { + CASE_TYPE(math, OP_BIT_XOR, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int ^ p_b._data._int); + } - r_valid = false; - return; - - } break; - case OP_BIT_NEGATE: { + CASE_TYPE_ALL_BUT_INT(math, OP_BIT_XOR) + _RETURN_FAIL; + } - if (p_a.type == INT) + SWITCH_OP(math, OP_BIT_NEGATE, p_a.type) { + CASE_TYPE(math, OP_BIT_NEGATE, INT) { _RETURN(~p_a._data._int); + } - r_valid = false; - return; + CASE_TYPE_ALL_BUT_INT(math, OP_BIT_NEGATE) + _RETURN_FAIL; + } - } break; - //logic - case OP_AND: { - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; - bool r = p_b.booleanize(r_valid); - if (!r_valid) - return; + SWITCH_OP(math, OP_AND, p_a.type) { + CASE_TYPE_ALL(math, OP_AND) { + bool l = p_a.booleanize(); + bool r = p_b.booleanize(); - _RETURN(l && r); - } break; - case OP_OR: { - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; - bool r = p_b.booleanize(r_valid); - if (!r_valid) - return; + _RETURN(l && r); + } + } - _RETURN(l || r); + SWITCH_OP(math, OP_OR, p_a.type) { + CASE_TYPE_ALL(math, OP_OR) { + bool l = p_a.booleanize(); + bool r = p_b.booleanize(); - } break; - case OP_XOR: { - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; - bool r = p_b.booleanize(r_valid); - if (!r_valid) - return; + _RETURN(l || r); + } + } - _RETURN((l || r) && !(l && r)); - } break; - case OP_NOT: { + SWITCH_OP(math, OP_XOR, p_a.type) { + CASE_TYPE_ALL(math, OP_XOR) { + bool l = p_a.booleanize(); + bool r = p_b.booleanize(); - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; - _RETURN(!l); + _RETURN((l || r) && !(l && r)); + } + } - } break; - case OP_IN: { + SWITCH_OP(math, OP_NOT, p_a.type) { + CASE_TYPE_ALL(math, OP_NOT) { + bool l = p_a.booleanize(); + _RETURN(!l); + } + } + SWITCH_OP(math, OP_IN, p_a.type) { + CASE_TYPE_ALL(math, OP_IN) _RETURN(p_b.in(p_a, &r_valid)); - - } break; - case OP_MAX: { - - r_valid = false; - ERR_FAIL(); } } - - r_valid = false; } void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) { @@ -1512,7 +1717,8 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) DEFAULT_OP_DVECTOR_SET(POOL_VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2) // 25 DEFAULT_OP_DVECTOR_SET(POOL_VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3) DEFAULT_OP_DVECTOR_SET(POOL_COLOR_ARRAY, Color, p_value.type != Variant::COLOR) - default: return; + default: + return; } } @@ -1885,7 +2091,8 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { DEFAULT_OP_DVECTOR_GET(POOL_VECTOR2_ARRAY, Vector2) // 25 DEFAULT_OP_DVECTOR_GET(POOL_VECTOR3_ARRAY, Vector3) DEFAULT_OP_DVECTOR_GET(POOL_COLOR_ARRAY, Color) - default: return Variant(); + default: + return Variant(); } return Variant(); @@ -2374,7 +2581,8 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { return true; } break; - default: {} + default: { + } } valid = false; @@ -2401,7 +2609,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { return true; } break; case VECTOR2: { - int64_t to = reinterpret_cast<const Vector3 *>(_data._mem)->y; + int64_t to = reinterpret_cast<const Vector2 *>(_data._mem)->y; int64_t idx = r_iter; idx++; @@ -2793,7 +3001,9 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) r_dst = Color(r, g, b, a); } return; - default: { r_dst = c < 0.5 ? a : b; } + default: { + r_dst = c < 0.5 ? a : b; + } return; } } diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index 7b120afa51..b61cf93ef7 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -23,11 +23,11 @@ <argument index="3" name="a8" type="int"> </argument> <description> - Returns a 32 bit color with red, green, blue and alpha channels. Each channel has 8bits of information ranging from 0 to 255. - 'r8' red channel - 'g8' green channel - 'b8' blue channel - 'a8' alpha channel + Returns a 32 bit color with red, green, blue and alpha channels. Each channel has 8 bits of information ranging from 0 to 255. + [code]r8[/code] red channel + [code]g8[/code] green channel + [code]b8[/code] blue channel + [code]a8[/code] alpha channel [codeblock] red = Color8(255, 0, 0) [/codeblock] @@ -41,7 +41,7 @@ <argument index="1" name="alpha" type="float"> </argument> <description> - Returns color 'name' with alpha ranging from 0 to 1. Note: 'name' is defined in color_names.inc. + Returns color [code]name[/code] with [code]alpha[/code] ranging from 0 to 1. Note: [code]name[/code] is defined in color_names.inc. [codeblock] red = ColorN('red') [/codeblock] @@ -53,7 +53,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the absolute value of parameter 's' (i.e. unsigned value, works for integer and float). + Returns the absolute value of parameter [code]s[/code] (i.e. unsigned value, works for integer and float). [codeblock] # a is 1 a = abs(-1) @@ -66,7 +66,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the arc cosine of 's' in radians. Use to get the angle of cosine 's'. + Returns the arc cosine of [code]s[/code] in radians. Use to get the angle of cosine [code]s[/code]. [codeblock] # c is 0.523599 or 30 degrees if converted with rad2deg(s) c = acos(0.866025) @@ -79,7 +79,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the arc sine of 's' in radians. Use to get the angle of sine 's'. + Returns the arc sine of [code]s[/code] in radians. Use to get the angle of sine [code]s[/code]. [codeblock] # s is 0.523599 or 30 degrees if converted with rad2deg(s) s = asin(0.5) @@ -92,7 +92,7 @@ <argument index="0" name="condition" type="bool"> </argument> <description> - Assert that the condition is true. If the condition is false a fatal error is generated and the program is halted. Useful for debugging to make sure a value is always true. + Assert that the [code]condition[/code] is true. If the [code]condition[/code] is false a fatal error is generated and the program is halted. Useful for debugging to make sure a value is always true. [codeblock] # Speed should always be between 0 and 20 speed = -10 @@ -108,7 +108,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the arc tangent of 's' in radians. Use it to get the angle from an angle's tangent in trigonometry: [code]atan(tan(angle)) == angle[/code]. + Returns the arc tangent of [code]s[/code] in radians. Use it to get the angle from an angle's tangent in trigonometry: [code]atan(tan(angle)) == angle[/code]. The method cannot know in which quadrant the angle should fall. See [method atan2] if you always want an exact angle. [codeblock] a = atan(0.5) # a is 0.463648 @@ -123,7 +123,7 @@ <argument index="1" name="y" type="float"> </argument> <description> - Returns the arc tangent of y/x in radians. Use to get the angle of tangent y/x. To compute the value, the method takes into account the sign of both arguments in order to determine the quadrant. + Returns the arc tangent of [code]y/x[/code] in radians. Use to get the angle of tangent [code]y/x[/code]. To compute the value, the method takes into account the sign of both arguments in order to determine the quadrant. [codeblock] a = atan(0,-1) # a is 3.141593 [/codeblock] @@ -135,7 +135,7 @@ <argument index="0" name="bytes" type="PoolByteArray"> </argument> <description> - Decode a byte array back to a value. + Decodes a byte array back to a value. </description> </method> <method name="ceil"> @@ -144,7 +144,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Rounds 's' upward, returning the smallest integral value that is not less than 's'. + Rounds [code]s[/code] upward, returning the smallest integral value that is not less than [code]s[/code]. [codeblock] i = ceil(1.45) # i is 2 i = ceil(1.001) # i is 2 @@ -157,7 +157,7 @@ <argument index="0" name="ascii" type="int"> </argument> <description> - Returns a character as String of the given ASCII code. + Returns a character as a String of the given ASCII code. [codeblock] # a is 'A' a = char(65) @@ -176,7 +176,7 @@ <argument index="2" name="max" type="float"> </argument> <description> - Clamp 'val' and return a value not less than 'min' and not more than 'max'. + Clamps [code]val[/code] and returns a value not less than [code]min[/code] and not more than [code]max[/code]. [codeblock] speed = 1000 # a is 20 @@ -196,7 +196,7 @@ <argument index="1" name="type" type="int"> </argument> <description> - Convert from a type to another in the best way possible. The "type" parameter uses the enum TYPE_* in [@Global Scope]. + Converts from a type to another in the best way possible. The [code]type[/code] parameter uses the enum TYPE_* in [@Global Scope]. [codeblock] a = Vector2(1, 0) # prints 1 @@ -214,7 +214,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the cosine of angle 's' in radians. + Returns the cosine of angle [code]s[/code] in radians. [codeblock] # prints 1 and -1 print(cos(PI*2)) @@ -228,7 +228,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the hyperbolic cosine of 's' in radians. + Returns the hyperbolic cosine of [code]s[/code] in radians. [codeblock] # prints 1.543081 print(cosh(1)) @@ -241,7 +241,7 @@ <argument index="0" name="db" type="float"> </argument> <description> - Convert from decibels to linear energy (audio). + Converts from decibels to linear energy (audio). </description> </method> <method name="decimals"> @@ -250,7 +250,7 @@ <argument index="0" name="step" type="float"> </argument> <description> - Returns the number of digit places after the decimal that the first non-zero digit occurs. + Returns the position of the first non-zero digit, after the decimal point. [codeblock] # n is 2 n = decimals(0.035) @@ -267,7 +267,7 @@ <argument index="2" name="step" type="float"> </argument> <description> - Returns the result of 'value' decreased by 'step' * 'amount'. + Returns the result of [code]value[/code] decreased by [code]step[/code] * [code]amount[/code]. [codeblock] # a = 59 a = dectime(60, 10, 0.1)) @@ -293,7 +293,7 @@ <argument index="0" name="dict" type="Dictionary"> </argument> <description> - Convert a previously converted instance to dictionary back into an instance. Useful for deserializing. + Converts a previously converted instance to a dictionary, back into an instance. Useful for deserializing. </description> </method> <method name="ease"> @@ -313,7 +313,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Raises the Euler's constant [b]e[/b] to the power of 's' and returns it. [b] has an approximate value of 2.71828. + Raises the Euler's constant [b]e[/b] to the power of [code]s[/code] and returns it. [b]e[/b] has an approximate value of 2.71828. [codeblock] a = exp(2) # approximately 7.39 [/codeblock] @@ -325,7 +325,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Rounds 's' to the closest smaller integer and returns it. + Rounds [code]s[/code] to the closest smaller integer and returns it. [codeblock] # a is 2 a = floor(2.99) @@ -342,11 +342,11 @@ <argument index="1" name="y" type="float"> </argument> <description> - Returns the floating-point remainder of x/y (rounded towards zero): + Returns the floating-point remainder of [code]x/y[/code]. [codeblock] - fmod = x - tquot * y + # remainder is 1.5 + var remainder = fmod(7, 5.5) [/codeblock] - Where tquot is the truncated (i.e., rounded towards zero) result of: x/y. </description> </method> <method name="fposmod"> @@ -357,7 +357,7 @@ <argument index="1" name="y" type="float"> </argument> <description> - Returns the floating-point remainder of x/y that wraps equally in positive and negative. + Returns the floating-point remainder of [code]x/y[/code] that wraps equally in positive and negative. [codeblock] var i = -10; while i < 0: @@ -387,7 +387,7 @@ <argument index="1" name="funcname" type="String"> </argument> <description> - Returns a reference to the specified function 'funcname' in the 'instance' node. As functions aren't first-class objects in GDscript, use 'funcref' to store a function in a variable and call it later. + Returns a reference to the specified function [code]funcname[/code] in the [code]instance[/code] node. As functions aren't first-class objects in GDscript, use [code]funcref[/code] to store a [FuncRef] in a variable and call it later. [codeblock] func foo(): return("bar") @@ -415,7 +415,7 @@ <argument index="0" name="inst" type="Object"> </argument> <description> - Returns the passed instance converted a dictionary (useful for serializing). + Returns the passed instance converted to a dictionary (useful for serializing). [codeblock] var foo = "bar" func _ready(): @@ -436,7 +436,7 @@ <argument index="0" name="instance_id" type="int"> </argument> <description> - Returns the Object that corresponds to 'instance_id'. All Objects have a unique instance ID. + Returns the Object that corresponds to [code]instance_id[/code]. All Objects have a unique instance ID. [codeblock] var foo = "bar" func _ready(): @@ -468,7 +468,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns True/False whether 's' is an infinity value (either positive infinity or negative infinity). + Returns True/False whether [code]s[/code] is an infinity value (either positive infinity or negative infinity). </description> </method> <method name="is_nan"> @@ -477,7 +477,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns True/False whether 's' is a NaN (Not-A-Number) value. + Returns True/False whether [code]s[/code] is a NaN (Not-A-Number) value. </description> </method> <method name="len"> @@ -486,7 +486,7 @@ <argument index="0" name="var" type="Variant"> </argument> <description> - Returns length of Variant 'var'. Length is the character count of String, element count of Array, size of Dictionary, etc. Note: Generates a fatal error if Variant can not provide a length. + Returns length of Variant [code]var[/code]. Length is the character count of String, element count of Array, size of Dictionary, etc. Note: Generates a fatal error if Variant can not provide a length. [codeblock] a = [1, 2, 3, 4] len(a) # returns 4 @@ -503,7 +503,7 @@ <argument index="2" name="weight" type="float"> </argument> <description> - Linear interpolates between two values by a normalized value. + Linearly interpolates between two values by a normalized value. [codeblock] lerp(1, 3, 0.5) # returns 2 [/codeblock] @@ -515,7 +515,7 @@ <argument index="0" name="nrg" type="float"> </argument> <description> - Convert from linear energy to decibels (audio). + Converts from linear energy to decibels (audio). </description> </method> <method name="load"> @@ -524,7 +524,7 @@ <argument index="0" name="path" type="String"> </argument> <description> - Load a resource from the filesystem located at 'path'. Note: resource paths can be obtained by right clicking on a resource in the Assets Pannel and choosing "Copy Path". + Loads a resource from the filesystem located at 'path'. Note: resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path". [codeblock] # load a scene called main located in the root of the project directory var main = load("res://main.tscn") @@ -537,7 +537,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Natural logarithm. The amount of time needed to reach a certain level of continuous growth. Note: This is not the same as the log funcation on your calculator which is a base 10 logarithm. + Natural logarithm. The amount of time needed to reach a certain level of continuous growth. Note: This is not the same as the log function on your calculator which is a base 10 logarithm. [codeblock] log(10) # returns 2.302585 [/codeblock] @@ -579,7 +579,7 @@ <argument index="0" name="val" type="int"> </argument> <description> - Returns the nearest larger power of 2 for integer 'val'. + Returns the nearest larger power of 2 for integer [code]val[/code]. [codeblock] nearest_po2(3) # returns 4 nearest_po2(4) # returns 4 @@ -594,7 +594,7 @@ </argument> <description> Parse JSON text to a Variant (use [method typeof] to check if it is what you expect). - Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert every numerical values to [float] types. + Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert all numerical values to [float] types. [codeblock] p = parse_json('["a", "b", "c"]') if typeof(p) == TYPE_ARRAY: @@ -612,7 +612,7 @@ <argument index="1" name="y" type="float"> </argument> <description> - Returns the result of 'x' raised to the power of 'y'. + Returns the result of [code]x[/code] raised to the power of [code]y[/code]. [codeblock] pow(2,5) # returns 32 [/codeblock] @@ -624,7 +624,7 @@ <argument index="0" name="path" type="String"> </argument> <description> - Returns a resource from the filesystem that is loaded during script parsing. Note: resource paths can be obtained by right clicking on a resource in the Assets Pannel and choosing "Copy Path". + Returns a resource from the filesystem that is loaded during script parsing. Note: resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path". [codeblock] # load a scene called main located in the root of the project directory var main = preload("res://main.tscn") @@ -646,7 +646,7 @@ <return type="void"> </return> <description> - Print a stack track at code location, only works when running with debugger turned on. + Prints a stack track at code location, only works when running with debugger turned on. Output in the console would look something like this: [codeblock] Frame 0 - res://test.gd:16 in function '_process' @@ -657,7 +657,7 @@ <return type="void"> </return> <description> - Print one or more arguments to strings in the best way possible to standard error line. + Prints one or more arguments to strings in the best way possible to standard error line. [codeblock] printerr("prints to stderr") [/codeblock] @@ -667,7 +667,7 @@ <return type="void"> </return> <description> - Print one or more arguments to strings in the best way possible to console. No newline is added at the end. + Prints one or more arguments to strings in the best way possible to console. No newline is added at the end. [codeblock] printraw("A") printraw("B") @@ -679,7 +679,7 @@ <return type="void"> </return> <description> - Print one or more arguments to the console with a space between each argument. + Prints one or more arguments to the console with a space between each argument. [codeblock] prints("A", "B", "C") # prints A B C [/codeblock] @@ -689,7 +689,7 @@ <return type="void"> </return> <description> - Print one or more arguments to the console with a tab between each argument. + Prints one or more arguments to the console with a tab between each argument. [codeblock] printt("A", "B", "C") # prints A B C [/codeblock] @@ -701,7 +701,7 @@ <argument index="0" name="rad" type="float"> </argument> <description> - Convert from radians to degrees. + Converts from radians to degrees. [codeblock] rad2deg(0.523599) # returns 30 [/codeblock] @@ -715,7 +715,7 @@ <argument index="1" name="to" type="float"> </argument> <description> - Random range, any floating point value between 'from' and 'to'. + Random range, any floating point value between [code]from[/code] and [code]to[/code]. [codeblock] prints(rand_range(0, 1), rand_range(0, 1)) # prints 0.135591 0.405263 [/codeblock] @@ -727,14 +727,14 @@ <argument index="0" name="seed" type="int"> </argument> <description> - Random from seed: pass a seed, and an array with both number and new seed is returned. "Seed" here refers to the internal state of the pseudo random number generator. The internal state of the current implementation is 64 bits. + Random from seed: pass a [code]seed[/code], and an array with both number and new seed is returned. "Seed" here refers to the internal state of the pseudo random number generator. The internal state of the current implementation is 64 bits. </description> </method> <method name="randf"> <return type="float"> </return> <description> - Return a random floating point value between 0 and 1. + Returns a random floating point value between 0 and 1. [codeblock] randf() # returns 0.375671 [/codeblock] @@ -744,7 +744,7 @@ <return type="int"> </return> <description> - Return a random 32 bit integer. Use remainder to obtain a random value between 0 and N (where N is smaller than 2^32 -1). + Returns a random 32 bit integer. Use remainder to obtain a random value between 0 and N (where N is smaller than 2^32 -1). [codeblock] randi() % 20 # returns random number between 0 and 19 randi() % 100 # returns random number between 0 and 99 @@ -756,7 +756,7 @@ <return type="void"> </return> <description> - Randomize the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time. + Randomizes the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time. [codeblock] func _ready(): randomize() @@ -767,7 +767,7 @@ <return type="Array"> </return> <description> - Return an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial, final-1, increment). + Returns an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial, final-1, increment). [codeblock] for i in range(4): print(i) @@ -807,7 +807,7 @@ <argument index="4" name="ostop" type="float"> </argument> <description> - Maps a value from range [istart, istop] to [ostart, ostop]. + Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code]. [codeblock] range_lerp(75, 0, 100, -1, 1) # returns 0.5 [/codeblock] @@ -819,7 +819,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the integral value that is nearest to s, with halfway cases rounded away from zero. + Returns the integral value that is nearest to [code]s[/code], with halfway cases rounded away from zero. [codeblock] round(2.6) # returns 3 [/codeblock] @@ -831,7 +831,7 @@ <argument index="0" name="seed" type="int"> </argument> <description> - Set seed for the random number generator. + Sets seed for the random number generator. [codeblock] my_seed = "Godot Rocks" seed(my_seed.hash()) @@ -844,7 +844,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Return sign of 's' -1 or 1. + Returns sign of [code]s[/code] -1 or 1. [codeblock] sign(-6) # returns -1 sign(6) # returns 1 @@ -857,7 +857,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Return the sine of angle 's' in radians. + Returns the sine of angle [code]s[/code] in radians. [codeblock] sin(0.523599) # returns 0.5 [/codeblock] @@ -869,7 +869,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Return the hyperbolic sine of 's'. + Returns the hyperbolic sine of [code]s[/code]. [codeblock] a = log(2.0) # returns 0.693147 sinh(a) # returns 0.75 @@ -882,7 +882,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Return the square root of 's'. + Returns the square root of [code]s[/code]. [codeblock] sqrt(9) # returns 3 [/codeblock] @@ -896,14 +896,14 @@ <argument index="1" name="step" type="float"> </argument> <description> - Snap float value to a given step. + Snaps float value [code]s[/code] to a given [code]step[/code]. </description> </method> <method name="str" qualifiers="vararg"> <return type="String"> </return> <description> - Convert one or more arguments to string in the best way possible. + Converts one or more arguments to string in the best way possible. [codeblock] var a = [10, 20, 30] var b = str(a); @@ -918,7 +918,7 @@ <argument index="0" name="string" type="String"> </argument> <description> - Convert a formatted string that was returned by [method var2str] to the original value. + Converts a formatted string that was returned by [method var2str] to the original value. [codeblock] a = '{ "a": 1, "b": 2 }' b = str2var(a) @@ -932,7 +932,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Return the tangent of angle 's' in radians. + Returns the tangent of angle [code]s[/code] in radians. [codeblock] tan( deg2rad(45) ) # returns 1 [/codeblock] @@ -944,7 +944,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the hyperbolic tangent of 's'. + Returns the hyperbolic tangent of [code]s[/code]. [codeblock] a = log(2.0) # returns 0.693147 tanh(a) # returns 0.6 @@ -957,7 +957,7 @@ <argument index="0" name="var" type="Variant"> </argument> <description> - Convert a Variant 'var' to json text and return the result. Useful for serializing data to store or send over the network + Converts a Variant [code]var[/code] to JSON text and return the result. Useful for serializing data to store or send over the network. [codeblock] a = { 'a': 1, 'b': 2 } b = to_json(a) @@ -971,7 +971,7 @@ <argument index="0" name="type" type="String"> </argument> <description> - Returns whether the given class is exist in [ClassDB]. + Returns whether the given class exists in [ClassDB]. [codeblock] type_exists("Sprite") # returns true type_exists("Variant") # returns false @@ -984,7 +984,7 @@ <argument index="0" name="what" type="Variant"> </argument> <description> - Return the internal type of the given Variant object, using the TYPE_* enum in [@Global Scope]. + Returns the internal type of the given Variant object, using the TYPE_* enum in [@Global Scope]. [codeblock] p = parse_json('["a", "b", "c"]') if typeof(p) == TYPE_ARRAY: @@ -1000,7 +1000,7 @@ <argument index="0" name="json" type="String"> </argument> <description> - Check that 'json' is valid json data. Return empty string if valid. Return error message if not valid. + Checks that [code]json[/code] is valid JSON data. Returns empty string if valid. Returns error message if not valid. [codeblock] j = to_json([1, 2, 3]) v = validate_json(j) @@ -1017,7 +1017,7 @@ <argument index="0" name="var" type="Variant"> </argument> <description> - Encode a variable value to a byte array. + Encodes a variable value to a byte array. </description> </method> <method name="var2str"> @@ -1026,7 +1026,7 @@ <argument index="0" name="var" type="Variant"> </argument> <description> - Convert a value to a formatted string that can later be parsed using [method str2var]. + Converts a Variant [code]var[/code] to a formatted string that can later be parsed using [method str2var]. [codeblock] a = { 'a': 1, 'b': 2 } print(var2str(a)) @@ -1046,7 +1046,7 @@ <argument index="0" name="obj" type="Object"> </argument> <description> - Return a weak reference to an object. + Returns a weak reference to an object. A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it. </description> </method> @@ -1058,7 +1058,7 @@ <argument index="1" name="signal" type="String"> </argument> <description> - Stop the function execution and return the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state. + Stops the function execution and returns the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state. Returns anything that was passed to the resume function call. If passed an object and a signal, the execution is resumed when the object's signal is emitted. </description> </method> diff --git a/doc/classes/BoxContainer.xml b/doc/classes/BoxContainer.xml index f7e50f02d8..0c70d919f3 100644 --- a/doc/classes/BoxContainer.xml +++ b/doc/classes/BoxContainer.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="BoxContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Base class for Box containers. + Base class for box containers. </brief_description> <description> - Base class for Box containers. It arranges children controls vertically or horizontally, and rearranges them automatically when their minimum size changes. + Arranges child controls vertically or horizontally, and rearranges the controls automatically when their minimum size changes. </description> <tutorials> </tutorials> @@ -17,8 +17,7 @@ <argument index="0" name="begin" type="bool"> </argument> <description> - Add a control to the box as a spacer. - If [i]begin[/i] is true the spacer control will be inserted in front of other children. + Adds a control to the box as a spacer. If [code]true[/code], [i]begin[/i] will insert the spacer control in front of other children. </description> </method> <method name="get_alignment" qualifiers="const"> @@ -40,17 +39,18 @@ </methods> <members> <member name="alignment" type="int" setter="set_alignment" getter="get_alignment" enum="BoxContainer.AlignMode"> + The alignment of the container's children (must be one of ALIGN_BEGIN, ALIGN_CENTER, or ALIGN_END). </member> </members> <constants> <constant name="ALIGN_BEGIN" value="0"> - Align children with beginning of the container. + Aligns children with the beginning of the container. </constant> <constant name="ALIGN_CENTER" value="1"> - Align children with center of the container. + Aligns children with the center of the container. </constant> <constant name="ALIGN_END" value="2"> - Align children with end of the container. + Aligns children with the end of the container. </constant> </constants> </class> diff --git a/doc/classes/BoxShape.xml b/doc/classes/BoxShape.xml index 8c98c93b57..4e8eb0ba6f 100644 --- a/doc/classes/BoxShape.xml +++ b/doc/classes/BoxShape.xml @@ -4,7 +4,7 @@ Box shape resource. </brief_description> <description> - Box shape resource, which can be set into a [PhysicsBody] or area. + 3D box shape that can be a child of a [PhysicsBody] or [Area]. </description> <tutorials> </tutorials> @@ -30,6 +30,7 @@ </methods> <members> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents"> + The shape's half extents. </member> </members> <constants> diff --git a/doc/classes/CapsuleShape.xml b/doc/classes/CapsuleShape.xml index 29072203ea..db075a504c 100644 --- a/doc/classes/CapsuleShape.xml +++ b/doc/classes/CapsuleShape.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CapsuleShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Capsule shape resource. + Capsule shape for collisions. </brief_description> <description> - Capsule shape resource, which can be set into a [PhysicsBody] or area. + Capsule shape for collisions. </description> <tutorials> </tutorials> @@ -46,8 +46,10 @@ </methods> <members> <member name="height" type="float" setter="set_height" getter="get_height"> + The capsule's height. </member> <member name="radius" type="float" setter="set_radius" getter="get_radius"> + The capsule's radius. </member> </members> <constants> diff --git a/doc/classes/CapsuleShape2D.xml b/doc/classes/CapsuleShape2D.xml index 9c2b1c4a3d..df833e0582 100644 --- a/doc/classes/CapsuleShape2D.xml +++ b/doc/classes/CapsuleShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CapsuleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Capsule 2D shape resource for physics. + Capsule shape for 2D collisions. </brief_description> <description> - Capsule 2D shape resource for physics. A capsule (or sometimes called "pill") is like a line grown in all directions. It has a radius and a height, and is often useful for modeling biped characters. + Capsule shape for 2D collisions. </description> <tutorials> </tutorials> @@ -46,8 +46,10 @@ </methods> <members> <member name="height" type="float" setter="set_height" getter="get_height"> + The capsule's height. </member> <member name="radius" type="float" setter="set_radius" getter="get_radius"> + The capsules's radius. </member> </members> <constants> diff --git a/doc/classes/CircleShape2D.xml b/doc/classes/CircleShape2D.xml index c3d4bdae03..1ed54f0705 100644 --- a/doc/classes/CircleShape2D.xml +++ b/doc/classes/CircleShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CircleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Circular Shape for 2D Physics. + Circular shape for 2D collisions. </brief_description> <description> - Circular Shape for 2D Physics. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast. + Circular shape for 2D collisions. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast. </description> <tutorials> </tutorials> @@ -30,6 +30,7 @@ </methods> <members> <member name="radius" type="float" setter="set_radius" getter="get_radius"> + The circle's radius. </member> </members> <constants> diff --git a/doc/classes/KinematicCollision.xml b/doc/classes/KinematicCollision.xml index 5e5b125654..b7269a646e 100644 --- a/doc/classes/KinematicCollision.xml +++ b/doc/classes/KinematicCollision.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="KinematicCollision" inherits="Reference" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Collision data for KinematicBody2D collisions. </brief_description> <description> + Contains collision data for KinematicBody collisions. When a [KinematicBody] is moved using [method KinematicBody.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a KinematicCollision object is returned. + This object contains information about the collision, including the colliding object, the remaining motion, and the collision position. This information can be used to calculate a collision response. </description> <tutorials> </tutorials> @@ -78,26 +81,37 @@ </methods> <members> <member name="collider" type="Object" setter="" getter="get_collider"> + The colliding body. </member> <member name="collider_id" type="int" setter="" getter="get_collider_id"> + The colliding body's unique [RID]. </member> <member name="collider_metadata" type="Variant" setter="" getter="get_collider_metadata"> + The colliding body's metadata. See [Object]. </member> <member name="collider_shape" type="Object" setter="" getter="get_collider_shape"> + The colliding body's shape. </member> <member name="collider_shape_index" type="int" setter="" getter="get_collider_shape_index"> + The colliding shape's index. See [CollisionObject]. </member> <member name="collider_velocity" type="Vector3" setter="" getter="get_collider_velocity"> + The colliding object's velocity. </member> <member name="local_shape" type="Object" setter="" getter="get_local_shape"> + The moving object's colliding shape. </member> <member name="normal" type="Vector3" setter="" getter="get_normal"> + The colliding body's shape's normal at the point of collision. </member> <member name="position" type="Vector3" setter="" getter="get_position"> + The point of collision. </member> <member name="remainder" type="Vector3" setter="" getter="get_remainder"> + The moving object's remaining movement vector. </member> <member name="travel" type="Vector3" setter="" getter="get_travel"> + The distance the moving object traveled before collision. </member> </members> <constants> diff --git a/doc/classes/LineShape2D.xml b/doc/classes/LineShape2D.xml index 3346c46a19..5596c48162 100644 --- a/doc/classes/LineShape2D.xml +++ b/doc/classes/LineShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="LineShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Line shape for 2D collision objects. + Line shape for 2D collisions. </brief_description> <description> - Line shape for 2D collision objects. It works like a 2D plane and will not allow any body to go to the negative side. Not recommended for rigid bodies, and usually not recommended for static bodies either because it forces checks against it on every frame. + Line shape for 2D collisions. It works like a 2D plane and will not allow any body to go to the negative side. Not recommended for rigid bodies, and usually not recommended for static bodies either because it forces checks against it on every frame. </description> <tutorials> </tutorials> @@ -46,8 +46,10 @@ </methods> <members> <member name="d" type="float" setter="set_d" getter="get_d"> + The line's distance from the origin. </member> <member name="normal" type="Vector2" setter="set_normal" getter="get_normal"> + The line's normal. </member> </members> <constants> diff --git a/doc/classes/PhysicsBody.xml b/doc/classes/PhysicsBody.xml index e8ae986346..e75fbb8e2d 100644 --- a/doc/classes/PhysicsBody.xml +++ b/doc/classes/PhysicsBody.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="PhysicsBody" inherits="CollisionObject" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Base class for different types of Physics bodies. + Base class for all objects affected by physics in 3D space. </brief_description> <description> - PhysicsBody is an abstract base class for implementing a physics body. All PhysicsBody types inherit from it. + PhysicsBody is an abstract base class for implementing a physics body. All *Body types inherit from it. </description> <tutorials> </tutorials> @@ -17,7 +17,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> - Adds a body to the collision exception list. This list contains bodies that this body will not collide with. + Adds a body to the list of bodies that this body can't collide with. </description> </method> <method name="get_collision_layer" qualifiers="const"> @@ -54,7 +54,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> - Removes a body from the collision exception list. + Removes a body from the list of bodies that this body can't collide with. </description> </method> <method name="set_collision_layer"> @@ -96,8 +96,12 @@ </methods> <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer"> + 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. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> + The physics layers this area can scan for collisions. </member> </members> <constants> diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml index e160311090..748506baa9 100644 --- a/doc/classes/PhysicsBody2D.xml +++ b/doc/classes/PhysicsBody2D.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Base class for all objects affected by physics. + Base class for all objects affected by physics in 2D space. </brief_description> <description> PhysicsBody2D is an abstract base class for implementing a physics body. All *Body2D types inherit from it. @@ -17,6 +17,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> + Adds a body to the list of bodies that this body can't collide with. </description> </method> <method name="get_collision_layer" qualifiers="const"> @@ -57,6 +58,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> + Removes a body from the list of bodies that this body can't collide with. </description> </method> <method name="set_collision_layer"> @@ -104,10 +106,15 @@ </methods> <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer"> + 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. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> + The physics layers this area can scan for collisions. </member> <member name="layers" type="int" setter="_set_layers" getter="_get_layers"> + Both collision_layer and collision_mask. Returns collision_layer when accessed. Updates collision_layers and collision_mask when modified. </member> </members> <constants> diff --git a/doc/classes/RayShape2D.xml b/doc/classes/RayShape2D.xml index 8414ee2348..4f6313a1d2 100644 --- a/doc/classes/RayShape2D.xml +++ b/doc/classes/RayShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RayShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Ray 2D shape resource for physics. + Ray shape for 2D collisions. </brief_description> <description> - Ray 2D shape resource for physics. A ray is not really a collision body, instead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + Ray shape for 2D collisions. A ray is not really a collision body, instead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. </description> <tutorials> </tutorials> @@ -30,6 +30,7 @@ </methods> <members> <member name="length" type="float" setter="set_length" getter="get_length"> + The ray's length. </member> </members> <constants> diff --git a/doc/classes/RectangleShape2D.xml b/doc/classes/RectangleShape2D.xml index 9c18df970b..7a1aec2021 100644 --- a/doc/classes/RectangleShape2D.xml +++ b/doc/classes/RectangleShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RectangleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Rectangle Shape for 2D Physics. + Rectangle shape for 2D collisions. </brief_description> <description> - Rectangle Shape for 2D Physics. This shape is useful for modeling box-like 2D objects. + Rectangle shape for 2D collisions. This shape is useful for modeling box-like 2D objects. </description> <tutorials> </tutorials> @@ -30,6 +30,7 @@ </methods> <members> <member name="extents" type="Vector2" setter="set_extents" getter="get_extents"> + The rectangle's half extents. The width and height of this shape is twice the half extents. </member> </members> <constants> diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml index fc9d241e35..8347597daf 100644 --- a/doc/classes/RigidBody.xml +++ b/doc/classes/RigidBody.xml @@ -1,10 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RigidBody" inherits="PhysicsBody" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Rigid body node. + Physics Body whose position is determined through physics simulation in 3D space. </brief_description> <description> - Rigid body node. This node is used for placing rigid bodies in the scene. It can contain a number of shapes, and also shift mode between regular Rigid body, Kinematic, Character or Static. + This is the node that implements full 3D physics. This means that you do not control a RigidBody directly. Instead you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. + This node can use custom force integration, for writing complex physics motion behavior per node. + This node can shift state between regular Rigid body, Kinematic, Character or Static. + Character mode forbids this node from being rotated. + As a warning, don't change RigidBody's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior. </description> <tutorials> </tutorials> @@ -324,55 +328,56 @@ </methods> <members> <member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp"> - Dampens rotational forces of the Rigid body by the 'angular_damp' rate. + Damps RigidBody's rotational forces. </member> <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity"> - The current rotational velocity of the Rigid body + RigidBody's rotational velocity. </member> <member name="axis_lock" type="int" setter="set_axis_lock" getter="get_axis_lock" enum="RigidBody.AxisLock"> Locks the rotational forces to a particular axis, preventing rotations on other axes. </member> <member name="bounce" type="float" setter="set_bounce" getter="get_bounce"> - Bounciness of the Rigid body. + RigidBody's bounciness. </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep"> - If true, the Rigid body will no longer calculate forces when there is no movement and will act as a static body. It will wake up when other forces are applied through other collisions or when the 'apply_impulse' method is used. + If [code]true[/code] the RigidBody will not calculate forces and will act as a static body while there is no movement. It will wake up when forces are applied through other collisions or when the [code]apply_impulse[/code] method is used. </member> <member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled"> - If true, the Rigid body will emit signals when it collides with another Rigid body. + If true, the RigidBody will emit signals when it collides with another RigidBody. </member> <member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported"> The maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. </member> <member name="continuous_cd" type="bool" setter="set_use_continuous_collision_detection" getter="is_using_continuous_collision_detection"> - Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. The first is more precise, and misses less impacts by small, fast-moving objects. The second is faster to compute, but can miss small, fast-moving objects. + If [code]true[/code] continuous collision detection is used. + Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. Continuous collision detection is more precise, and misses less impacts by small, fast-moving objects. Not using continuous collision detection is faster to compute, but can miss small, fast-moving objects. </member> <member name="custom_integrator" type="bool" setter="set_use_custom_integrator" getter="is_using_custom_integrator"> - If true, internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined. + If [code]true[/code] internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined. </member> <member name="friction" type="float" setter="set_friction" getter="get_friction"> The body friction, from 0 (frictionless) to 1 (max friction). </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale"> - The 'gravity_scale' for this Rigid body will be multiplied by the global 3d gravity setting found in "Project > Project Settings > Physics > 3d". A value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. + This is multiplied by the global 3D gravity setting found in "Project > Project Settings > Physics > 3d" to produce RigidBody's gravity. E.g. a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp"> - The linear damp for this body. Default of -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden. + RigidBody's linear damp. Default value: -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden. </member> <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity"> - The body linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. + RigidBody's linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. </member> <member name="mass" type="float" setter="set_mass" getter="get_mass"> - The body mass. + RigidBody's mass. </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody.Mode"> The body mode from the MODE_* enum. Modes include: MODE_STATIC, MODE_KINEMATIC, MODE_RIGID, and MODE_CHARACTER. </member> <member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping"> - The current 'sleeping' state of the Rigid body. + If [code]true[/code] RigidBody is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method. </member> <member name="weight" type="float" setter="set_weight" getter="get_weight"> - The body weight given standard earth-weight (gravity 9.8). + RigidBody's weight based on its mass and the global 3D gravity. Global values are set in "Project > Project Settings > Physics > 3d". </member> </members> <signals> diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index e92c417323..a4faa697de 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -1,12 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RigidBody2D" inherits="PhysicsBody2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Rigid body 2D node. + Physics Body whose position is determined through physics simulation in 2D space. </brief_description> <description> - Rigid body 2D node. This node is used for placing rigid bodies in the scene. It can contain a number of shapes, and also shift state between regular Rigid body, Kinematic, Character or Static. - Character mode forbids the node from being rotated. This node can have a custom force integrator function, for writing complex physics motion behavior per node. - As a warning, don't change this node position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior. + This is the node that implements full 2D physics. This means that you do not control a RigidBody2D directly. Instead you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. + This node can use custom force integration, for writing complex physics motion behavior per node. + This node can shift state between regular Rigid body, Kinematic, Character or Static. + Character mode forbids this node from being rotated. + As a warning, don't change RigidBody2D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior. </description> <tutorials> </tutorials> @@ -382,36 +384,53 @@ </methods> <members> <member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp"> + Damps RigidBody2D's rotational forces. </member> <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity"> + RigidBody2D's rotational velocity. </member> <member name="bounce" type="float" setter="set_bounce" getter="get_bounce"> + RigidBody2D's bounciness. </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep"> + If [code]true[/code] RigidBody2D will not calculate forces and will act as a static body while there is no movement. It will wake up when other forces are applied through other collisions or when the [code]apply_impulse[/code] method is used. Default value: [code]true[/code] </member> <member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled"> + If [code]true[/code] RigidBody2D will emit signals when it collides with another RigidBody2D. </member> <member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported"> + The maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. </member> <member name="continuous_cd" type="int" setter="set_continuous_collision_detection_mode" getter="get_continuous_collision_detection_mode" enum="RigidBody2D.CCDMode"> + If [code]true[/code] continuous collision detection is used. Default value: [code]false[/code] + Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. Continuous collision detection is more precise, and misses less impacts by small, fast-moving objects. Not using continuous collision detection is faster to compute, but can miss small, fast-moving objects. </member> <member name="custom_integrator" type="bool" setter="set_use_custom_integrator" getter="is_using_custom_integrator"> + If [code]true[/code] internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined. </member> <member name="friction" type="float" setter="set_friction" getter="get_friction"> + The body friction, from 0 (frictionless) to 1 (max friction). </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale"> + This is multiplied by the global 2D gravity setting found in "Project > Project Settings > Physics > 2d" to produce RigidBody2D's gravity. E.g. a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp"> + RigidBody2D's linear damp. Default of -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden. </member> <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity"> + RigidBody2D's linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. </member> <member name="mass" type="float" setter="set_mass" getter="get_mass"> + RigidBody2D's mass. </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody2D.Mode"> + The body mode from the MODE_* enum. Modes include: MODE_STATIC, MODE_KINEMATIC, MODE_RIGID, and MODE_CHARACTER. </member> <member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping"> + If [code]true[/code] RigidBody2D is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method. </member> <member name="weight" type="float" setter="set_weight" getter="get_weight"> + RigidBody2D's weight based on its mass and the global 2D gravity. Global values are set in "Project > Project Settings > Physics > 2d". </member> </members> <signals> diff --git a/doc/classes/SegmentShape2D.xml b/doc/classes/SegmentShape2D.xml index 0e2c5c86f3..3b7a747bcb 100644 --- a/doc/classes/SegmentShape2D.xml +++ b/doc/classes/SegmentShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SegmentShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Segment Shape for 2D Collision Detection. + Segment shape for 2D collisions. </brief_description> <description> - Segment Shape for 2D Collision Detection, consists of two points, 'a' and 'b'. + Segment shape for 2D collisions. Consists of two points, [code]a[/code] and [code]b[/code]. </description> <tutorials> </tutorials> @@ -46,8 +46,10 @@ </methods> <members> <member name="a" type="Vector2" setter="set_a" getter="get_a"> + The segment's first point position. </member> <member name="b" type="Vector2" setter="set_b" getter="get_b"> + The segment's second point position. </member> </members> <constants> diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp index ae5fdd28b6..a184c9e9cf 100644 --- a/drivers/rtaudio/audio_driver_rtaudio.cpp +++ b/drivers/rtaudio/audio_driver_rtaudio.cpp @@ -143,7 +143,7 @@ Error AudioDriverRtAudio::init() { } } - return OK; + return active ? OK : ERR_UNAVAILABLE; } int AudioDriverRtAudio::get_mix_rate() const { diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 80565c5b02..e19bc738cb 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -274,6 +274,15 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) { }; } +Error FileAccessUnix::_chmod(const String &p_path, int p_mod) { + int err = chmod(p_path.utf8().get_data(), p_mod); + if (!err) { + return OK; + } + + return FAILED; +} + FileAccess *FileAccessUnix::create_libc() { return memnew(FileAccessUnix); diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 6e5110431f..c5ab8821be 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -78,6 +78,8 @@ public: virtual uint64_t _get_modified_time(const String &p_file); + virtual Error _chmod(const String &p_path, int p_mod); + FileAccessUnix(); virtual ~FileAccessUnix(); }; diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp index 47360ff7fb..96e5627bef 100644 --- a/editor/animation_editor.cpp +++ b/editor/animation_editor.cpp @@ -2898,10 +2898,6 @@ void AnimationKeyEditor::_notification(int p_what) { zoomicon->set_custom_minimum_size(Size2(24 * EDSCALE, 0)); zoomicon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); - menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue", "EditorIcons"), "Add Normal Track", ADD_TRACK_MENU_ADD_VALUE_TRACK); - menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform", "EditorIcons"), "Add Transform Track", ADD_TRACK_MENU_ADD_TRANSFORM_TRACK); - menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall", "EditorIcons"), "Add Call Func Track", ADD_TRACK_MENU_ADD_CALL_TRACK); - menu_track->set_icon(get_icon("Tools", "EditorIcons")); menu_track->get_popup()->add_item(TTR("Scale Selection"), TRACK_MENU_SCALE); menu_track->get_popup()->add_item(TTR("Scale From Cursor"), TRACK_MENU_SCALE_PIVOT); @@ -3817,6 +3813,9 @@ AnimationKeyEditor::AnimationKeyEditor() { hb->add_child(menu_add_track); menu_add_track->get_popup()->connect("id_pressed", this, "_menu_add_track"); menu_add_track->set_tooltip(TTR("Add new tracks.")); + menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue", "EditorIcons"), "Add Normal Track", ADD_TRACK_MENU_ADD_VALUE_TRACK); + menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform", "EditorIcons"), "Add Transform Track", ADD_TRACK_MENU_ADD_TRANSFORM_TRACK); + menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall", "EditorIcons"), "Add Call Func Track", ADD_TRACK_MENU_ADD_CALL_TRACK); move_up_button = memnew(ToolButton); hb->add_child(move_up_button); @@ -3934,7 +3933,7 @@ AnimationKeyEditor::AnimationKeyEditor() { key_editor_tab = memnew(TabContainer); key_editor_tab->set_tab_align(TabContainer::ALIGN_LEFT); hb->add_child(key_editor_tab); - key_editor_tab->set_custom_minimum_size(Size2(200, 0)); + key_editor_tab->set_custom_minimum_size(Size2(200, 0) * EDSCALE); key_editor = memnew(PropertyEditor); key_editor->set_area_as_parent_rect(); @@ -4052,8 +4051,6 @@ AnimationKeyEditor::AnimationKeyEditor() { cleanup_dialog->connect("confirmed", this, "_menu_track", varray(TRACK_MENU_CLEAN_UP_CONFIRM)); - add_constant_override("separation", get_constant("separation", "VBoxContainer")); - track_editor->set_clip_contents(true); } diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 8c153d2745..5dd8b8a800 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1023,8 +1023,10 @@ void CodeTextEditor::_line_col_changed() { void CodeTextEditor::_text_changed() { - code_complete_timer->start(); - idle->start(); + if (text_editor->is_insert_text_operation()) { + code_complete_timer->start(); + idle->start(); + } } void CodeTextEditor::_code_complete_timer_timeout() { diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 9797a2e9f5..33734957e2 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -637,6 +637,7 @@ CreateDialog::CreateDialog() { search_box->set_h_size_flags(SIZE_EXPAND_FILL); search_hb->add_child(search_box); favorite = memnew(Button); + favorite->set_flat(true); favorite->set_toggle_mode(true); search_hb->add_child(favorite); favorite->connect("pressed", this, "_favorite_toggled"); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index d08a595fd2..ad9bc4a662 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -1246,9 +1246,13 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr } DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - da->copy(template_path, p_path); + Error err = da->copy(template_path, p_path, get_chmod_flags()); memdelete(da); + if (err != OK) { + return err; + } + String pck_path = p_path.get_basename() + ".pck"; return save_pack(p_preset, pck_path); @@ -1302,5 +1306,17 @@ void EditorExportPlatformPC::get_platform_features(List<String> *r_features) { } } +int EditorExportPlatformPC::get_chmod_flags() const { + + return chmod_flags; +} + +void EditorExportPlatformPC::set_chmod_flags(int p_flags) { + + chmod_flags = p_flags; +} + EditorExportPlatformPC::EditorExportPlatformPC() { + + chmod_flags = -1; } diff --git a/editor/editor_export.h b/editor/editor_export.h index b6ea4fd889..50379b9683 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -319,6 +319,7 @@ class EditorExportPlatformPC : public EditorExportPlatform { Set<String> extra_features; bool use64; + int chmod_flags; public: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features); @@ -347,6 +348,9 @@ public: void add_platform_feature(const String &p_feature); virtual void get_platform_features(List<String> *r_features); + int get_chmod_flags() const; + void set_chmod_flags(int p_flags); + EditorExportPlatformPC(); }; diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 288b923e87..8d13153128 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -1299,6 +1299,7 @@ EditorFileDialog::EditorFileDialog() { pathhb->add_child(refresh); favorite = memnew(ToolButton); + favorite->set_flat(true); favorite->set_toggle_mode(true); favorite->connect("toggled", this, "_favorite_toggled"); pathhb->add_child(favorite); diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index b0334685c3..6e5726a16d 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -137,6 +137,9 @@ void editor_register_fonts(Ref<Theme> p_theme) { p_theme->set_font("doc", "EditorFonts", df_doc); p_theme->set_font("doc_title", "EditorFonts", df_title); + MAKE_DEFAULT_FONT(df_rulers, int(EDITOR_DEF("canvas_item_editor/rulers", 8)) * EDSCALE); + p_theme->set_font("rulers", "EditorFonts", df_rulers); + Ref<DynamicFont> df_code; df_code.instance(); df_code->set_size(int(EditorSettings::get_singleton()->get("interface/source_font_size")) * EDSCALE); diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 035819f503..481f2aaecf 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -85,7 +85,11 @@ void EditorLog::clear() { void EditorLog::add_message(const String &p_msg, bool p_error) { + Ref<Font> doc_code_font = get_font("doc_source", "EditorFonts"); + log->push_font(doc_code_font); + log->add_newline(); + if (p_error) { log->push_color(get_color("error_color", "Editor")); Ref<Texture> icon = get_icon("Error", "EditorIcons"); @@ -100,6 +104,8 @@ void EditorLog::add_message(const String &p_msg, bool p_error) { if (p_error) log->pop(); + + log->pop(); // pop font; } /* diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index d7cce71b90..1a89d6ef6e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4061,6 +4061,13 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { ERR_FAIL_INDEX(p_idx, bottom_panel_items.size()); if (p_enable) { + // this is the debug panel wich uses tabs, so the top section should be smaller + if (ScriptEditor::get_singleton()->get_debugger() == bottom_panel_items[p_idx].control) { + Ref<StyleBoxFlat> style_panel_invisible_top = gui_base->get_stylebox("debugger_panel", "EditorStyles"); + bottom_panel->add_style_override("panel", style_panel_invisible_top); + } else { + bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); + } for (int i = 0; i < bottom_panel_items.size(); i++) { bottom_panel_items[i].button->set_pressed(i == p_idx); @@ -4069,11 +4076,14 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE); center_split->set_collapsed(false); } else { + bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); + for (int i = 0; i < bottom_panel_items.size(); i++) { bottom_panel_items[i].button->set_pressed(false); bottom_panel_items[i].control->set_visible(false); } + center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); center_split->set_collapsed(true); } diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp index 6b972262b9..247775fa1d 100644 --- a/editor/editor_profiler.cpp +++ b/editor/editor_profiler.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "editor_profiler.h" +#include "editor_scale.h" #include "editor_settings.h" #include "os/os.h" @@ -656,14 +657,14 @@ EditorProfiler::EditorProfiler() { hb->add_child(cursor_metric_edit); cursor_metric_edit->connect("value_changed", this, "_cursor_metric_changed"); - hb->add_constant_override("separation", 8); + hb->add_constant_override("separation", 8 * EDSCALE); h_split = memnew(HSplitContainer); add_child(h_split); h_split->set_v_size_flags(SIZE_EXPAND_FILL); variables = memnew(Tree); - variables->set_custom_minimum_size(Size2(300, 0)); + variables->set_custom_minimum_size(Size2(300, 0) * EDSCALE); variables->set_hide_folding(true); h_split->add_child(variables); variables->set_hide_root(true); @@ -674,10 +675,10 @@ EditorProfiler::EditorProfiler() { variables->set_column_min_width(0, 60); variables->set_column_title(1, "Time"); variables->set_column_expand(1, false); - variables->set_column_min_width(1, 60); + variables->set_column_min_width(1, 60 * EDSCALE); variables->set_column_title(2, "Calls"); variables->set_column_expand(2, false); - variables->set_column_min_width(2, 60); + variables->set_column_min_width(2, 60 * EDSCALE); variables->connect("item_edited", this, "_item_edited"); graph = memnew(TextureRect); @@ -691,8 +692,6 @@ EditorProfiler::EditorProfiler() { h_split->add_child(graph); graph->set_h_size_flags(SIZE_EXPAND_FILL); - add_constant_override("separation", 3); - int metric_size = CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size", 600)), 60, 1024); frame_metrics.resize(metric_size); last_metric = -1; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index d4ee6b2d17..eb72fdf64b 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -460,7 +460,7 @@ void EditorSettings::setup_network() { List<IP_Address> local_ip; IP::get_singleton()->get_local_addresses(&local_ip); - String lip; + String lip = "127.0.0.1"; String hint; String current = has("network/debug/remote_host") ? get("network/debug/remote_host") : ""; int port = has("network/debug/remote_port") ? (int)get("network/debug/remote_port") : 6007; @@ -469,8 +469,9 @@ void EditorSettings::setup_network() { String ip = E->get(); - if (lip == "") - lip = ip; + // link-local IPv6 addresses don't work, skipping them + if (ip.begins_with("fe80:0:0:0:")) // fe80::/64 + continue; if (ip == current) lip = current; //so it saves if (hint != "") @@ -581,6 +582,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { hints["interface/theme/contrast"] = PropertyInfo(Variant::REAL, "interface/theme/contrast", PROPERTY_HINT_RANGE, "0.01, 1, 0.01"); set("interface/theme/highlight_tabs", false); set("interface/theme/border_size", 1); + set("interface/theme/use_graph_node_headers", false); hints["interface/theme/border_size"] = PropertyInfo(Variant::INT, "interface/theme/border_size", PROPERTY_HINT_RANGE, "0,2,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); set("interface/theme/custom_theme", ""); hints["interface/theme/custom_theme"] = PropertyInfo(Variant::STRING, "interface/theme/custom_theme", PROPERTY_HINT_GLOBAL_FILE, "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 0cba024595..4aa1ccaa81 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -112,41 +112,49 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool dark_theme = tr #ifdef SVG_ENABLED Dictionary dark_icon_color_dictionary; - //convert color: FROM TO - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#4f4f4f"); // common icon color - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#000000"); // white - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#000000"); // script darker color - - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#cea4f1", "#bb6dff"); // animation - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc9c9c", "#ff5f5f"); // spatial - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5b7f3", "#6d90ff"); // 2d - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#708cea", "#0843ff"); // 2d dark - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#29d739"); // control - - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff3333"); // error - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00db50"); // success - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#ffad07"); // warning - - // rainbow - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff7070", "#ff2929"); // red - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffeb70", "#ffe337"); // yellow - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9dff70", "#74ff34"); // green - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70ffb9", "#2cff98"); // aqua - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70deff", "#22ccff"); // blue - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9f70ff", "#702aff"); // purple - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff70ac", "#ff2781"); // pink - - // audio gradient - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff4040"); // red - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1dc7a", "#d6cf4b"); // yellow - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00f010"); // green - - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#fea900"); // mesh (orange) - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#40a2ff", "#68b6ff"); // shape (blue) - - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84c2ff", "#5caeff"); // selection (blue) - - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea686c", "#e3383d"); // key xform (red) + if (!dark_theme) { + //convert color: FROM TO + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#4f4f4f"); // common icon color + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#000000"); // white + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#000000"); // script darker color + + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#cea4f1", "#bb6dff"); // animation + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc9c9c", "#ff5f5f"); // spatial + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5b7f3", "#6d90ff"); // 2d + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#708cea", "#0843ff"); // 2d dark + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#29d739"); // control + + // rainbow + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff7070", "#ff2929"); // red + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffeb70", "#ffe337"); // yellow + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9dff70", "#74ff34"); // green + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70ffb9", "#2cff98"); // aqua + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70deff", "#22ccff"); // blue + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9f70ff", "#702aff"); // purple + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff70ac", "#ff2781"); // pink + + // audio gradient + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff4040"); // red + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1dc7a", "#d6cf4b"); // yellow + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00f010"); // green + + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#fea900"); // mesh (orange) + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#40a2ff", "#68b6ff"); // shape (blue) + + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff3333"); // remove (red) + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00db50"); // add (green) + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84c2ff", "#5caeff"); // selection (blue) + + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea686c", "#e3383d"); // key xform (red) + } + + // these ones should be converted even if we are using a dark theme + const Color error_color = p_theme->get_color("error_color", "Editor"); + const Color success_color = p_theme->get_color("success_color", "Editor"); + const Color warning_color = p_theme->get_color("warning_color", "Editor"); + dark_icon_color_dictionary[Color::html("#ff5d5d")] = error_color; + dark_icon_color_dictionary[Color::html("#45ff8b")] = success_color; + dark_icon_color_dictionary[Color::html("#ffdd65")] = warning_color; List<String> exceptions; exceptions.push_back("EditorPivot"); @@ -157,17 +165,20 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool dark_theme = tr exceptions.push_back("ProceduralSky"); exceptions.push_back("EditorControlAnchor"); exceptions.push_back("DefaultProjectIcon"); + exceptions.push_back("GuiCloseCustomizable"); + exceptions.push_back("GuiGraphNodePort"); + exceptions.push_back("GuiResizer"); clock_t begin_time = clock(); - ImageLoaderSVG::set_convert_colors(dark_theme ? NULL : &dark_icon_color_dictionary); + ImageLoaderSVG::set_convert_colors(&dark_icon_color_dictionary); // generate icons if (!only_thumbs) for (int i = 0; i < editor_icons_count; i++) { List<String>::Element *is_exception = exceptions.find(editor_icons_names[i]); if (is_exception) exceptions.erase(is_exception); - Ref<ImageTexture> icon = editor_generate_icon(i, !dark_theme && !is_exception); + Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception); p_theme->set_icon(editor_icons_names[i], "EditorIcons", icon); } @@ -220,6 +231,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { bool highlight_tabs = EDITOR_DEF("interface/theme/highlight_tabs", false); int border_size = EDITOR_DEF("interface/theme/border_size", 1); + bool use_gn_headers = EDITOR_DEF("interface/theme/use_graph_node_headers", false); + Color script_bg_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0)); switch (preset) { @@ -322,6 +335,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const int border_width = CLAMP(border_size, 0, 3) * EDSCALE; const int default_margin_size = 4; + const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 3); // styleboxes // this is the most commonly used stylebox, variations should be made as duplicate of this @@ -333,11 +347,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Button and widgets Ref<StyleBoxFlat> style_widget = style_default->duplicate(); - // style_widget->set_bg_color(dark_color_1.linear_interpolate(base_color, 0.4)); style_widget->set_bg_color(dark_color_1); style_widget->set_default_margin(MARGIN_LEFT, 6 * EDSCALE); style_widget->set_default_margin(MARGIN_RIGHT, 6 * EDSCALE); - // style_widget->set_border_color_all(contrast_color_1); style_widget->set_border_color_all(dark_color_2); Ref<StyleBoxFlat> style_widget_disabled = style_widget->duplicate(); @@ -368,18 +380,19 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size); // Tabs + const int tab_default_margin_side = 10 * EDSCALE; Ref<StyleBoxFlat> style_tab_selected = style_default->duplicate(); style_tab_selected->set_border_width_all(border_width); style_tab_selected->set_border_width(MARGIN_BOTTOM, 0); style_tab_selected->set_border_color_all(dark_color_3); style_tab_selected->set_expand_margin_size(MARGIN_BOTTOM, border_width); - style_tab_selected->set_default_margin(MARGIN_LEFT, 10 * EDSCALE); - style_tab_selected->set_default_margin(MARGIN_RIGHT, 10 * EDSCALE); + style_tab_selected->set_default_margin(MARGIN_LEFT, tab_default_margin_side); + style_tab_selected->set_default_margin(MARGIN_RIGHT, tab_default_margin_side); style_tab_selected->set_bg_color(tab_color); - Ref<StyleBoxEmpty> style_tab_unselected = style_empty->duplicate(); - style_tab_unselected->set_default_margin(MARGIN_LEFT, 10 * EDSCALE); - style_tab_unselected->set_default_margin(MARGIN_RIGHT, 10 * EDSCALE); + Ref<StyleBoxFlat> style_tab_unselected = style_tab_selected->duplicate(); + style_tab_unselected->set_bg_color(Color(0.0, 0.0, 0.0, 0.0)); + style_tab_unselected->set_border_color_all(Color(0.0, 0.0, 0.0, 0.0)); // Editor background theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); @@ -603,13 +616,18 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Ref<StyleBoxFlat> style_content_panel = style_default->duplicate(); style_content_panel->set_border_color_all(dark_color_3); style_content_panel->set_border_width_all(border_width); + // compensate the border + style_content_panel->set_default_margin(MARGIN_TOP, margin_size_extra * EDSCALE); + style_content_panel->set_default_margin(MARGIN_RIGHT, margin_size_extra * EDSCALE); + style_content_panel->set_default_margin(MARGIN_BOTTOM, margin_size_extra * EDSCALE); + style_content_panel->set_default_margin(MARGIN_LEFT, margin_size_extra * EDSCALE); // this is the stylebox used in 3d and 2d viewports (no borders) Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate(); - style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width); - style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size); - style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width); - style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width); + style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width * 2); + style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE); + style_content_panel_vp->set_default_margin(MARGIN_RIGHT, border_width * 2); + style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width * 2); theme->set_stylebox("panel", "TabContainer", style_content_panel); theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp); @@ -617,15 +635,29 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, border_width)); theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, border_width, 0, true)); - // Debugger - Ref<StyleBoxFlat> style_panel_debugger = style_default->duplicate(); - theme->set_stylebox("DebuggerPanel", "EditorStyles", style_panel_debugger); + // HACK Debuger panel + Ref<StyleBoxFlat> style_panel_debugger = style_content_panel->duplicate(); + const int v_offset = theme->get_font("font", "Tabs")->get_height() + style_tab_selected->get_minimum_size().height + default_margin_size * EDSCALE; + style_panel_debugger->set_expand_margin_size(MARGIN_TOP, -v_offset); + theme->set_stylebox("debugger_panel", "EditorStyles", style_panel_debugger); + // Debugger + Ref<StyleBoxFlat> style_debugger_contents = style_content_panel->duplicate(); + style_debugger_contents->set_default_margin(MARGIN_LEFT, 0); + style_debugger_contents->set_default_margin(MARGIN_BOTTOM, 0); + style_debugger_contents->set_default_margin(MARGIN_RIGHT, 0); + style_debugger_contents->set_border_width_all(0); + style_debugger_contents->set_expand_margin_size(MARGIN_TOP, -v_offset); + theme->set_constant("extra_margin", "DebuggerPanel", default_margin_size * EDSCALE + border_width); + theme->set_stylebox("DebuggerPanel", "EditorStyles", style_debugger_contents); Ref<StyleBoxFlat> style_tab_fg_debugger = style_tab_selected->duplicate(); - style_tab_fg_debugger->set_border_width_all(0); - + style_tab_fg_debugger->set_expand_margin_size(MARGIN_LEFT, default_margin_size * EDSCALE + border_width); + style_tab_fg_debugger->set_default_margin(MARGIN_LEFT, tab_default_margin_side - default_margin_size * EDSCALE); theme->set_stylebox("DebuggerTabFG", "EditorStyles", style_tab_fg_debugger); - theme->set_stylebox("DebuggerTabBG", "EditorStyles", style_tab_unselected); + Ref<StyleBoxFlat> style_tab_bg_debugger = style_tab_unselected->duplicate(); + style_tab_bg_debugger->set_expand_margin_size(MARGIN_LEFT, default_margin_size * EDSCALE + border_width); + style_tab_bg_debugger->set_default_margin(MARGIN_LEFT, tab_default_margin_side - default_margin_size * EDSCALE); + theme->set_stylebox("DebuggerTabBG", "EditorStyles", style_tab_bg_debugger); // LineEdit theme->set_stylebox("normal", "LineEdit", style_widget); @@ -651,6 +683,17 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE); theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE); + // Containers + theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE); + theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE); + theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE); + theme->set_constant("margin_left", "MarginContainer", 0); + theme->set_constant("margin_top", "MarginContainer", 0); + theme->set_constant("margin_right", "MarginContainer", 0); + theme->set_constant("margin_bottom", "MarginContainer", 0); + theme->set_constant("hseparation", "GridContainer", default_margin_size * EDSCALE); + theme->set_constant("vseparation", "GridContainer", default_margin_size * EDSCALE); + // WindowDialog Ref<StyleBoxFlat> style_window = style_popup->duplicate(); style_window->set_border_color_all(tab_color); @@ -762,28 +805,40 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // GraphNode - Ref<StyleBoxFlat> graphsb = make_flat_stylebox(Color(0, 0, 0, 0.3), 16, 24, 16, 5); + const int gn_margin_side = 28; + Ref<StyleBoxFlat> graphsb = make_flat_stylebox(Color(0, 0, 0, 0.3), gn_margin_side, 24, gn_margin_side, 5); graphsb->set_border_width_all(border_width); - graphsb->set_border_color_all(Color(1, 1, 1, 0.6)); - graphsb->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width); - Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(Color(0, 0, 0, 0.4), 16, 24, 16, 5); + graphsb->set_border_color_all(Color(1, 1, 1, 0.9)); + Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(Color(0, 0, 0, 0.4), gn_margin_side, 24, gn_margin_side, 5); graphsbselected->set_border_width_all(border_width); graphsbselected->set_border_color_all(Color(accent_color.r, accent_color.g, accent_color.b, 0.9)); graphsbselected->set_shadow_size(8 * EDSCALE); graphsbselected->set_shadow_color(shadow_color); - graphsbselected->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width); - Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(Color(0, 0, 0, 0.3), 16, 24, 16, 5); + Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(Color(0, 0, 0, 0.3), gn_margin_side, 24, gn_margin_side, 5); graphsbcomment->set_border_width_all(border_width); - graphsbcomment->set_border_color_all(Color(1, 1, 1, 0.6)); - graphsbcomment->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width); - Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(Color(0, 0, 0, 0.4), 16, 24, 16, 5); + graphsbcomment->set_border_color_all(Color(1, 1, 1, 0.9)); + Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(Color(0, 0, 0, 0.4), gn_margin_side, 24, gn_margin_side, 5); graphsbcommentselected->set_border_width_all(border_width); graphsbcommentselected->set_border_color_all(Color(1, 1, 1, 0.9)); - graphsbcommentselected->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width); + + if (use_gn_headers) { + graphsb->set_border_width(MARGIN_TOP, 24 * EDSCALE); + graphsbselected->set_border_width(MARGIN_TOP, 24 * EDSCALE); + graphsbcomment->set_border_width(MARGIN_TOP, 24 * EDSCALE); + graphsbcommentselected->set_border_width(MARGIN_TOP, 24 * EDSCALE); + } + theme->set_stylebox("frame", "GraphNode", graphsb); theme->set_stylebox("selectedframe", "GraphNode", graphsbselected); theme->set_stylebox("comment", "GraphNode", graphsbcomment); theme->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected); + theme->set_constant("port_offset", "GraphNode", 14 * EDSCALE); + theme->set_constant("title_h_offset", "GraphNode", -16 * EDSCALE); + theme->set_constant("close_h_offset", "GraphNode", 20 * EDSCALE); + theme->set_constant("close_offset", "GraphNode", 20 * EDSCALE); + theme->set_icon("close", "GraphNode", theme->get_icon("GuiCloseCustomizable", "EditorIcons")); + theme->set_icon("resizer", "GraphNode", theme->get_icon("GuiResizer", "EditorIcons")); + theme->set_icon("port", "GraphNode", theme->get_icon("GuiGraphNodePort", "EditorIcons")); // FileDialog theme->set_color("files_disabled", "FileDialog", font_color_disabled); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index f0ace864e4..526a8fe810 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1812,8 +1812,6 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { display_mode = DISPLAY_THUMBNAILS; path = "res://"; - - add_constant_override("separation", 4); } FileSystemDock::~FileSystemDock() { diff --git a/editor/icons/icon_a_r_v_r_camera.svg b/editor/icons/icon_a_r_v_r_camera.svg new file mode 100644 index 0000000000..a02b4d983c --- /dev/null +++ b/editor/icons/icon_a_r_v_r_camera.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m2 1c-0.55401 0-1 0.446-1 1v7c0 0.554 0.44599 1 1 1h4l1-2c0.24699-0.494 0.44772-1 1-1s0.75301 0.506 1 1l1 2h4c0.55401 0 1-0.446 1-1v-7c0-0.554-0.44599-1-1-1h-12zm2 3a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm8 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm-8 7v4h2c0.502 4e-4 0.9265-0.37144 0.99219-0.86914 0.0059-0.047 0.0085325-0.094025 0.0078125-0.14062v-2.9902h-1v3h-1v-3h-1zm5 0v4h1v-1h1v1h1v-1c-7.73e-4 -0.1811-0.05073-0.35867-0.14453-0.51367 0.08369-0.1462 0.14453-0.30573 0.14453-0.48633v-1c0-0.5523-0.4485-1.0293-1-1h-2zm1 1h1v1h-1v-1z" fill="#fc9c9c"/> +</svg> diff --git a/editor/icons/icon_area.svg b/editor/icons/icon_area.svg index 22348d50c1..ac673d10fc 100644 --- a/editor/icons/icon_area.svg +++ b/editor/icons/icon_area.svg @@ -1,5 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#fc9c9c" fill-opacity=".99608"/> +<path transform="translate(0 1036.4)" d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#fc9c9c"/> </g> </svg> diff --git a/editor/icons/icon_error.svg b/editor/icons/icon_error.svg index 771a418cfa..846bd88cb1 100644 --- a/editor/icons/icon_error.svg +++ b/editor/icons/icon_error.svg @@ -1,5 +1,5 @@ <svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1044.4)"> -<rect x="2.2204e-16" y="1044.4" width="8" height="8" ry="4" fill="#ff8484"/> +<rect x="2.2204e-16" y="1044.4" width="8" height="8" ry="4" fill="#ff5d5d"/> </g> </svg> diff --git a/editor/icons/icon_error_sign.svg b/editor/icons/icon_error_sign.svg index a2d714c31a..bde0494a93 100644 --- a/editor/icons/icon_error_sign.svg +++ b/editor/icons/icon_error_sign.svg @@ -1,7 +1,6 @@ <svg width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1020.4)"> -<path d="m10 1048.4h12l6-6v-12l-6-6h-12l-6 6v12z" fill="#ff8484" fill-rule="evenodd"/> -<rect x="14" y="1028.4" width="4" height="9" fill="#fff"/> -<rect x="14" y="1040.4" width="4" height="4" fill="#fff"/> +<path d="m10 1048.4h12l6-6v-12l-6-6h-12l-6 6v12z" fill="#ff5d5d" fill-rule="evenodd"/> +<path transform="translate(0 1020.4)" d="m14 8l1 10h2l1-10h-4zm2 12a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#fff"/> </g> </svg> diff --git a/editor/icons/icon_file_broken.svg b/editor/icons/icon_file_broken.svg index f352eeb001..7b05ab625e 100644 --- a/editor/icons/icon_file_broken.svg +++ b/editor/icons/icon_file_broken.svg @@ -1,7 +1,7 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> <g transform="translate(0 -1.6949e-5)"> -<path transform="translate(0 1036.4)" d="m2 1v8.5859l1.293-1.293a1.0001 1.0001 0 0 1 0.69141 -0.29102 1.0001 1.0001 0 0 1 0.72266 0.29102l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 1.4141 0l2.293 2.293 1-1v-3.5859h-5v-5h-7zm8 0v4h4l-4-4zm-6 9.4141l-2 2v2.5859h12v-2.5859l-0.29297 0.29297a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293-2.293 2.293a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293z" fill="#ff8484"/> +<path transform="translate(0 1036.4)" d="m2 1v8.5859l1.293-1.293a1.0001 1.0001 0 0 1 0.69141 -0.29102 1.0001 1.0001 0 0 1 0.72266 0.29102l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 1.4141 0l2.293 2.293 1-1v-3.5859h-5v-5h-7zm8 0v4h4l-4-4zm-6 9.4141l-2 2v2.5859h12v-2.5859l-0.29297 0.29297a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293-2.293 2.293a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293z" fill="#ff5d5d"/> </g> </g> </svg> diff --git a/editor/icons/icon_file_broken_big_thumb.svg b/editor/icons/icon_file_broken_big_thumb.svg index 167bb1bb5f..5e8fa607c1 100644 --- a/editor/icons/icon_file_broken_big_thumb.svg +++ b/editor/icons/icon_file_broken_big_thumb.svg @@ -1,7 +1,7 @@ <svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -988.36)"> <g transform="translate(0 -1.6949e-5)"> -<path transform="translate(0 988.36)" d="m14 5c-2.1987 0-4 1.8013-4 4v26.172a1.0001 1.0001 0 0 0 1.707 0.70703l3.293-3.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l8-8a1.0001 1.0001 0 0 0 0.29297 -0.70703v-11.172a1.0001 1.0001 0 0 0 -0.29297 -0.70703l-16-16a1.0001 1.0001 0 0 0 -0.70703 -0.29297h-23zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v9.7578l-7 7-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-2.293 2.293v-23.758c0-1.1253 0.87473-2 2-2zm0.98438 28.83a1.0001 1.0001 0 0 0 -0.69141 0.29297l-4 4a1.0001 1.0001 0 0 0 -0.29297 0.70703v14.17c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-16.17a1.0001 1.0001 0 0 0 -1.707 -0.70703l-7.293 7.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -0.72266 -0.29297zm0.015625 2.4141l9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l6.293-6.293v13.756c0 1.1253-0.87473 2-2 2h-36c-1.1253 0-2-0.87473-2-2v-13.756l3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> +<path transform="translate(0 988.36)" d="m14 5c-2.1987 0-4 1.8013-4 4v26.172a1.0001 1.0001 0 0 0 1.707 0.70703l3.293-3.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l8-8a1.0001 1.0001 0 0 0 0.29297 -0.70703v-11.172a1.0001 1.0001 0 0 0 -0.29297 -0.70703l-16-16a1.0001 1.0001 0 0 0 -0.70703 -0.29297h-23zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v9.7578l-7 7-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-2.293 2.293v-23.758c0-1.1253 0.87473-2 2-2zm0.98438 28.83a1.0001 1.0001 0 0 0 -0.69141 0.29297l-4 4a1.0001 1.0001 0 0 0 -0.29297 0.70703v14.17c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-16.17a1.0001 1.0001 0 0 0 -1.707 -0.70703l-7.293 7.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -0.72266 -0.29297zm0.015625 2.4141l9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l6.293-6.293v13.756c0 1.1253-0.87473 2-2 2h-36c-1.1253 0-2-0.87473-2-2v-13.756l3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> </g> </g> </svg> diff --git a/editor/icons/icon_file_dead.svg b/editor/icons/icon_file_dead.svg index e0aee6fd90..ec13e7087f 100644 --- a/editor/icons/icon_file_dead.svg +++ b/editor/icons/icon_file_dead.svg @@ -1,7 +1,7 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> <g transform="translate(0 -1.6949e-5)"> -<path transform="translate(0 1036.4)" d="m2 1v14h12v-9h-5v-5zm8 0v4h4zm-6.0078 6c0.1353-0.0020779 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091882 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm6 0c0.1353-0.00208 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091883 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm-6.4922 4h9c0.277 0 0.5 0.223 0.5 0.5s-0.223 0.5-0.5 0.5h-4.5c0 1.1046-0.89543 2-2 2s-2-0.8954-2-2h-0.5c-0.277 0-0.5-0.223-0.5-0.5s0.223-0.5 0.5-0.5zm1.5 1c-1.9e-5 0.5523 0.44771 1 1 1s1-0.4477 1-1z" fill="#ff8484"/> +<path transform="translate(0 1036.4)" d="m2 1v14h12v-9h-5v-5zm8 0v4h4zm-6.0078 6c0.1353-0.0020779 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091882 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm6 0c0.1353-0.00208 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091883 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm-6.4922 4h9c0.277 0 0.5 0.223 0.5 0.5s-0.223 0.5-0.5 0.5h-4.5c0 1.1046-0.89543 2-2 2s-2-0.8954-2-2h-0.5c-0.277 0-0.5-0.223-0.5-0.5s0.223-0.5 0.5-0.5zm1.5 1c-1.9e-5 0.5523 0.44771 1 1 1s1-0.4477 1-1z" fill="#ff5d5d"/> </g> </g> </svg> diff --git a/editor/icons/icon_file_dead_big_thumb.svg b/editor/icons/icon_file_dead_big_thumb.svg index c8aab912f1..2ac8d1e9df 100644 --- a/editor/icons/icon_file_dead_big_thumb.svg +++ b/editor/icons/icon_file_dead_big_thumb.svg @@ -1,7 +1,7 @@ <svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -988.36)"> <g transform="translate(0 -1.6949e-5)"> -<path d="m14 993.36c-2.1987 0-4 1.8013-4 4v46c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-33h-0.0078c2e-3 -0.2483-0.0793-0.501-0.28516-0.707l-16-16c-0.18788-0.18693-0.44247-0.28939-0.70704-0.28907v-4e-3zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v32c0 1.1253-0.87472 2-2 2h-36c-1.1253 0-2-0.8747-2-2v-46c0-1.1253 0.87472-2 2-2zm2.9512 22.002a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm23 0a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm-18.951 13.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h3v3c0 2.7527 2.2473 5 5 5s5-2.2473 5-5v-3h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm5 2h6v3c0 1.6793-1.3207 3-3 3s-3-1.3207-3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> +<path d="m14 993.36c-2.1987 0-4 1.8013-4 4v46c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-33h-0.0078c2e-3 -0.2483-0.0793-0.501-0.28516-0.707l-16-16c-0.18788-0.18693-0.44247-0.28939-0.70704-0.28907v-4e-3zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v32c0 1.1253-0.87472 2-2 2h-36c-1.1253 0-2-0.8747-2-2v-46c0-1.1253 0.87472-2 2-2zm2.9512 22.002a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm23 0a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm-18.951 13.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h3v3c0 2.7527 2.2473 5 5 5s5-2.2473 5-5v-3h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm5 2h6v3c0 1.6793-1.3207 3-3 3s-3-1.3207-3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> </g> </g> </svg> diff --git a/editor/icons/icon_file_dead_medium_thumb.svg b/editor/icons/icon_file_dead_medium_thumb.svg index 60a456a600..010019ae03 100644 --- a/editor/icons/icon_file_dead_medium_thumb.svg +++ b/editor/icons/icon_file_dead_medium_thumb.svg @@ -1,7 +1,7 @@ <svg width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1020.4)"> <g transform="translate(0 -1.6949e-5)"> -<path transform="translate(0 1020.4)" d="m5 1c-1.6447 0-3 1.3553-3 3v24c0 1.6447 1.3553 3 3 3h22c1.6447 0 3-1.3553 3-3v-16.809c-5.1e-5 -0.2652-0.10543-0.51952-0.29297-0.70703l-9.1816-9.1895c-0.18719-0.18825-0.44155-0.29435-0.70703-0.29492h-14.818zm0 2h14v6c0 1.6447 1.3553 3 3 3h6v16c0 0.5713-0.42868 1-1 1h-22c-0.57133 0-1-0.4287-1-1v-24c0-0.5713 0.42867-1 1-1zm1.9863 11.002a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm14 0a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm-13.986 7.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h1a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2 -3.4648h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-18zm3 2h4a2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> +<path transform="translate(0 1020.4)" d="m5 1c-1.6447 0-3 1.3553-3 3v24c0 1.6447 1.3553 3 3 3h22c1.6447 0 3-1.3553 3-3v-16.809c-5.1e-5 -0.2652-0.10543-0.51952-0.29297-0.70703l-9.1816-9.1895c-0.18719-0.18825-0.44155-0.29435-0.70703-0.29492h-14.818zm0 2h14v6c0 1.6447 1.3553 3 3 3h6v16c0 0.5713-0.42868 1-1 1h-22c-0.57133 0-1-0.4287-1-1v-24c0-0.5713 0.42867-1 1-1zm1.9863 11.002a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm14 0a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm-13.986 7.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h1a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2 -3.4648h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-18zm3 2h4a2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> </g> </g> </svg> diff --git a/editor/icons/icon_gui_close_customizable.svg b/editor/icons/icon_gui_close_customizable.svg new file mode 100644 index 0000000000..ac023b7030 --- /dev/null +++ b/editor/icons/icon_gui_close_customizable.svg @@ -0,0 +1,5 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m3.7578 2.3438l-1.4141 1.4141 4.2422 4.2422-4.2422 4.2422 1.4141 1.4141 4.2422-4.2422 4.2422 4.2422 1.4141-1.4141-4.2422-4.2422 4.2422-4.2422-1.4141-1.4141-4.2422 4.2422-4.2422-4.2422z" fill="#fff" fill-opacity=".89804"/> +</g> +</svg> diff --git a/editor/icons/icon_gui_graph_node_port.svg b/editor/icons/icon_gui_graph_node_port.svg new file mode 100644 index 0000000000..1120218844 --- /dev/null +++ b/editor/icons/icon_gui_graph_node_port.svg @@ -0,0 +1,5 @@ +<svg width="10" height="10" version="1.1" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(0 -1042.4)"> +<circle cx="5" cy="1047.4" r="5" fill="#fff" fill-rule="evenodd"/> +</g> +</svg> diff --git a/editor/icons/icon_gui_resizer.svg b/editor/icons/icon_gui_resizer.svg new file mode 100644 index 0000000000..d9af047213 --- /dev/null +++ b/editor/icons/icon_gui_resizer.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m11 3c-0.55228 0-1 0.44772-1 1v6h-6c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1h7c0.55226-5.5e-5 0.99994-0.44774 1-1v-7c0-0.55228-0.44772-1-1-1z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fff" fill-opacity=".58824" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/> +</svg> diff --git a/editor/icons/icon_import_check.svg b/editor/icons/icon_import_check.svg index e3ad9ec37e..c9f51bb6e0 100644 --- a/editor/icons/icon_import_check.svg +++ b/editor/icons/icon_import_check.svg @@ -1,5 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> -<path d="m2 1044.4 4 4 8-8" fill="none" stroke="#84ffb1" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/> +<path d="m2 1044.4 4 4 8-8" fill="none" stroke="#45ff8b" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/> </g> </svg> diff --git a/editor/icons/icon_import_fail.svg b/editor/icons/icon_import_fail.svg index e088126043..f4aa212c20 100644 --- a/editor/icons/icon_import_fail.svg +++ b/editor/icons/icon_import_fail.svg @@ -1,5 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> -<path transform="translate(0 1036.4)" d="m2.9902 1.9902a1.0001 1.0001 0 0 0 -0.69727 1.7168l4.293 4.293-4.293 4.293a1.0001 1.0001 0 1 0 1.4141 1.4141l4.293-4.293 4.293 4.293a1.0001 1.0001 0 1 0 1.4141 -1.4141l-4.293-4.293 4.293-4.293a1.0001 1.0001 0 0 0 -0.72656 -1.7148 1.0001 1.0001 0 0 0 -0.6875 0.30078l-4.293 4.293-4.293-4.293a1.0001 1.0001 0 0 0 -0.7168 -0.30273z" color="#000000" color-rendering="auto" fill="#ff8484" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/> +<path transform="translate(0 1036.4)" d="m2.9902 1.9902a1.0001 1.0001 0 0 0 -0.69727 1.7168l4.293 4.293-4.293 4.293a1.0001 1.0001 0 1 0 1.4141 1.4141l4.293-4.293 4.293 4.293a1.0001 1.0001 0 1 0 1.4141 -1.4141l-4.293-4.293 4.293-4.293a1.0001 1.0001 0 0 0 -0.72656 -1.7148 1.0001 1.0001 0 0 0 -0.6875 0.30078l-4.293 4.293-4.293-4.293a1.0001 1.0001 0 0 0 -0.7168 -0.30273z" color="#000000" color-rendering="auto" fill="#ff5d5d" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/> </g> </svg> diff --git a/editor/icons/icon_key_invalid.svg b/editor/icons/icon_key_invalid.svg index f1df51f7c3..742859bac5 100644 --- a/editor/icons/icon_key_invalid.svg +++ b/editor/icons/icon_key_invalid.svg @@ -1,5 +1,5 @@ <svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1044.4)"> -<path d="m0.46447 1046.2 2.1213 2.1213-2.1213 2.1213 1.4142 1.4142l2.1213-2.1213 2.1213 2.1213 1.4142-1.4142-2.1213-2.1213 2.1213-2.1213-1.4142-1.4142-2.1213 2.1213-2.1213-2.1213-1.4142 1.4142z" fill="#ff8484"/> +<path d="m0.46447 1046.2 2.1213 2.1213-2.1213 2.1213 1.4142 1.4142l2.1213-2.1213 2.1213 2.1213 1.4142-1.4142-2.1213-2.1213 2.1213-2.1213-1.4142-1.4142-2.1213 2.1213-2.1213-2.1213-1.4142 1.4142z" fill="#ff5d5d"/> </g> </svg> diff --git a/editor/icons/icon_key_move_disabled.svg b/editor/icons/icon_key_move_disabled.svg new file mode 100644 index 0000000000..05c158dc3c --- /dev/null +++ b/editor/icons/icon_key_move_disabled.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m7.984 1.002c-0.259 4e-3 -0.507 0.108-0.691 0.291l-2 2 1.414 1.414 1.293-1.293 1.293 1.293 1.414-1.414-2-2c-0.191-0.191-0.452-0.296-0.722-0.291h-1e-3zm-4.691 4.291l-2 2c-0.39 0.391-0.39 1.024 0 1.414l2 2 1.414-1.414-1.293-1.293 1.293-1.293-1.414-1.414zm9.414 0l-1.414 1.414 1.293 1.293-1.293 1.293 1.414 1.414 2-2c0.39-0.39 0.39-1.023 0-1.414l-2-2zm-6 6l-1.414 1.414 2 2c0.391 0.391 1.024 0.391 1.414 0l2-2-1.414-1.414-1.293 1.293-1.293-1.293z" fill="#e0e0e0" fill-opacity=".5" fill-rule="evenodd"/> +<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84c2ff" fill-opacity=".5"/> +</svg> diff --git a/editor/icons/icon_key_move_enabled.svg b/editor/icons/icon_key_move_enabled.svg new file mode 100644 index 0000000000..2d455f2d81 --- /dev/null +++ b/editor/icons/icon_key_move_enabled.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m7.984 1.002c-0.259 4e-3 -0.507 0.108-0.691 0.291l-2 2 1.414 1.414 1.293-1.293 1.293 1.293 1.414-1.414-2-2c-0.191-0.191-0.452-0.296-0.722-0.291h-1e-3zm-4.691 4.291l-2 2c-0.39 0.391-0.39 1.024 0 1.414l2 2 1.414-1.414-1.293-1.293 1.293-1.293-1.414-1.414zm9.414 0l-1.414 1.414 1.293 1.293-1.293 1.293 1.414 1.414 2-2c0.39-0.39 0.39-1.023 0-1.414l-2-2zm-6 6l-1.414 1.414 2 2c0.391 0.391 1.024 0.391 1.414 0l2-2-1.414-1.414-1.293 1.293-1.293-1.293z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/> +<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84C2FF"/> +</svg> diff --git a/editor/icons/icon_key_rotate_disabled.svg b/editor/icons/icon_key_rotate_disabled.svg new file mode 100644 index 0000000000..6394bfd82d --- /dev/null +++ b/editor/icons/icon_key_rotate_disabled.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m8.088 1.001c-0.102-1e-3 -0.203 0-0.305 2e-3 -0.233 8e-3 -0.466 0.027-0.697 0.057-2.973 0.392-5.366 2.633-5.951 5.574-0.46 2.319 0.281 4.712 1.97 6.365h-1.105v2h4c0.308 1e-3 0.599-0.141 0.788-0.384 0.19-0.243 0.257-0.559 0.183-0.858l-1-4-1.942 0.487 0.281 1.121c-0.84-0.92-1.308-2.12-1.31-3.366 0-2.761 2.239-5 5-5 1.326 0 2.598 0.527 3.536 1.465 0.937 0.938 1.464 2.209 1.464 3.535-1e-3 1.326-0.529 2.597-1.467 3.534l1.416 1.416c2.12-2.121 2.654-5.356 1.328-8.045-1.165-2.362-3.556-3.869-6.189-3.903z" fill="#e0e0e0" fill-opacity=".5"/> +<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84c2ff" fill-opacity=".5"/> +</svg> diff --git a/editor/icons/icon_key_rotate_enabled.svg b/editor/icons/icon_key_rotate_enabled.svg new file mode 100644 index 0000000000..1dcb12c8ab --- /dev/null +++ b/editor/icons/icon_key_rotate_enabled.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m8.088 1.001c-0.102-1e-3 -0.203 0-0.305 2e-3 -0.233 8e-3 -0.466 0.027-0.697 0.057-2.973 0.392-5.366 2.633-5.951 5.574-0.46 2.319 0.281 4.712 1.97 6.365h-1.105v2h4c0.308 1e-3 0.599-0.141 0.788-0.384 0.19-0.243 0.257-0.559 0.183-0.858l-1-4-1.942 0.487 0.281 1.121c-0.84-0.92-1.308-2.12-1.31-3.366 0-2.761 2.239-5 5-5 1.326 0 2.598 0.527 3.536 1.465 0.937 0.938 1.464 2.209 1.464 3.535-1e-3 1.326-0.529 2.597-1.467 3.534l1.416 1.416c2.12-2.121 2.654-5.356 1.328-8.045-1.165-2.362-3.556-3.869-6.189-3.903z" fill="#e0e0e0" fill-opacity=".99608"/> +<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84C2FF"/> +</svg> diff --git a/editor/icons/icon_key_scale_disabled.svg b/editor/icons/icon_key_scale_disabled.svg new file mode 100644 index 0000000000..9601e4925b --- /dev/null +++ b/editor/icons/icon_key_scale_disabled.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m9 1c-0.552 0-1 0.448-1 1s0.448 1 1 1h2.586l-1.293 1.293 1.414 1.414 1.293-1.293v2.586c0 0.552 0.448 1 1 1s1-0.448 1-1v-5c0-0.552-0.448-1-1-1h-5zm-7 7c-0.552 0-1 0.448-1 1v5c0 0.552 0.448 1 1 1h5c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2.586l1.293-1.293-1.414-1.414-1.293 1.293v-2.586c0-0.552-0.448-1-1-1z" fill="#e0e0e0" fill-opacity=".5" fill-rule="evenodd"/> +<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84c2ff" fill-opacity=".5"/> +</svg> diff --git a/editor/icons/icon_key_scale_enabled.svg b/editor/icons/icon_key_scale_enabled.svg new file mode 100644 index 0000000000..f00f3db35f --- /dev/null +++ b/editor/icons/icon_key_scale_enabled.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" style="isolation:isolate" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<path d="m9 1c-0.552 0-1 0.448-1 1s0.448 1 1 1h2.586l-1.293 1.293 1.414 1.414 1.293-1.293v2.586c0 0.552 0.448 1 1 1s1-0.448 1-1v-5c0-0.552-0.448-1-1-1h-5zm-7 7c-0.552 0-1 0.448-1 1v5c0 0.552 0.448 1 1 1h5c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2.586l1.293-1.293-1.414-1.414-1.293 1.293v-2.586c0-0.552-0.448-1-1-1z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/> +<path d="m5.168 7.595l2.427-2.427c0.224-0.224 0.586-0.224 0.81 0l2.427 2.427c0.224 0.224 0.224 0.586 0 0.81l-2.427 2.427c-0.224 0.224-0.586 0.224-0.81 0l-2.427-2.427c-0.224-0.224-0.224-0.586 0-0.81z" fill="#84C2FF"/> +</svg> diff --git a/editor/icons/icon_node_warning.svg b/editor/icons/icon_node_warning.svg index 5c03bad343..66663f7d62 100644 --- a/editor/icons/icon_node_warning.svg +++ b/editor/icons/icon_node_warning.svg @@ -1,7 +1,7 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> <g transform="translate(0 -1.6949e-5)"> -<path transform="translate(0 1036.4)" d="m8.0293 2.002a1.0001 1.0001 0 0 0 -0.88672 0.48438l-6 10a1.0001 1.0001 0 0 0 0.85742 1.5137h12a1.0001 1.0001 0 0 0 0.85742 -1.5137l-6-10a1.0001 1.0001 0 0 0 -0.82812 -0.48438zm-1.0293 2.998h2v5h-2v-5zm0 6h2v2h-2v-2z" color="#000000" color-rendering="auto" fill="#ffd684" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/> +<path transform="translate(0 1036.4)" d="m8.0293 2.002a1.0001 1.0001 0 0 0 -0.88672 0.48438l-6 10a1.0001 1.0001 0 0 0 0.85742 1.5137h12a1.0001 1.0001 0 0 0 0.85742 -1.5137l-6-10a1.0001 1.0001 0 0 0 -0.82812 -0.48438zm-1.0293 2.998h2v5h-2v-5zm0 6h2v2h-2v-2z" color="#000000" color-rendering="auto" fill="#ffdd65" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/> </g> </g> </svg> diff --git a/editor/icons/icon_sample_library.svg b/editor/icons/icon_sample_library.svg index b5ec2bb43c..403ea5ff42 100644 --- a/editor/icons/icon_sample_library.svg +++ b/editor/icons/icon_sample_library.svg @@ -1,6 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)" fill="#ff8484"> -<path transform="translate(0 1036.4)" d="m9 8v1 5 1h5c0.55228 0 1-0.44772 1-1v-5c0-0.55228-0.44772-1-1-1v4l-1-1-1 1v-4z"/> -<path d="m7.0215 1037.4a1.0001 1.0001 0 0 0 -1 0.875l-0.58984 4.7226-0.52344-1.0468a1.0001 1.0001 0 0 0 -0.89453 -0.5528h-2a1.0001 1.0001 0 1 0 0 2h1.3828l1.7227 3.4473a1.0001 1.0001 0 0 0 1.8867 -0.3223l0.58984-4.7226 0.52344 1.0449a1.0001 1.0001 0 0 0 0.89453 0.5527h3a1.0001 1.0001 0 1 0 0 -2h-2.3809l-1.7246-3.4472a1.0001 1.0001 0 0 0 -0.88672 -0.5508z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m7.0215 1.002a1.0001 1.0001 0 0 0 -1 0.875l-0.58984 4.7227-0.52344-1.0469a1.0001 1.0001 0 0 0 -0.89453 -0.55273h-2a1.0001 1.0001 0 1 0 0 2h1.3828l1.7227 3.4473a1.0001 1.0001 0 0 0 1.8867 -0.32227l0.58984-4.7227 0.52344 1.0449a1.0001 1.0001 0 0 0 0.89453 0.55273h3a1.0001 1.0001 0 1 0 0 -2h-2.3809l-1.7246-3.4473a1.0001 1.0001 0 0 0 -0.88672 -0.55078zm1.9785 6.998v1 5 1h5c0.55228 0 1-0.44772 1-1v-5c0-0.55228-0.44772-1-1-1v4l-1-1-1 1v-4h-3z" fill="#ff8484"/> </g> </svg> diff --git a/editor/icons/icon_slider_joint.svg b/editor/icons/icon_slider_joint.svg index 479323bf9a..d1469058d1 100644 --- a/editor/icons/icon_slider_joint.svg +++ b/editor/icons/icon_slider_joint.svg @@ -1,10 +1,5 @@ <svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1036.4)"> -<path d="m3 1051.4h5l-1-4z" fill="#fc9c9c" fill-opacity=".99608"/> -<path d="m6 1048.4 9-9v3l-8 8z" fill="#fb9b9b"/> -<path d="m10 1040.4-9 9v-3l8-8z" fill="#fb9b9b"/> -<path d="m13 1037.4h-5l1 4z" fill="#fc9c9c" fill-opacity=".99608"/> -<path d="m10 1038.4h-5" fill="none" stroke="#fb9b9b" stroke-linecap="round" stroke-width="2"/> -<path d="m11 1050.4h-5" fill="none" stroke="#fb9b9b" stroke-linecap="round" stroke-width="2"/> +<path transform="translate(0 1036.4)" d="m5 1c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1h3l-7 7v3l12-12zm10 2-12 12h8c0.55228 0 1-0.44772 1-1s-0.44772-1-1-1h-3l7-7z" fill="#fc9c9c"/> </g> </svg> diff --git a/editor/icons/icon_snap.svg b/editor/icons/icon_snap.svg index b1f36cfe43..0195f7cfc6 100644 --- a/editor/icons/icon_snap.svg +++ b/editor/icons/icon_snap.svg @@ -1,10 +1,93 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path d="m3 1036.4v3h-3v2h3v4h-3v2h3v3h2v-3-2-4h4 2 3v-2h-3v-3h-2v3h-4v-3h-2z" fill="#f3f3f3"/> -<path d="m11 1043.4a4 4 0 0 0 -4 4h2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2h2a4 4 0 0 0 -4 -4z" fill="#ff8484"/> -<rect x="7" y="1047.4" width="2" height="2" fill="#ff8484"/> -<rect x="13" y="1047.4" width="2" height="2" fill="#ff8484"/> -<rect x="7" y="1049.4" width="2" height="2" fill="#fff"/> -<rect x="13" y="1049.4" width="2" height="2" fill="#fff"/> -</g> +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg848" + sodipodi:docname="icon_snap.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata854"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs852" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2558" + inkscape:window-height="1422" + id="namedview850" + showgrid="true" + inkscape:pagecheckerboard="true" + inkscape:zoom="26.317631" + inkscape:cx="-14.078109" + inkscape:cy="-1.3201296" + inkscape:window-x="1366" + inkscape:window-y="16" + inkscape:window-maximized="1" + inkscape:current-layer="svg848"> + <inkscape:grid + type="xygrid" + id="grid862" /> + </sodipodi:namedview> + <path + style="fill:#ff8484;stroke-width:1.48039925" + inkscape:connector-curvature="0" + id="path836" + d="m 3.9501321,14.20668 a 5.9215969,5.9215969 0 0 0 8.0890509,-2.167455 l -2.5641252,-1.4804 A 2.9607985,2.9607985 0 0 1 5.4305313,11.642553 2.9607985,2.9607985 0 0 1 4.3468039,7.5980268 L 1.7826772,6.1176278 A 5.9215969,5.9215969 0 0 0 3.9501321,14.20668 Z" /> + <rect + style="fill:#ff8484;stroke-width:1.48039925" + id="rect838" + height="2.9607985" + width="2.9607985" + y="-4.4066463" + x="-16.44585" + transform="rotate(-150)" /> + <rect + style="fill:#ff8484;stroke-width:1.48039925" + id="rect840" + height="2.9607985" + width="2.9607985" + y="-4.4066463" + x="-7.5634551" + transform="rotate(-150)" /> + <rect + style="fill:#ffffff;stroke-width:1.48039925" + id="rect842" + height="2.9607985" + width="2.9607985" + y="-1.4458472" + x="-16.44585" + transform="rotate(-150)" /> + <rect + style="fill:#ffffff;stroke-width:1.48039925" + id="rect844" + height="2.9607985" + width="2.9607985" + y="-1.4458472" + x="-7.5634551" + transform="rotate(-150)" /> </svg> diff --git a/editor/icons/icon_snap_grid.svg b/editor/icons/icon_snap_grid.svg new file mode 100644 index 0000000000..b479496327 --- /dev/null +++ b/editor/icons/icon_snap_grid.svg @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg913" + sodipodi:docname="icon_snap_grid.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata919"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs917" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2558" + inkscape:window-height="1422" + id="namedview915" + showgrid="false" + inkscape:pagecheckerboard="true" + inkscape:zoom="52.635261" + inkscape:cx="6.4374987" + inkscape:cy="5.7074131" + inkscape:window-x="1366" + inkscape:window-y="16" + inkscape:window-maximized="1" + inkscape:current-layer="svg913" /> + <g + transform="translate(0 -1036.4)" + id="g911"> + <path + d="m3 1036.4v3h-3v2h3v4h-3v2h3v3h2v-3-2-4h4 2 3v-2h-3v-3h-2v3h-4v-3h-2z" + fill="#f3f3f3" + id="path899" /> + <path + d="m11 1043.4a4 4 0 0 0 -4 4h2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2h2a4 4 0 0 0 -4 -4z" + fill="#ff8484" + id="path901" /> + <rect + x="7" + y="1047.4" + width="2" + height="2" + fill="#ff8484" + id="rect903" /> + <rect + x="13" + y="1047.4" + width="2" + height="2" + fill="#ff8484" + id="rect905" /> + <rect + x="7" + y="1049.4" + width="2" + height="2" + fill="#fff" + id="rect907" /> + <rect + x="13" + y="1049.4" + width="2" + height="2" + fill="#fff" + id="rect909" /> + </g> +</svg> diff --git a/editor/icons/icon_warning.svg b/editor/icons/icon_warning.svg index 455e7b1877..8f6bf2184a 100644 --- a/editor/icons/icon_warning.svg +++ b/editor/icons/icon_warning.svg @@ -1,5 +1,5 @@ <svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(0 -1044.4)"> -<rect y="1044.4" width="8" height="8" ry="4" fill="#ffd684"/> +<rect y="1044.4" width="8" height="8" ry="4" fill="#ffdd65"/> </g> </svg> diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index cc519c1c4b..b448ab8920 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -120,13 +120,13 @@ String ResourceImporterScene::get_preset_name(int p_idx) const { switch (p_idx) { case PRESET_SINGLE_SCENE: return TTR("Import as Single Scene"); - case PRESET_SEPERATE_ANIMATIONS: return TTR("Import with Seperate Animations"); + case PRESET_SEPARATE_ANIMATIONS: return TTR("Import with Separate Animations"); case PRESET_SEPARATE_MATERIALS: return TTR("Import with Separate Materials"); case PRESET_SEPARATE_MESHES: return TTR("Import with Separate Objects"); case PRESET_SEPARATE_MESHES_AND_MATERIALS: return TTR("Import with Separate Objects+Materials"); - case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: return TTR("Import with Seperate Objects+Animations"); - case PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS: return TTR("Import with Seperate Materials+Animations"); - case PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS: return TTR("Import with Seperate Objects+Materials+Animations"); + case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: return TTR("Import with Separate Objects+Animations"); + case PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS: return TTR("Import with Separate Materials+Animations"); + case PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS: return TTR("Import with Separate Objects+Materials+Animations"); case PRESET_MULTIPLE_SCENES: return TTR("Import as Multiple Scenes"); case PRESET_MULTIPLE_SCENES_AND_MATERIALS: return TTR("Import as Multiple Scenes+Materials"); } @@ -954,10 +954,10 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in script_ext_hint += "*." + E->get(); } - bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS; - bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS; + bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; + bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; bool scenes_out = p_preset == PRESET_MULTIPLE_SCENES || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS; - bool animations_out = p_preset == PRESET_SEPERATE_ANIMATIONS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS; + bool animations_out = p_preset == PRESET_SEPARATE_ANIMATIONS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/custom_script", PROPERTY_HINT_FILE, script_ext_hint), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "nodes/storage", PROPERTY_HINT_ENUM, "Single Scene,Instanced Sub-Scenes"), scenes_out ? 1 : 0)); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 652977b98a..c3a66aa8b8 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -85,14 +85,14 @@ class ResourceImporterScene : public ResourceImporter { enum Presets { PRESET_SEPARATE_MATERIALS, PRESET_SEPARATE_MESHES, - PRESET_SEPERATE_ANIMATIONS, + PRESET_SEPARATE_ANIMATIONS, PRESET_SINGLE_SCENE, PRESET_SEPARATE_MESHES_AND_MATERIALS, PRESET_SEPARATE_MESHES_AND_ANIMATIONS, - PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS, - PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS, + PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS, + PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS, PRESET_MULTIPLE_SCENES, PRESET_MULTIPLE_SCENES_AND_MATERIALS, diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index d7762a66df..c8db1763ab 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -103,13 +103,11 @@ void AnimationPlayerEditor::_notification(int p_what) { get_tree()->connect("node_removed", this, "_node_removed"); add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel")); - add_constant_override("separation", get_constant("separation", "VBoxContainer")); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel")); - add_constant_override("separation", get_constant("separation", "VBoxContainer")); } break; case NOTIFICATION_THEME_CHANGED: { diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index b28da54c6d..27dad7756e 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -53,6 +53,8 @@ #define MIN_ZOOM 0.01 #define MAX_ZOOM 100 +#define RULER_WIDTH 15 * EDSCALE + class SnapDialog : public ConfirmationDialog { GDCLASS(SnapDialog, ConfirmationDialog); @@ -109,13 +111,13 @@ public: label->set_h_size_flags(SIZE_EXPAND_FILL); grid_step_x = memnew(SpinBox); - grid_step_x->set_min(-SPIN_BOX_GRID_RANGE); + grid_step_x->set_min(0.01); grid_step_x->set_max(SPIN_BOX_GRID_RANGE); grid_step_x->set_suffix("px"); child_container->add_child(grid_step_x); grid_step_y = memnew(SpinBox); - grid_step_y->set_min(-SPIN_BOX_GRID_RANGE); + grid_step_y->set_min(0.01); grid_step_y->set_max(SPIN_BOX_GRID_RANGE); grid_step_y->set_suffix("px"); child_container->add_child(grid_step_y); @@ -149,7 +151,7 @@ public: child_container->add_child(rotation_step); } - void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) { + void set_fields(const Point2 p_grid_offset, const Point2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) { grid_offset_x->set_value(p_grid_offset.x); grid_offset_y->set_value(p_grid_offset.y); grid_step_x->set_value(p_grid_step.x); @@ -158,11 +160,9 @@ public: rotation_step->set_value(p_rotation_step * (180 / Math_PI)); } - void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) { - p_grid_offset.x = grid_offset_x->get_value(); - p_grid_offset.y = grid_offset_y->get_value(); - p_grid_step.x = grid_step_x->get_value(); - p_grid_step.y = grid_step_y->get_value(); + void get_fields(Point2 &p_grid_offset, Point2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) { + p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value()); + p_grid_step = Point2(grid_step_x->get_value(), grid_step_y->get_value()); p_rotation_offset = rotation_offset->get_value() / (180 / Math_PI); p_rotation_step = rotation_step->get_value() / (180 / Math_PI); } @@ -222,6 +222,135 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) { undo_redo->commit_action(); } +void CanvasItemEditor::_snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) { + float radius = p_radius / zoom; + float dist; + + Transform2D rot_trans = Transform2D(rotation, Point2()); + p_value = rot_trans.inverse().xform(p_value); + p_target_snap = rot_trans.inverse().xform(p_target_snap); + r_current_snap = rot_trans.inverse().xform(r_current_snap); + + dist = Math::abs(p_value.x - p_target_snap.x); + if (p_radius < 0 || dist < radius && (!r_snapped[0] || dist < Math::abs(r_current_snap.x - p_value.x))) { + r_current_snap.x = p_target_snap.x; + r_snapped[0] = true; + } + + dist = Math::abs(p_value.y - p_target_snap.y); + if (p_radius < 0 || dist < radius && (!r_snapped[1] || dist < Math::abs(r_current_snap.y - p_value.y))) { + r_current_snap.y = p_target_snap.y; + r_snapped[1] = true; + } + + r_current_snap = rot_trans.xform(r_current_snap); +} + +void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap) { + const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_current); + if (canvas_item && p_current != p_to_snap) { + Transform2D ci_transform = canvas_item->get_global_transform_with_canvas(); + Transform2D to_snap_transform = p_to_snap->get_global_transform_with_canvas(); + if (ci_transform.get_rotation() == to_snap_transform.get_rotation()) { + Point2 begin = ci_transform.xform(canvas_item->get_item_rect().get_position()); + Point2 end = ci_transform.xform(canvas_item->get_item_rect().get_position() + canvas_item->get_item_rect().get_size()); + + _snap_if_closer(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation()); + _snap_if_closer(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation()); + } + } + for (int i = 0; i < p_current->get_child_count(); i++) { + _snap_other_nodes(p_value, r_current_snap, r_snapped, p_current->get_child(i), p_to_snap); + } +} + +Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const CanvasItem *p_canvas_item, unsigned int p_forced_modes) { + Point2 dist[2]; + bool snapped[2] = { false, false }; + + // Smart snap using the canvas position + Vector2 output = p_target; + real_t rotation = 0.0; + + if (p_canvas_item) { + Point2 begin; + Point2 end; + rotation = p_canvas_item->get_global_transform_with_canvas().get_rotation(); + + if ((snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) { + // Parent sides and center + bool can_snap = false; + if (const Control *c = Object::cast_to<Control>(p_canvas_item)) { + begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0))); + end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1))); + can_snap = true; + } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) { + begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position()); + end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position() + parent_ci->get_item_rect().get_size()); + can_snap = true; + } + + if (can_snap) { + _snap_if_closer(p_target, begin, output, snapped, rotation); + _snap_if_closer(p_target, (begin + end) / 2.0, output, snapped, rotation); + _snap_if_closer(p_target, end, output, snapped, rotation); + } + } + + // Self anchors (for sides) + if ((snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) { + if (const Control *c = Object::cast_to<Control>(p_canvas_item)) { + begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP)))); + end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM)))); + _snap_if_closer(p_target, begin, output, snapped, rotation); + _snap_if_closer(p_target, end, output, snapped, rotation); + } + } + + // Self sides (for anchors) + if ((snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) { + begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position()); + end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position() + p_canvas_item->get_item_rect().get_size()); + _snap_if_closer(p_target, begin, output, snapped, rotation); + _snap_if_closer(p_target, end, output, snapped, rotation); + } + + // Other nodes sides + if ((snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) { + _snap_other_nodes(p_target, output, snapped, get_tree()->get_edited_scene_root(), p_canvas_item); + } + } + + if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && rotation == 0.0) { + // Grid + Point2 offset = grid_offset; + if (snap_relative) { + List<Node *> &selection = editor_selection->get_selected_node_list(); + if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) { + offset = Object::cast_to<Node2D>(selection[0])->get_global_position(); + } else { + offset = _find_topleftmost_point(); + } + } + Point2 grid_output; + grid_output.x = Math::stepify(p_target.x - offset.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)) + offset.x; + grid_output.y = Math::stepify(p_target.y - offset.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)) + offset.y; + _snap_if_closer(p_target, grid_output, output, snapped, 0.0, -1.0); + } + + if (((snap_pixel && (p_modes & SNAP_PIXEL)) || (p_forced_modes & SNAP_PIXEL)) && rotation == 0.0) { + // Pixel + output = output.snapped(Size2(1, 1)); + } + + return output; +} + +float CanvasItemEditor::snap_angle(float p_target, float p_start) const { + float offset = snap_relative ? p_start : p_target; + return (snap_rotation && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target; +} + void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { Ref<InputEventKey> k = p_ev; @@ -232,22 +361,34 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { if (k->get_control()) return; - if (k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V && drag == DRAG_NONE && can_move_pivot) { - - if (k->get_shift()) { + if (k->is_pressed() && !k->is_echo()) { + if (drag_pivot_shortcut.is_valid() && drag_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) { //move drag pivot drag = DRAG_PIVOT; - } else if (!Input::get_singleton()->is_mouse_button_pressed(0)) { - - List<Node *> &selection = editor_selection->get_selected_node_list(); - Vector2 mouse_pos = viewport->get_local_mouse_pos(); - if (selection.size() && viewport->get_rect().has_point(mouse_pos)) { - //just in case, make it work if over viewport - mouse_pos = transform.affine_inverse().xform(mouse_pos); - mouse_pos = snap_point(mouse_pos); - - _edit_set_pivot(mouse_pos); + } else if (set_pivot_shortcut.is_valid() && set_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) { + if (!Input::get_singleton()->is_mouse_button_pressed(0)) { + List<Node *> &selection = editor_selection->get_selected_node_list(); + Vector2 mouse_pos = viewport->get_local_mouse_pos(); + if (selection.size() && viewport->get_rect().has_point(mouse_pos)) { + //just in case, make it work if over viewport + mouse_pos = transform.affine_inverse().xform(mouse_pos); + mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item()); + + _edit_set_pivot(mouse_pos); + } } + } else if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) { + // Multiply the grid size + grid_step_multiplier = MIN(grid_step_multiplier + 1, 12); + viewport_base->update(); + viewport->update(); + } else if ((snap_grid || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) { + // Divide the grid size + Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1); + if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0) + grid_step_multiplier--; + viewport_base->update(); + viewport->update(); } } } @@ -272,38 +413,25 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) { return memnew(CanvasItemEditorSelectedItem); } -inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) { - float offset = p_snap_relative ? p_start : p_offset; - return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target; -} - -Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const { - if (snap_grid) { - p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x); - p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y); - } - if (snap_pixel) - p_target = p_target.snapped(Size2(1, 1)); - - return p_target; -} - -float CanvasItemEditor::snap_angle(float p_target, float p_start) const { - return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target; -} - Dictionary CanvasItemEditor::get_state() const { Dictionary state; state["zoom"] = zoom; state["ofs"] = Point2(h_scroll->get_value(), v_scroll->get_value()); //state["ofs"]=-transform.get_origin(); - state["snap_offset"] = snap_offset; - state["snap_step"] = snap_step; + state["grid_offset"] = grid_offset; + state["grid_step"] = grid_step; state["snap_rotation_offset"] = snap_rotation_offset; state["snap_rotation_step"] = snap_rotation_step; + state["snap_active"] = snap_active; + state["snap_node_parent"] = snap_node_parent; + state["snap_node_anchors"] = snap_node_anchors; + state["snap_node_sides"] = snap_node_sides; + state["snap_other_nodes"] = snap_other_nodes; state["snap_grid"] = snap_grid; - state["snap_show_grid"] = snap_show_grid; + state["show_grid"] = show_grid; + state["show_rulers"] = show_rulers; + state["show_helpers"] = show_helpers; state["snap_rotation"] = snap_rotation; state["snap_relative"] = snap_relative; state["snap_pixel"] = snap_pixel; @@ -324,12 +452,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { v_scroll->set_value(ofs.y); } - if (state.has("snap_step")) { - snap_step = state["snap_step"]; + if (state.has("grid_offset")) { + grid_offset = state["grid_offset"]; } - if (state.has("snap_offset")) { - snap_offset = state["snap_offset"]; + if (state.has("grid_step")) { + grid_step = state["grid_step"]; } if (state.has("snap_rotation_step")) { @@ -340,40 +468,81 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { snap_rotation_offset = state["snap_rotation_offset"]; } + if (state.has("snap_active")) { + snap_active = state["snap_active"]; + snap_button->set_pressed(snap_active); + } + + if (state.has("snap_node_parent")) { + snap_node_parent = state["snap_node_parent"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); + smartsnap_config_popup->set_item_checked(idx, snap_node_parent); + } + + if (state.has("snap_node_anchors")) { + snap_node_anchors = state["snap_node_anchors"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS); + smartsnap_config_popup->set_item_checked(idx, snap_node_anchors); + } + + if (state.has("snap_node_sides")) { + snap_node_sides = state["snap_node_sides"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES); + smartsnap_config_popup->set_item_checked(idx, snap_node_sides); + } + + if (state.has("snap_other_nodes")) { + snap_other_nodes = state["snap_other_nodes"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES); + smartsnap_config_popup->set_item_checked(idx, snap_other_nodes); + } + if (state.has("snap_grid")) { snap_grid = state["snap_grid"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE); - edit_menu->get_popup()->set_item_checked(idx, snap_grid); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID); + snap_config_menu->get_popup()->set_item_checked(idx, snap_grid); + } + + if (state.has("show_grid")) { + show_grid = state["show_grid"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); + view_menu->get_popup()->set_item_checked(idx, show_grid); + } + + if (state.has("show_rulers")) { + show_rulers = state["show_rulers"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS); + view_menu->get_popup()->set_item_checked(idx, show_rulers); } - if (state.has("snap_show_grid")) { - snap_show_grid = state["snap_show_grid"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID); - edit_menu->get_popup()->set_item_checked(idx, snap_show_grid); + if (state.has("show_helpers")) { + show_helpers = state["show_helpers"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS); + view_menu->get_popup()->set_item_checked(idx, show_helpers); } if (state.has("snap_rotation")) { snap_rotation = state["snap_rotation"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); - edit_menu->get_popup()->set_item_checked(idx, snap_rotation); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); + snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation); } if (state.has("snap_relative")) { snap_relative = state["snap_relative"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE); - edit_menu->get_popup()->set_item_checked(idx, snap_relative); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE); + snap_config_menu->get_popup()->set_item_checked(idx, snap_relative); } if (state.has("snap_pixel")) { snap_pixel = state["snap_pixel"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); - edit_menu->get_popup()->set_item_checked(idx, snap_pixel); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); + snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel); } if (state.has("skeleton_show_bones")) { skeleton_show_bones = state["skeleton_show_bones"]; - int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES); - skeleton_menu->set_item_checked(idx, skeleton_show_bones); + int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES); + skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones); } viewport->update(); @@ -495,6 +664,7 @@ void CanvasItemEditor::_select_click_on_empty_area(Point2 p_click_pos, bool p_ap if (!p_append) { editor_selection->clear(); viewport->update(); + viewport_base->update(); }; if (p_box_selection) { @@ -534,6 +704,7 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po } viewport->update(); + viewport_base->update(); return still_selected; } @@ -566,7 +737,7 @@ void CanvasItemEditor::_key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE Vector2 drag = p_dir; if (p_snap) - drag *= snap_step; + drag *= grid_step * Math::pow(2.0, grid_step_multiplier); undo_redo->add_undo_method(canvas_item, "edit_set_state", canvas_item->edit_get_state()); @@ -649,7 +820,7 @@ int CanvasItemEditor::get_item_count() { return ic; } -CanvasItem *CanvasItemEditor::get_single_item() { +CanvasItem *CanvasItemEditor::_get_single_item() { Map<Node *, Object *> &selection = editor_selection->get_selection(); @@ -674,7 +845,7 @@ CanvasItem *CanvasItemEditor::get_single_item() { CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point) { // Returns a drag type if a resize handle is clicked - CanvasItem *canvas_item = get_single_item(); + CanvasItem *canvas_item = _get_single_item(); ERR_FAIL_COND_V(!canvas_item, DRAG_NONE); @@ -738,35 +909,7 @@ CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const return DRAG_NONE; } -float CanvasItemEditor::_anchor_snap(float p_anchor, bool *p_snapped, float p_opposite_anchor) { - bool snapped = false; - float dist, dist_min = 0.0; - float radius = 0.05 / zoom; - float basic_anchors[3] = { 0.0, 0.5, 1.0 }; - for (int i = 0; i < 3; i++) { - dist = fabs(p_anchor - basic_anchors[i]); - if (dist < radius) { - if (!snapped || dist <= dist_min) { - p_anchor = basic_anchors[i]; - dist_min = dist; - snapped = true; - } - } - } - dist = fabs(p_anchor - p_opposite_anchor); - if (p_opposite_anchor >= 0 && dist < radius) { - if (!snapped || dist <= dist_min) { - p_anchor = p_opposite_anchor; - dist_min = dist; - snapped = true; - } - } - if (p_snapped) - *p_snapped = snapped; - return p_anchor; -} - -Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor) { +Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2 anchor) { ERR_FAIL_COND_V(!p_control, Vector2()); Transform2D parent_transform = p_control->get_transform().affine_inverse(); @@ -775,7 +918,7 @@ Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor return parent_transform.xform(Vector2(parent_size.x * anchor.x, parent_size.y * anchor.y)); } -Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 position) { +Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 position) { ERR_FAIL_COND_V(!p_control, Vector2()); Size2 parent_size = p_control->get_parent_area_size(); @@ -784,7 +927,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 positi CanvasItemEditor::DragType CanvasItemEditor::_get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point) { // Returns a drag type if an anchor handle is clicked - CanvasItem *canvas_item = get_single_item(); + CanvasItem *canvas_item = _get_single_item(); ERR_FAIL_COND_V(!canvas_item, DRAG_NONE); Control *control = Object::cast_to<Control>(canvas_item); @@ -920,28 +1063,12 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *p_item) { } void CanvasItemEditor::_snap_changed() { - ((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step); + ((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step); + grid_step_multiplier = 0; + viewport_base->update(); viewport->update(); } -void CanvasItemEditor::_dialog_value_changed(double) { - - if (updating_value_dialog) - return; - - switch (last_option) { - - case ZOOM_SET: { - - zoom = dialog_val->get_value() / 100.0; - _update_scroll(0); - viewport->update(); - - } break; - default: {} - } -} - void CanvasItemEditor::_selection_result_pressed(int p_result) { if (selection_results.size() <= p_result) @@ -962,7 +1089,7 @@ void CanvasItemEditor::_selection_menu_hide() { void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) { - Point2 click = b->get_position(); + Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); Node *scene = editor->get_edited_scene(); if (!scene) @@ -1070,7 +1197,7 @@ void CanvasItemEditor::_update_cursor() { viewport->set_default_cursor_shape(c); } -void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { +void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) { { EditorNode *en = editor; @@ -1103,7 +1230,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { float prev_zoom = zoom; zoom = zoom * (1 - (0.05 * b->get_factor())); { - Point2 ofs = b->get_position(); + Point2 ofs = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); ofs = ofs / prev_zoom - ofs / zoom; h_scroll->set_value(h_scroll->get_value() + ofs.x); v_scroll->set_value(v_scroll->get_value() + ofs.y); @@ -1127,7 +1254,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { float prev_zoom = zoom; zoom = zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95); { - Point2 ofs = b->get_position(); + Point2 ofs = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); ofs = ofs / prev_zoom - ofs / zoom; h_scroll->set_value(h_scroll->get_value() + ofs.x); v_scroll->set_value(v_scroll->get_value() + ofs.y); @@ -1216,9 +1343,9 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) { if (b->is_pressed()) { // Set the pivot point - Point2 mouse_pos = b->get_position(); + Point2 mouse_pos = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); mouse_pos = transform.affine_inverse().xform(mouse_pos); - mouse_pos = snap_point(mouse_pos); + mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item()); _edit_set_pivot(mouse_pos); } return; @@ -1339,8 +1466,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { E->get().to }; - Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_position(), s); - float d = p.distance_to(b->get_position()); + Vector2 p = Geometry::get_closest_point_to_segment_2d(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()), s); + float d = p.distance_to(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position())); if (d < bone_width && d < closest_dist) { Cbone = E; closest_dist = d; @@ -1397,12 +1524,12 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } // Single selected item - CanvasItem *canvas_item = get_single_item(); + CanvasItem *canvas_item = _get_single_item(); if (canvas_item) { CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); ERR_FAIL_COND(!se); - Point2 click = b->get_position(); + Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); // Rotation if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { @@ -1440,7 +1567,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } // Drag anchor handles - if (Object::cast_to<Control>(canvas_item)) { + Control *control = Object::cast_to<Control>(canvas_item); + if (control && show_helpers && !Object::cast_to<Container>(control->get_parent())) { drag = _get_anchor_handle_drag_type(click, drag_point_from); if (drag != DRAG_NONE) { drag_from = transform.affine_inverse().xform(click); @@ -1453,7 +1581,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } // Multiple selected items - Point2 click = b->get_position(); + Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) { // Drag the nodes @@ -1513,12 +1641,12 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { // Mouse motion event _update_cursor(); - if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) - viewport->call_deferred("grab_focus"); + if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) + viewport_base->call_deferred("grab_focus"); if (box_selecting) { // Update box selection - box_selecting_to = transform.affine_inverse().xform(m->get_position()); + box_selecting_to = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position())); viewport->update(); return; } @@ -1564,7 +1692,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } Vector2 dfrom = drag_from; - Vector2 dto = transform.affine_inverse().xform(m->get_position()); + Vector2 dto = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position())); if (canvas_item->has_meta("_edit_lock_")) continue; @@ -1598,60 +1726,74 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { continue; } + bool uniform = m->get_shift(); + bool symmetric = m->get_alt(); + + Vector2 drag_vector = + canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) - + canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom); + + switch (drag) { + case DRAG_ALL: + case DRAG_NODE_2D: + dto -= drag_from - drag_point_from; + if (uniform) { + if (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) { + dto.y = drag_point_from.y; + } else { + dto.x = drag_point_from.x; + } + } + break; + } + Control *control = Object::cast_to<Control>(canvas_item); if (control) { // Drag and snap the anchor - Vector2 anchor = _position_to_anchor(control, canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto - drag_from + drag_point_from)); + Transform2D c_trans_rev = canvas_item->get_global_transform_with_canvas().affine_inverse(); + + Vector2 anchor = c_trans_rev.xform(dto - drag_from + drag_point_from); + anchor = _position_to_anchor(control, anchor); + + Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | SNAP_OTHER_NODES, _get_single_item(), SNAP_NODE_PARENT | SNAP_NODE_SIDES)); + anchor_snapped = _position_to_anchor(control, anchor_snapped).snapped(Vector2(0.00001, 0.00001)); + + bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x); switch (drag) { case DRAG_ANCHOR_TOP_LEFT: - control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_RIGHT)), false, false); - control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_BOTTOM)), false, false); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y); continue; break; case DRAG_ANCHOR_TOP_RIGHT: - control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_LEFT)), false, false); - control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_BOTTOM)), false, false); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y); continue; break; case DRAG_ANCHOR_BOTTOM_RIGHT: - control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_LEFT)), false, false); - control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_TOP)), false, false); - continue; + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y); break; case DRAG_ANCHOR_BOTTOM_LEFT: - control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_RIGHT)), false, false); - control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_TOP)), false, false); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y); continue; break; case DRAG_ANCHOR_ALL: - control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x)); - control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x)); - control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y)); - control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y)); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y); continue; break; } } - bool uniform = m->get_shift(); - bool symmetric = m->get_alt(); - - if (drag == DRAG_ALL || drag == DRAG_NODE_2D) - dto -= drag_from - drag_point_from; - - if (uniform && (drag == DRAG_ALL || drag == DRAG_NODE_2D)) { - if (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) { - dto.y = drag_point_from.y; - } else { - dto.x = drag_point_from.x; - } - } - dfrom = drag_point_from; - dto = snap_point(dto, drag_point_from); + dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, _get_single_item()); - Vector2 drag_vector = + drag_vector = canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) - canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom); @@ -1901,56 +2043,148 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } } +void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) { + Color color = Color(0.8, 0.8, 0.8, 0.5); + Ref<Font> font = get_font("font", "Label"); + Size2 text_size = font->get_string_size(p_string); + switch (p_side) { + case MARGIN_LEFT: + p_position += Vector2(-text_size.x - 5, text_size.y / 2); + break; + case MARGIN_TOP: + p_position += Vector2(-text_size.x / 2, -5); + break; + case MARGIN_RIGHT: + p_position += Vector2(5, text_size.y / 2); + break; + case MARGIN_BOTTOM: + p_position += Vector2(-text_size.x / 2, text_size.y + 5); + break; + } + viewport->draw_string(font, p_position, p_string, color); +} + +void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Margin p_side) { + String str = vformat("%d px", p_value); + if (p_value != 0) { + _draw_text_at_position(p_position, str, p_side); + } +} + void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side) { + String str = vformat("%.1f %%", p_value * 100.0); if (p_value != 0) { - Color color = Color(0.8, 0.8, 0.8, 0.5); - Ref<Font> font = get_font("font", "Label"); - String str = vformat("%.1f %%", p_value * 100.0); - Size2 text_size = font->get_string_size(str); - switch (p_side) { - case MARGIN_LEFT: - p_position += Vector2(-text_size.x - 5, text_size.y / 2); - break; - case MARGIN_TOP: - p_position += Vector2(-text_size.x / 2, -5); - break; - case MARGIN_RIGHT: - p_position += Vector2(5, text_size.y / 2); - break; - case MARGIN_BOTTOM: - p_position += Vector2(-text_size.x / 2, text_size.y + 5); - break; - } - viewport->draw_string(font, p_position, str, color); + _draw_text_at_position(p_position, str, p_side); } } -void CanvasItemEditor::_viewport_draw() { +void CanvasItemEditor::_draw_rulers() { + Color graduation_color = Color(0.5, 0.5, 0.5, 1); + Color bg_color = get_color("dark_color_2", "Editor"); + Color font_color = Color(0.8, 0.8, 0.8, 1); + Ref<Font> font = get_font("rulers", "EditorFonts"); + + // The rule transform + Transform2D ruler_transform; + if (show_grid || snap_grid) { + ruler_transform = Transform2D(); + if (snap_relative && get_item_count() > 0) { + ruler_transform.translate(_find_topleftmost_point()); + ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); + } else { + ruler_transform.translate(grid_offset); + ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); + } + while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) { - // TODO fetch the viewport? + ruler_transform.scale_basis(Point2(2, 2)); + } + } else { + float basic_rule = 100; + for (int i = 0; basic_rule * zoom > 100; i++) { + basic_rule /= (i % 2) ? 5.0 : 2.0; + } + for (int i = 0; basic_rule * zoom < 100; i++) { + basic_rule *= (i % 2) ? 2.0 : 5.0; + } + ruler_transform = Transform2D(); + ruler_transform.scale(Size2(basic_rule, basic_rule)); + } - Ref<Texture> pivot = get_icon("EditorPivot", "EditorIcons"); - _update_scrollbars(); - RID ci = viewport->get_canvas_item(); + // Subdivisions + int major_subdivision = 2; + Transform2D major_subdivide = Transform2D(); + major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision)); + + int minor_subdivision = 5; + Transform2D minor_subdivide = Transform2D(); + minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision)); + + // First and last graduations to draw (in the ruler space) + Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2()); + Point2 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size()); + + // Draw top ruler + viewport_base->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color); + for (int i = Math::ceil(first.x); i < last.x; i++) { + Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)); + if (i % (major_subdivision * minor_subdivision) == 0) { + viewport_base->draw_line(Point2(position.x + RULER_WIDTH, 0), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x; + viewport_base->draw_string(font, Point2(position.x + RULER_WIDTH + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + } else { + if (i % minor_subdivision == 0) { + viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.33), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + } else { + viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.66), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + } + } + } + + // Draw left ruler + viewport_base->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color); + for (int i = Math::ceil(first.y); i < last.y; i++) { + Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)); + if (i % (major_subdivision * minor_subdivision) == 0) { + viewport_base->draw_line(Point2(0, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y; + viewport_base->draw_string(font, Point2(2, position.y + RULER_WIDTH + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + } else { + if (i % minor_subdivision == 0) { + viewport_base->draw_line(Point2(RULER_WIDTH * 0.33, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + } else { + viewport_base->draw_line(Point2(RULER_WIDTH * 0.66, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + } + } + } + viewport_base->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color); +} - if (snap_show_grid) { +void CanvasItemEditor::_draw_focus() { + if (viewport_base->has_focus()) { + get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size())); + } +} + +void CanvasItemEditor::_draw_grid() { + if (show_grid) { //Draw the grid Size2 s = viewport->get_size(); int last_cell = 0; Transform2D xform = transform.affine_inverse(); - Vector2 grid_offset; - if (snap_relative && snap_grid && get_item_count() > 0) { + Vector2 real_grid_offset; + if (snap_relative && get_item_count() > 0) { Vector2 topleft = _find_topleftmost_point(); - grid_offset.x = fmod(topleft.x, snap_step.x); - grid_offset.y = fmod(topleft.y, snap_step.y); + real_grid_offset.x = fmod(topleft.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)); + real_grid_offset.y = fmod(topleft.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)); } else { - grid_offset = snap_offset; + real_grid_offset = grid_offset; } - if (snap_step.x != 0) { + if (grid_step.x != 0) { for (int i = 0; i < s.width; i++) { - int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - grid_offset.x) / snap_step.x)); + int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - real_grid_offset.x) / (grid_step.x * Math::pow(2.0, grid_step_multiplier)))); if (i == 0) last_cell = cell; if (last_cell != cell) @@ -1959,9 +2193,9 @@ void CanvasItemEditor::_viewport_draw() { } } - if (snap_step.y != 0) { + if (grid_step.y != 0) { for (int i = 0; i < s.height; i++) { - int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - grid_offset.y) / snap_step.y)); + int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - real_grid_offset.y) / (grid_step.y * Math::pow(2.0, grid_step_multiplier)))); if (i == 0) last_cell = cell; if (last_cell != cell) @@ -1970,21 +2204,15 @@ void CanvasItemEditor::_viewport_draw() { } } } +} - if (viewport->has_focus()) { - Size2 size = viewport->get_size(); - get_stylebox("Focus", "EditorStyles")->draw(ci, Rect2(Point2(), size)); - } - - Ref<Texture> lock = get_icon("Lock", "EditorIcons"); - Ref<Texture> group = get_icon("Group", "EditorIcons"); - - bool single = get_single_item() != NULL; - - Map<Node *, Object *> &selection = editor_selection->get_selection(); - +void CanvasItemEditor::_draw_selection() { bool pivot_found = false; + Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons"); + bool single = _get_single_item() != NULL; + RID ci = viewport->get_canvas_item(); + Map<Node *, Object *> &selection = editor_selection->get_selection(); for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); @@ -2036,10 +2264,10 @@ void CanvasItemEditor::_viewport_draw() { if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks - if (Object::cast_to<Node2D>(canvas_item)) { - - if (Object::cast_to<Node2D>(canvas_item)->edit_has_pivot()) { - viewport->draw_texture(pivot, xform.get_origin() + (-pivot->get_size() / 2).floor()); + Node2D *node2d = Object::cast_to<Node2D>(canvas_item); + if (node2d) { + if (node2d->edit_has_pivot()) { + viewport->draw_texture(pivot_icon, xform.get_origin() + (-pivot_icon->get_size() / 2).floor()); can_move_pivot = true; pivot_found = true; } @@ -2049,12 +2277,15 @@ void CanvasItemEditor::_viewport_draw() { if (control) { Vector2 pivot_ofs = control->get_pivot_offset(); if (pivot_ofs != Vector2()) { - viewport->draw_texture(pivot, xform.xform(pivot_ofs) + (-pivot->get_size() / 2).floor()); + viewport->draw_texture(pivot_icon, xform.xform(pivot_ofs) + (-pivot_icon->get_size() / 2).floor()); } can_move_pivot = true; pivot_found = true; - if (tool == TOOL_SELECT) { + if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) { + // Draw the helpers + Color color_base = Color(0.8, 0.8, 0.8, 0.5); + float anchors_values[4]; anchors_values[0] = control->get_anchor(MARGIN_LEFT); anchors_values[1] = control->get_anchor(MARGIN_TOP); @@ -2069,6 +2300,7 @@ void CanvasItemEditor::_viewport_draw() { anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i])); } + Map<Node *, Object *> &selection = editor_selection->get_selection(); // Get which anchor is dragged int dragged_anchor = -1; switch (drag) { @@ -2091,7 +2323,6 @@ void CanvasItemEditor::_viewport_draw() { // Draw the 4 lines when dragged bool snapped; Color color_snapped = Color(0.64, 0.93, 0.67, 0.5); - Color color_base = Color(0.8, 0.8, 0.8, 0.5); Vector2 corners_pos[4]; for (int i = 0; i < 4; i++) { @@ -2104,7 +2335,7 @@ void CanvasItemEditor::_viewport_draw() { float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i]; line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val); line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val); - _anchor_snap(anchors_values[i], &snapped); + snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0; viewport->draw_line(line_starts[i], line_ends[i], snapped ? color_snapped : color_base, (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) ? 2 : 1); } @@ -2136,6 +2367,83 @@ void CanvasItemEditor::_viewport_draw() { for (int i = 0; i < 4; i++) { anchor_handle->draw_rect(ci, anchor_rects[i]); } + + // Draw the margin values and the node width/height when dragging control side + float ratio = 0.33; + Transform2D parent_transform = xform * control->get_transform().affine_inverse(); + float node_pos_in_parent[4]; + + node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * control->get_parent_area_size().width + control->get_margin(MARGIN_LEFT); + node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * control->get_parent_area_size().height + control->get_margin(MARGIN_TOP); + node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * control->get_parent_area_size().width + control->get_margin(MARGIN_RIGHT); + node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * control->get_parent_area_size().height + control->get_margin(MARGIN_BOTTOM); + + switch (drag) { + case DRAG_LEFT: + case DRAG_TOP_LEFT: + case DRAG_BOTTOM_LEFT: + _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); + case DRAG_ALL: + Point2 start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio)); + Point2 end = start - Vector2(control->get_margin(MARGIN_LEFT), 0); + _draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + } + switch (drag) { + case DRAG_RIGHT: + case DRAG_TOP_RIGHT: + case DRAG_BOTTOM_RIGHT: + _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); + case DRAG_ALL: + Point2 start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio)); + Point2 end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0); + _draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + } + switch (drag) { + case DRAG_TOP: + case DRAG_TOP_LEFT: + case DRAG_TOP_RIGHT: + _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT); + case DRAG_ALL: + Point2 start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]); + Point2 end = start - Vector2(0, control->get_margin(MARGIN_TOP)); + _draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + } + switch (drag) { + case DRAG_BOTTOM: + case DRAG_BOTTOM_LEFT: + case DRAG_BOTTOM_RIGHT: + _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT); + case DRAG_ALL: + Point2 start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]); + Point2 end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM)); + _draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + } + + switch (drag) { + //Draw the ghost rect if the node if rotated/scaled + case DRAG_LEFT: + case DRAG_TOP_LEFT: + case DRAG_TOP: + case DRAG_TOP_RIGHT: + case DRAG_RIGHT: + case DRAG_BOTTOM_RIGHT: + case DRAG_BOTTOM: + case DRAG_BOTTOM_LEFT: + case DRAG_ALL: + if (control->get_rotation() != 0.0 || control->get_scale() != Vector2(1, 1)) { + Rect2 rect = Rect2(Vector2(node_pos_in_parent[0], node_pos_in_parent[1]), control->get_size()); + viewport->draw_rect(parent_transform.xform(rect), color_base, false); + } + break; + } } } @@ -2158,33 +2466,32 @@ void CanvasItemEditor::_viewport_draw() { } } } - - //DRAW_EMPTY_RECT( Rect2( current_window->get_scroll()-Point2(1,1), get_size()+Size2(2,2)), Color(0.8,0.8,1.0,0.8) ); - //E->get().last_rect = rect; } - pivot_button->set_disabled(!pivot_found); - VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); - - Color x_axis_color(1.0, 0.4, 0.4, 0.6); - Color y_axis_color(0.4, 1.0, 0.4, 0.6); - Color area_axis_color(0.4, 0.4, 1.0, 0.4); - Color rotate_color(0.4, 0.7, 1.0, 0.8); - - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(h_scroll->get_min(), 0) + transform.get_origin(), Point2(h_scroll->get_max(), 0) + transform.get_origin(), x_axis_color); - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(0, v_scroll->get_min()) + transform.get_origin(), Point2(0, v_scroll->get_max()) + transform.get_origin(), y_axis_color); if (box_selecting) { - Point2 bsfrom = transform.xform(drag_from); Point2 bsto = transform.xform(box_selecting_to); VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(bsfrom, bsto - bsfrom), Color(0.7, 0.7, 1.0, 0.3)); } + Color rotate_color(0.4, 0.7, 1.0, 0.8); if (drag == DRAG_ROTATE) { VisualServer::get_singleton()->canvas_item_add_line(ci, transform.xform(display_rotate_from), transform.xform(display_rotate_to), rotate_color); } +} + +void CanvasItemEditor::_draw_axis() { + RID ci = viewport->get_canvas_item(); + + Color x_axis_color(1.0, 0.4, 0.4, 0.6); + Color y_axis_color(0.4, 1.0, 0.4, 0.6); + Color area_axis_color(0.4, 0.4, 1.0, 0.4); + + Point2 origin = transform.get_origin(); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(0, origin.y), Point2(viewport->get_size().x, origin.y), x_axis_color); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(origin.x, 0), Point2(origin.x, viewport->get_size().y), y_axis_color); Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); @@ -2196,34 +2503,12 @@ void CanvasItemEditor::_viewport_draw() { }; for (int i = 0; i < 4; i++) { - VisualServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color); } +} - for (List<LockList>::Element *E = lock_list.front(); E; E = E->next()) { - - Vector2 ofs = transform.xform(E->get().pos); - if (E->get().lock) { - - lock->draw(ci, ofs); - ofs.x += lock->get_width(); - } - if (E->get().group) { - - group->draw(ci, ofs); - } - } - - { - - EditorNode *en = editor; - EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); - - if (!over_plugin_list->empty()) { - - over_plugin_list->forward_draw_over_canvas(transform, viewport); - } - } +void CanvasItemEditor::_draw_bones() { + RID ci = viewport->get_canvas_item(); if (skeleton_show_bones) { int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width"); @@ -2291,6 +2576,125 @@ void CanvasItemEditor::_viewport_draw() { } } +void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_xform) { + RID viewport_ci = viewport->get_canvas_item(); + + Transform2D transform_ci = p_xform; + CanvasItem *ci = Object::cast_to<CanvasItem>(p_node); + if (ci) + transform_ci = transform_ci * ci->get_transform(); + + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + _draw_locks_and_groups(p_node->get_child(i), transform_ci); + } + + if (ci) { + Ref<Texture> lock = get_icon("Lock", "EditorIcons"); + if (p_node->has_meta("_edit_lock_")) { + lock->draw(viewport_ci, transform_ci.xform(Point2(0, 0))); + } + + Ref<Texture> group = get_icon("Group", "EditorIcons"); + if (ci->has_meta("_edit_group_")) { + Vector2 ofs = transform_ci.xform(Point2(0, 0)); + if (ci->has_meta("_edit_lock_")) + ofs = Point2(ofs.x + lock->get_size().x, ofs.y); + group->draw(viewport_ci, ofs); + } + } +} + +void CanvasItemEditor::_build_bones_list(Node *p_node) { + for (int i = 0; i < p_node->get_child_count(); i++) { + _build_bones_list(p_node->get_child(i)); + } + + CanvasItem *c = Object::cast_to<CanvasItem>(p_node); + if (c && c->is_visible_in_tree()) { + if (c->has_meta("_edit_bone_")) { + + ObjectID id = c->get_instance_id(); + if (!bone_list.has(id)) { + BoneList bone; + bone.bone = id; + bone_list[id] = bone; + } + + bone_list[id].last_pass = bone_last_frame; + } + } +} + +void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) { + for (int i = 0; i < p_node->get_child_count(); i++) { + _get_encompassing_rect(p_node->get_child(i), r_rect, p_xform); + } + + CanvasItem *c = Object::cast_to<CanvasItem>(p_node); + if (c && c->is_visible_in_tree()) { + Rect2 rect = c->get_item_rect(); + Transform2D xform = p_xform * c->get_transform(); + r_rect.expand_to(xform.xform(rect.position)); + r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); + r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); + r_rect.expand_to(xform.xform(rect.position + rect.size)); + } +} + +void CanvasItemEditor::_draw_viewport_base() { + if (show_rulers) + _draw_rulers(); + _draw_focus(); +} + +void CanvasItemEditor::_draw_viewport() { + + // hide/show buttons depending on the selection + bool all_locked = true; + bool all_group = true; + List<Node *> &selection = editor_selection->get_selected_node_list(); + if (selection.empty()) { + all_locked = false; + all_group = false; + } else { + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { + if (Object::cast_to<Control>(E->get()) && !Object::cast_to<Control>(E->get())->has_meta("_edit_lock_")) { + all_locked = false; + break; + } + } + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { + if (Object::cast_to<Control>(E->get()) && !Object::cast_to<Control>(E->get())->has_meta("_edit_group_")) { + all_group = false; + break; + } + } + } + + lock_button->set_visible(!all_locked); + lock_button->set_disabled(selection.empty()); + unlock_button->set_visible(all_locked); + group_button->set_visible(!all_group); + group_button->set_disabled(selection.empty()); + ungroup_button->set_visible(all_group); + + _update_scrollbars(); + + _draw_grid(); + _draw_selection(); + _draw_axis(); + _draw_locks_and_groups(editor->get_edited_scene(), transform); + + RID ci = viewport->get_canvas_item(); + VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); + + EditorPluginList *over_plugin_list = editor->get_editor_plugins_over(); + if (!over_plugin_list->empty()) { + over_plugin_list->forward_draw_over_canvas(transform, viewport); + } + _draw_focus(); +} + void CanvasItemEditor::_notification(int p_what) { if (p_what == NOTIFICATION_FIXED_PROCESS) { @@ -2341,6 +2745,7 @@ void CanvasItemEditor::_notification(int p_what) { if (pivot != se->prev_pivot || anchors[MARGIN_LEFT] != se->prev_anchors[MARGIN_LEFT] || anchors[MARGIN_RIGHT] != se->prev_anchors[MARGIN_RIGHT] || anchors[MARGIN_TOP] != se->prev_anchors[MARGIN_TOP] || anchors[MARGIN_BOTTOM] != se->prev_anchors[MARGIN_BOTTOM]) { viewport->update(); + viewport_base->update(); se->prev_pivot = pivot; se->prev_anchors[MARGIN_LEFT] = anchors[MARGIN_LEFT]; se->prev_anchors[MARGIN_RIGHT] = anchors[MARGIN_RIGHT]; @@ -2389,6 +2794,9 @@ void CanvasItemEditor::_notification(int p_what) { list_select_button->set_icon(get_icon("ListSelect", "EditorIcons")); move_button->set_icon(get_icon("ToolMove", "EditorIcons")); rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons")); + snap_button->set_icon(get_icon("Snap", "EditorIcons")); + snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons")); + skeleton_menu->set_icon(get_icon("Bone", "EditorIcons")); pan_button->set_icon(get_icon("ToolPan", "EditorIcons")); pivot_button->set_icon(get_icon("EditPivot", "EditorIcons")); select_handle = get_icon("EditorHandle", "EditorIcons"); @@ -2399,6 +2807,10 @@ void CanvasItemEditor::_notification(int p_what) { ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons")); key_insert_button->set_icon(get_icon("Key", "EditorIcons")); + zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons")); + zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); + zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons")); + anchor_menu->set_icon(get_icon("Anchor", "EditorIcons")); PopupMenu *p = anchor_menu->get_popup(); @@ -2433,6 +2845,9 @@ void CanvasItemEditor::_notification(int p_what) { list_select_button->set_icon(get_icon("ListSelect", "EditorIcons")); move_button->set_icon(get_icon("ToolMove", "EditorIcons")); rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons")); + snap_button->set_icon(get_icon("Snap", "EditorIcons")); + snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons")); + skeleton_menu->set_icon(get_icon("Bone", "EditorIcons")); pan_button->set_icon(get_icon("ToolPan", "EditorIcons")); pivot_button->set_icon(get_icon("EditPivot", "EditorIcons")); select_handle = get_icon("EditorHandle", "EditorIcons"); @@ -2474,66 +2889,23 @@ void CanvasItemEditor::edit(CanvasItem *p_canvas_item) { drag = DRAG_NONE; + // Clear the selection editor_selection->clear(); //_clear_canvas_items(); editor_selection->add_node(p_canvas_item); //_add_canvas_item(p_canvas_item); viewport->update(); -} - -void CanvasItemEditor::_find_canvas_items_span(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) { - - if (!p_node) - return; - - CanvasItem *c = Object::cast_to<CanvasItem>(p_node); - - for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - - //CanvasItem *r=NULL; - - if (c && !c->is_set_as_toplevel()) - _find_canvas_items_span(p_node->get_child(i), r_rect, p_xform * c->get_transform()); - else - _find_canvas_items_span(p_node->get_child(i), r_rect, Transform2D()); - } - - if (c && c->is_visible_in_tree()) { - - Rect2 rect = c->get_item_rect(); - Transform2D xform = p_xform * c->get_transform(); - - LockList lock; - lock.lock = c->has_meta("_edit_lock_"); - lock.group = c->has_meta("_edit_group_"); - - if (lock.group || lock.lock) { - lock.pos = xform.xform(rect.position); - lock_list.push_back(lock); - } - - if (c->has_meta("_edit_bone_")) { - - ObjectID id = c->get_instance_id(); - if (!bone_list.has(id)) { - BoneList bone; - bone.bone = id; - bone_list[id] = bone; - } - - bone_list[id].last_pass = bone_last_frame; - } - - r_rect.expand_to(xform.xform(rect.position)); - r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); - r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); - r_rect.expand_to(xform.xform(rect.position + rect.size)); - } + viewport_base->update(); } void CanvasItemEditor::_update_scrollbars() { updating_scroll = true; + if (show_rulers) + viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH)); + else + viewport_scrollable->set_begin(Point2()); + Size2 size = viewport->get_size(); Size2 hmin = h_scroll->get_minimum_size(); Size2 vmin = v_scroll->get_minimum_size(); @@ -2550,11 +2922,12 @@ void CanvasItemEditor::_update_scrollbars() { Rect2 canvas_item_rect = Rect2(Point2(), screen_rect); - lock_list.clear(); bone_last_frame++; - if (editor->get_edited_scene()) - _find_canvas_items_span(editor->get_edited_scene(), canvas_item_rect, Transform2D()); + if (editor->get_edited_scene()) { + _build_bones_list(editor->get_edited_scene()); + _get_encompassing_rect(editor->get_edited_scene(), canvas_item_rect, Transform2D()); + } List<Map<ObjectID, BoneList>::Element *> bone_to_erase; @@ -2577,7 +2950,6 @@ void CanvasItemEditor::_update_scrollbars() { Point2 ofs; if (canvas_item_rect.size.height <= (local_rect.size.y / zoom)) { - v_scroll->hide(); ofs.y = canvas_item_rect.position.y; } else { @@ -2638,6 +3010,7 @@ void CanvasItemEditor::_update_scroll(float) { editor->get_scene_root()->set_global_canvas_transform(transform); viewport->update(); + viewport_base->update(); } void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) { @@ -2684,88 +3057,117 @@ void CanvasItemEditor::_set_full_rect() { undo_redo->commit_action(); } +void CanvasItemEditor::_zoom_minus() { + if (zoom < MIN_ZOOM) + return; + zoom /= 2.0; + + _update_scroll(0); + viewport->update(); + viewport_base->update(); +} + +void CanvasItemEditor::_zoom_reset() { + zoom = 1; + _update_scroll(0); + viewport->update(); + viewport_base->update(); +} + +void CanvasItemEditor::_zoom_plus() { + if (zoom > MAX_ZOOM) + return; + + zoom *= 2.0; + _update_scroll(0); + viewport->update(); + viewport_base->update(); +} + +void CanvasItemEditor::_toggle_snap(bool p_status) { + snap_active = p_status; + viewport->update(); + viewport_base->update(); +} + void CanvasItemEditor::_popup_callback(int p_op) { last_option = MenuOption(p_op); switch (p_op) { - case SNAP_USE: { - snap_grid = !snap_grid; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE); - edit_menu->get_popup()->set_item_checked(idx, snap_grid); + case SHOW_GRID: { + show_grid = !show_grid; + int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); + view_menu->get_popup()->set_item_checked(idx, show_grid); viewport->update(); + viewport_base->update(); } break; - case SNAP_SHOW_GRID: { - snap_show_grid = !snap_show_grid; - int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID); - edit_menu->get_popup()->set_item_checked(idx, snap_show_grid); - viewport->update(); + case SNAP_USE_NODE_PARENT: { + snap_node_parent = !snap_node_parent; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); + smartsnap_config_popup->set_item_checked(idx, snap_node_parent); + } break; + case SNAP_USE_NODE_ANCHORS: { + snap_node_anchors = !snap_node_anchors; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS); + smartsnap_config_popup->set_item_checked(idx, snap_node_anchors); + } break; + case SNAP_USE_NODE_SIDES: { + snap_node_sides = !snap_node_sides; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES); + smartsnap_config_popup->set_item_checked(idx, snap_node_sides); + } break; + case SNAP_USE_OTHER_NODES: { + snap_other_nodes = !snap_other_nodes; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES); + smartsnap_config_popup->set_item_checked(idx, snap_other_nodes); + } break; + case SNAP_USE_GRID: { + snap_grid = !snap_grid; + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID); + snap_config_menu->get_popup()->set_item_checked(idx, snap_grid); } break; case SNAP_USE_ROTATION: { snap_rotation = !snap_rotation; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); - edit_menu->get_popup()->set_item_checked(idx, snap_rotation); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); + snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation); } break; case SNAP_RELATIVE: { snap_relative = !snap_relative; - int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE); - edit_menu->get_popup()->set_item_checked(idx, snap_relative); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE); + snap_config_menu->get_popup()->set_item_checked(idx, snap_relative); viewport->update(); + viewport_base->update(); } break; case SNAP_USE_PIXEL: { snap_pixel = !snap_pixel; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); - edit_menu->get_popup()->set_item_checked(idx, snap_pixel); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); + snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel); } break; case SNAP_CONFIGURE: { - ((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step); + ((SnapDialog *)snap_dialog)->set_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step); snap_dialog->popup_centered(Size2(220, 160)); } break; case SKELETON_SHOW_BONES: { skeleton_show_bones = !skeleton_show_bones; - int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES); - skeleton_menu->set_item_checked(idx, skeleton_show_bones); + int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES); + skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones); viewport->update(); } break; - case ZOOM_IN: { - if (zoom > MAX_ZOOM) - return; - zoom = zoom * (1.0 / 0.5); - _update_scroll(0); + case SHOW_HELPERS: { + show_helpers = !show_helpers; + int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS); + view_menu->get_popup()->set_item_checked(idx, show_helpers); viewport->update(); - return; } break; - case ZOOM_OUT: { - if (zoom < MIN_ZOOM) - return; - - zoom = zoom * 0.5; - _update_scroll(0); + case SHOW_RULERS: { + show_rulers = !show_rulers; + int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS); + view_menu->get_popup()->set_item_checked(idx, show_rulers); viewport->update(); - return; - - } break; - case ZOOM_RESET: { - - zoom = 1; - _update_scroll(0); - viewport->update(); - return; - + viewport_base->update(); } break; - case ZOOM_SET: { - - updating_value_dialog = true; - dialog_label->set_text(TTR("Zoom (%):")); - dialog_val->set_min(0.1); - dialog_val->set_step(0.1); - dialog_val->set_max(800); - dialog_val->set_value(zoom * 100); - value_dialog->popup_centered(Size2(200, 85)); - updating_value_dialog = false; - - } break; case LOCK_SELECTED: { List<Node *> &selection = editor_selection->get_selected_node_list(); @@ -3112,7 +3514,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { n2d->set_meta("_edit_bone_", true); if (!skeleton_show_bones) - skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); + skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3131,7 +3533,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { n2d->set_meta("_edit_bone_", Variant()); if (!skeleton_show_bones) - skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); + skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3151,7 +3553,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { canvas_item->set_meta("_edit_ik_", true); if (!skeleton_show_bones) - skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); + skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3171,7 +3573,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { n2d->set_meta("_edit_ik_", Variant()); if (!skeleton_show_bones) - skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); + skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3234,15 +3636,19 @@ void CanvasItemEditor::_focus_selection(int p_op) { void CanvasItemEditor::_bind_methods() { + ClassDB::bind_method("_zoom_minus", &CanvasItemEditor::_zoom_minus); + ClassDB::bind_method("_zoom_reset", &CanvasItemEditor::_zoom_reset); + ClassDB::bind_method("_zoom_plus", &CanvasItemEditor::_zoom_plus); + ClassDB::bind_method("_toggle_snap", &CanvasItemEditor::_toggle_snap); ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll); ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback); - ClassDB::bind_method("_dialog_value_changed", &CanvasItemEditor::_dialog_value_changed); ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data); ClassDB::bind_method("_tool_select", &CanvasItemEditor::_tool_select); ClassDB::bind_method("_keying_changed", &CanvasItemEditor::_keying_changed); ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input); - ClassDB::bind_method("_viewport_draw", &CanvasItemEditor::_viewport_draw); - ClassDB::bind_method("_viewport_gui_input", &CanvasItemEditor::_viewport_gui_input); + ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport); + ClassDB::bind_method("_draw_viewport_base", &CanvasItemEditor::_draw_viewport_base); + ClassDB::bind_method("_viewport_base_gui_input", &CanvasItemEditor::_viewport_base_gui_input); ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed); ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed); ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide); @@ -3284,64 +3690,92 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->set_area_as_parent_rect(); bottom_split = memnew(VSplitContainer); - bottom_split->set_v_size_flags(SIZE_EXPAND_FILL); add_child(bottom_split); + bottom_split->set_v_size_flags(SIZE_EXPAND_FILL); palette_split = memnew(HSplitContainer); - palette_split->set_v_size_flags(SIZE_EXPAND_FILL); bottom_split->add_child(palette_split); + palette_split->set_v_size_flags(SIZE_EXPAND_FILL); - Control *vp_base = memnew(Control); - vp_base->set_v_size_flags(SIZE_EXPAND_FILL); - palette_split->add_child(vp_base); - - ViewportContainer *vp = memnew(ViewportContainer); - vp->set_stretch(true); - vp_base->add_child(vp); - vp->set_area_as_parent_rect(); - vp->add_child(p_editor->get_scene_root()); + viewport_base = memnew(Control); + palette_split->add_child(viewport_base); + viewport_base->connect("draw", this, "_draw_viewport_base"); + viewport_base->connect("gui_input", this, "_viewport_base_gui_input"); + viewport_base->set_focus_mode(FOCUS_ALL); + viewport_base->set_v_size_flags(SIZE_EXPAND_FILL); + viewport_base->set_h_size_flags(SIZE_EXPAND_FILL); + + viewport_scrollable = memnew(Control); + viewport_base->add_child(viewport_scrollable); + viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS); + viewport_scrollable->set_draw_behind_parent(true); + viewport_scrollable->set_area_as_parent_rect(); + viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH)); + + ViewportContainer *scene_tree = memnew(ViewportContainer); + viewport_scrollable->add_child(scene_tree); + scene_tree->set_stretch(true); + scene_tree->set_area_as_parent_rect(); + scene_tree->add_child(p_editor->get_scene_root()); viewport = memnew(CanvasItemEditorViewport(p_editor, this)); - vp_base->add_child(viewport); + viewport_scrollable->add_child(viewport); + viewport->set_mouse_filter(MOUSE_FILTER_PASS); viewport->set_area_as_parent_rect(); viewport->set_clip_contents(true); + viewport->connect("draw", this, "_draw_viewport"); h_scroll = memnew(HScrollBar); - v_scroll = memnew(VScrollBar); - viewport->add_child(h_scroll); - viewport->add_child(v_scroll); - viewport->connect("draw", this, "_viewport_draw"); - viewport->connect("gui_input", this, "_viewport_gui_input"); - h_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED); - v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED); - h_scroll->hide(); + + v_scroll = memnew(VScrollBar); + viewport->add_child(v_scroll); + v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED); v_scroll->hide(); + + HBoxContainer *zoom_hb = memnew(HBoxContainer); + viewport->add_child(zoom_hb); + zoom_hb->set_begin(Point2(5, 5)); + + zoom_minus = memnew(ToolButton); + zoom_hb->add_child(zoom_minus); + zoom_minus->connect("pressed", this, "_zoom_minus"); + zoom_minus->set_focus_mode(FOCUS_NONE); + + zoom_reset = memnew(ToolButton); + zoom_hb->add_child(zoom_reset); + zoom_reset->connect("pressed", this, "_zoom_reset"); + zoom_reset->set_focus_mode(FOCUS_NONE); + + zoom_plus = memnew(ToolButton); + zoom_hb->add_child(zoom_plus); + zoom_plus->connect("pressed", this, "_zoom_plus"); + zoom_plus->set_focus_mode(FOCUS_NONE); + updating_scroll = false; - viewport->set_focus_mode(FOCUS_ALL); handle_len = 10; first_update = true; select_button = memnew(ToolButton); - select_button->set_toggle_mode(true); hb->add_child(select_button); + select_button->set_toggle_mode(true); select_button->connect("pressed", this, "_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_tooltip(TTR("Select Mode") + " $sc\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Depth list selection")); move_button = memnew(ToolButton); - move_button->set_toggle_mode(true); hb->add_child(move_button); + move_button->set_toggle_mode(true); move_button->connect("pressed", this, "_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_tooltip(TTR("Move Mode")); rotate_button = memnew(ToolButton); - rotate_button->set_toggle_mode(true); hb->add_child(rotate_button); + rotate_button->set_toggle_mode(true); rotate_button->connect("pressed", this, "_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_tooltip(TTR("Rotate Mode")); @@ -3349,25 +3783,60 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); list_select_button = memnew(ToolButton); - list_select_button->set_toggle_mode(true); hb->add_child(list_select_button); + list_select_button->set_toggle_mode(true); list_select_button->connect("pressed", this, "_tool_select", make_binds(TOOL_LIST_SELECT)); list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); pivot_button = memnew(ToolButton); - pivot_button->set_toggle_mode(true); hb->add_child(pivot_button); + pivot_button->set_toggle_mode(true); pivot_button->connect("pressed", this, "_tool_select", make_binds(TOOL_EDIT_PIVOT)); pivot_button->set_tooltip(TTR("Click to change object's rotation pivot.")); pan_button = memnew(ToolButton); - pan_button->set_toggle_mode(true); hb->add_child(pan_button); + pan_button->set_toggle_mode(true); pan_button->connect("pressed", this, "_tool_select", make_binds(TOOL_PAN)); pan_button->set_tooltip(TTR("Pan Mode")); hb->add_child(memnew(VSeparator)); + snap_button = memnew(ToolButton); + hb->add_child(snap_button); + snap_button->set_toggle_mode(true); + snap_button->connect("toggled", this, "_toggle_snap"); + snap_button->set_tooltip(TTR("Toggles snapping")); + snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap"), KEY_S)); + + snap_config_menu = memnew(MenuButton); + hb->add_child(snap_config_menu); + snap_config_menu->get_popup()->connect("id_pressed", this, "_popup_callback"); + snap_config_menu->set_h_size_flags(SIZE_SHRINK_END); + snap_config_menu->set_tooltip(TTR("Snapping options")); + + PopupMenu *p = snap_config_menu->get_popup(); + p->connect("id_pressed", this, "_popup_callback"); + p->set_hide_on_checkable_item_selection(false); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_grid", TTR("Snap to grid")), SNAP_USE_GRID); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap...")), SNAP_CONFIGURE); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL); + p->add_submenu_item(TTR("Smart snapping"), "SmartSnapping"); + + smartsnap_config_popup = memnew(PopupMenu); + p->add_child(smartsnap_config_popup); + smartsnap_config_popup->set_name("SmartSnapping"); + smartsnap_config_popup->connect("id_pressed", this, "_popup_callback"); + smartsnap_config_popup->set_hide_on_checkable_item_selection(false); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_parent", TTR("Snap to parent")), SNAP_USE_NODE_PARENT); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_anchors", TTR("Snap to node anchor")), SNAP_USE_NODE_ANCHORS); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_sides", TTR("Snap to node sides")), SNAP_USE_NODE_SIDES); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to other nodes")), SNAP_USE_OTHER_NODES); + + hb->add_child(memnew(VSeparator)); + lock_button = memnew(ToolButton); hb->add_child(lock_button); @@ -3391,35 +3860,23 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - edit_menu = memnew(MenuButton); - edit_menu->set_text(TTR("Edit")); - hb->add_child(edit_menu); - edit_menu->get_popup()->connect("id_pressed", this, "_popup_callback"); + skeleton_menu = memnew(MenuButton); + hb->add_child(skeleton_menu); - PopupMenu *p; - p = edit_menu->get_popup(); + p = skeleton_menu->get_popup(); p->set_hide_on_checkable_item_selection(false); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap")), SNAP_USE); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid")), SNAP_SHOW_GRID); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap..")), SNAP_CONFIGURE); + p->connect("id_pressed", this, "_popup_callback"); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES); p->add_separator(); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES); p->add_separator(); - p->add_submenu_item(TTR("Skeleton.."), "skeleton"); - skeleton_menu = memnew(PopupMenu); - p->add_child(skeleton_menu); - skeleton_menu->set_name("skeleton"); - skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES); - skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES); - skeleton_menu->add_separator(); - skeleton_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES); - skeleton_menu->add_separator(); - skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN); - skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN); - skeleton_menu->set_hide_on_checkable_item_selection(false); - skeleton_menu->connect("id_pressed", this, "_popup_callback"); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN); + p->set_hide_on_checkable_item_selection(false); + p->connect("id_pressed", this, "_popup_callback"); + + hb->add_child(memnew(VSeparator)); view_menu = memnew(MenuButton); view_menu->set_text(TTR("View")); @@ -3427,11 +3884,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { view_menu->get_popup()->connect("id_pressed", this, "_popup_callback"); p = view_menu->get_popup(); - - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_in", TTR("Zoom In")), ZOOM_IN); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_out", TTR("Zoom Out")), ZOOM_OUT); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset")), ZOOM_RESET); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_set", TTR("Zoom Set..")), ZOOM_SET); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid"), KEY_G), 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"), KEY_R), SHOW_RULERS); 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); @@ -3502,23 +3957,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_dialog->connect("confirmed", this, "_snap_changed"); add_child(snap_dialog); - value_dialog = memnew(AcceptDialog); - value_dialog->set_title(TTR("Set a Value")); - value_dialog->get_ok()->set_text(TTR("Close")); - add_child(value_dialog); - - Label *l = memnew(Label); - l->set_text(TTR("Snap (Pixels):")); - l->set_position(Point2(5, 5)); - value_dialog->add_child(l); - dialog_label = l; - - dialog_val = memnew(SpinBox); - dialog_val->set_anchor(MARGIN_RIGHT, ANCHOR_END); - dialog_val->set_begin(Point2(15, 25)); - dialog_val->set_end(Point2(-10, 25)); - value_dialog->add_child(dialog_val); - dialog_val->connect("value_changed", this, "_dialog_value_changed"); select_sb = Ref<StyleBoxTexture>(memnew(StyleBoxTexture)); selection_menu = memnew(PopupMenu); @@ -3527,22 +3965,35 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { selection_menu->connect("id_pressed", this, "_selection_result_pressed"); selection_menu->connect("popup_hide", this, "_selection_menu_hide"); + drag_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/drag_pivot", TTR("Drag pivot from mouse position"), KEY_MASK_SHIFT | KEY_V); + set_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/set_pivot", TTR("Set pivot at mouse position"), KEY_V); + + 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); + key_pos = true; key_rot = true; key_scale = false; + show_grid = false; + show_helpers = false; + show_rulers = false; zoom = 1; - snap_offset = Vector2(0, 0); - snap_step = Vector2(10, 10); + grid_offset = Point2(); + grid_step = Point2(10, 10); + grid_step_multiplier = 0; snap_rotation_offset = 0; snap_rotation_step = 15 / (180 / Math_PI); - snap_grid = false; - snap_show_grid = false; + snap_active = false; + snap_node_parent = true; + snap_node_anchors = true; + snap_node_sides = true; + snap_other_nodes = true; + snap_grid = true; snap_rotation = false; snap_pixel = false; skeleton_show_bones = true; - skeleton_menu->set_item_checked(skeleton_menu->get_item_index(SKELETON_SHOW_BONES), true); - updating_value_dialog = false; + skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); box_selecting = false; //zoom=0.5; singleton = this; @@ -3573,7 +4024,7 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) { canvas_item_editor->show(); canvas_item_editor->set_fixed_process(true); VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false); - canvas_item_editor->viewport->grab_focus(); + canvas_item_editor->viewport_base->grab_focus(); } else { @@ -3742,7 +4193,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & target_pos -= texture_size / 2; } // there's nothing to be used as source position so snapping will work as absolute if enabled - target_pos = canvas->snap_point(target_pos, Vector2()); + target_pos = canvas->snap_point(target_pos); editor_data->get_undo_redo().add_do_method(child, "set_position", target_pos); } @@ -3776,22 +4227,13 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons editor_data->get_undo_redo().add_do_method(sed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name); editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); - Point2 pos; - Node2D *parent_node2d = Object::cast_to<Node2D>(parent); - if (parent_node2d) { - pos = parent_node2d->get_global_position(); - } else { - Control *parent_control = Object::cast_to<Control>(parent); - if (parent_control) { - pos = parent_control->get_global_position(); - } + CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent); + if (parent_ci) { + Vector2 target_pos = canvas->get_canvas_transform().affine_inverse().xform(p_point); + target_pos = canvas->snap_point(target_pos); + target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos); + editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); } - Transform2D trans = canvas->get_canvas_transform(); - Vector2 target_pos = (p_point - trans.get_origin()) / trans.get_scale().x - pos; - // in relative snapping it may be useful for the user to take the original node position into account - Vector2 start_pos = Object::cast_to<Node2D>(instanced_scene) ? Object::cast_to<Node2D>(instanced_scene)->get_position() : target_pos; - target_pos = canvas->snap_point(target_pos, start_pos); - editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); return true; } @@ -3870,6 +4312,20 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian continue; } memdelete(instanced_scene); + } else if (type == "Texture" || + type == "ImageTexture" || + type == "ViewportTexture" || + type == "CurveTexture" || + type == "GradientTexture" || + type == "StreamTexture" || + type == "AtlasTexture" || + type == "LargeTexture") { + Ref<Texture> texture = ResourceLoader::load(files[i]); + if (texture.is_valid() == false) { + continue; + } + } else { + continue; } can_instance = true; break; @@ -3978,41 +4434,39 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte editor_data = editor->get_scene_tree_dock()->get_editor_data(); canvas = p_canvas; preview_node = memnew(Node2D); + accept = memnew(AcceptDialog); editor->get_gui_base()->add_child(accept); selector = memnew(AcceptDialog); + editor->get_gui_base()->add_child(selector); selector->set_title(TTR("Change default type")); + selector->connect("confirmed", this, "_on_change_type"); VBoxContainer *vbc = memnew(VBoxContainer); + selector->add_child(vbc); vbc->set_h_size_flags(SIZE_EXPAND_FILL); vbc->set_v_size_flags(SIZE_EXPAND_FILL); vbc->set_custom_minimum_size(Size2(200, 260) * EDSCALE); selector_label = memnew(Label); + vbc->add_child(selector_label); selector_label->set_align(Label::ALIGN_CENTER); selector_label->set_valign(Label::VALIGN_BOTTOM); selector_label->set_custom_minimum_size(Size2(0, 30) * EDSCALE); - vbc->add_child(selector_label); - - button_group.instance(); btn_group = memnew(VBoxContainer); + vbc->add_child(btn_group); btn_group->set_h_size_flags(0); + button_group.instance(); for (int i = 0; i < types.size(); i++) { CheckBox *check = memnew(CheckBox); + btn_group->add_child(check); check->set_text(types[i]); check->connect("button_down", this, "_on_select_type", varray(check)); - btn_group->add_child(check); check->set_button_group(button_group); } - vbc->add_child(btn_group); - - selector->connect("confirmed", this, "_on_change_type"); - - selector->add_child(vbc); - editor->get_gui_base()->add_child(selector); label = memnew(Label); label->add_color_override("font_color_shadow", Color(0, 0, 0, 1)); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index f61bfc9ebb..af834507e0 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -70,7 +70,6 @@ class CanvasItemEditor : public VBoxContainer { EditorNode *editor; enum Tool { - TOOL_SELECT, TOOL_LIST_SELECT, TOOL_MOVE, @@ -82,15 +81,18 @@ class CanvasItemEditor : public VBoxContainer { enum MenuOption { SNAP_USE, - SNAP_SHOW_GRID, + SNAP_USE_NODE_PARENT, + SNAP_USE_NODE_ANCHORS, + SNAP_USE_NODE_SIDES, + SNAP_USE_OTHER_NODES, + SNAP_USE_GRID, SNAP_USE_ROTATION, SNAP_RELATIVE, SNAP_CONFIGURE, SNAP_USE_PIXEL, - ZOOM_IN, - ZOOM_OUT, - ZOOM_RESET, - ZOOM_SET, + SHOW_GRID, + SHOW_HELPERS, + SHOW_RULERS, LOCK_SELECTED, UNLOCK_SELECTED, GROUP_SELECTED, @@ -163,6 +165,8 @@ class CanvasItemEditor : public VBoxContainer { Tool tool; bool first_update; Control *viewport; + Control *viewport_base; + Control *viewport_scrollable; bool can_move_pivot; @@ -170,14 +174,28 @@ class CanvasItemEditor : public VBoxContainer { VScrollBar *v_scroll; HBoxContainer *hb; + ToolButton *zoom_minus; + ToolButton *zoom_reset; + ToolButton *zoom_plus; + Transform2D transform; + bool show_grid; + bool show_rulers; + bool show_helpers; float zoom; - Vector2 snap_offset; - Vector2 snap_step; + + Point2 grid_offset; + Point2 grid_step; + int grid_step_multiplier; + float snap_rotation_step; float snap_rotation_offset; + bool snap_active; + bool snap_node_parent; + bool snap_node_anchors; + bool snap_node_sides; + bool snap_other_nodes; bool snap_grid; - bool snap_show_grid; bool snap_rotation; bool snap_relative; bool snap_pixel; @@ -204,18 +222,6 @@ class CanvasItemEditor : public VBoxContainer { Vector<_SelectResult> selection_results; - struct LockList { - Point2 pos; - bool lock; - bool group; - LockList() { - lock = false; - group = false; - } - }; - - List<LockList> lock_list; - struct BoneList { Transform2D xform; @@ -255,6 +261,10 @@ class CanvasItemEditor : public VBoxContainer { ToolButton *move_button; ToolButton *rotate_button; + ToolButton *snap_button; + MenuButton *snap_config_menu; + PopupMenu *smartsnap_config_popup; + ToolButton *pivot_button; ToolButton *pan_button; @@ -264,8 +274,7 @@ class CanvasItemEditor : public VBoxContainer { ToolButton *group_button; ToolButton *ungroup_button; - MenuButton *edit_menu; - PopupMenu *skeleton_menu; + MenuButton *skeleton_menu; MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; @@ -278,6 +287,9 @@ class CanvasItemEditor : public VBoxContainer { PopupMenu *selection_menu; + Control *top_ruler; + Control *left_ruler; + //PopupMenu *popup; DragType drag; Point2 drag_from; @@ -290,6 +302,11 @@ class CanvasItemEditor : public VBoxContainer { Ref<Texture> select_handle; Ref<Texture> anchor_handle; + Ref<ShortCut> drag_pivot_shortcut; + Ref<ShortCut> set_pivot_shortcut; + Ref<ShortCut> multiply_grid_step_shortcut; + Ref<ShortCut> divide_grid_step_shortcut; + int handle_len; bool _is_part_of_subscene(CanvasItem *p_item); void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, Vector<_SelectResult> &r_items, int limit = 0); @@ -300,10 +317,6 @@ class CanvasItemEditor : public VBoxContainer { ConfirmationDialog *snap_dialog; - AcceptDialog *value_dialog; - Label *dialog_label; - SpinBox *dialog_val; - CanvasItem *ref_item; void _edit_set_pivot(const Vector2 &mouse_pos); @@ -317,9 +330,8 @@ class CanvasItemEditor : public VBoxContainer { void _prepare_drag(const Point2 &p_click_pos); DragType _get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point); - float _anchor_snap(float p_anchor, bool *p_snapped = NULL, float p_opposite_anchor = -1); - Vector2 _anchor_to_position(Control *p_control, Vector2 anchor); - Vector2 _position_to_anchor(Control *p_control, Vector2 position); + Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor); + Vector2 _position_to_anchor(const Control *p_control, Vector2 position); void _popup_callback(int p_op); bool updating_scroll; @@ -330,7 +342,6 @@ class CanvasItemEditor : public VBoxContainer { void incend(float &beg, float &end, float inc, float minsize, bool p_symmetric); void _append_canvas_item(CanvasItem *p_item); - void _dialog_value_changed(double); void _snap_changed(); void _selection_result_pressed(int); void _selection_menu_hide(); @@ -339,26 +350,49 @@ class CanvasItemEditor : public VBoxContainer { Point2 _find_topleftmost_point(); - void _find_canvas_items_span(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform); + void _build_bones_list(Node *p_node); + + void _get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform); Object *_get_editor_data(Object *p_what); - CanvasItem *get_single_item(); + CanvasItem *_get_single_item(); int get_item_count(); void _keying_changed(); void _unhandled_key_input(const Ref<InputEvent> &p_ev); + void _draw_text_at_position(Point2 p_position, String p_string, Margin p_side); + void _draw_margin_at_position(int p_value, Point2 p_position, Margin p_side); void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side); - void _viewport_gui_input(const Ref<InputEvent> &p_event); - void _viewport_draw(); + void _draw_rulers(); + void _draw_focus(); + void _draw_grid(); + void _draw_selection(); + void _draw_axis(); + void _draw_bones(); + void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform); + + void _draw_viewport(); + + void _viewport_base_gui_input(const Ref<InputEvent> &p_event); + void _draw_viewport_base(); void _focus_selection(int p_op); + void _snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0); + void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap); + void _set_anchors_preset(Control::LayoutPreset p_preset); void _set_full_rect(); + void _zoom_minus(); + void _zoom_reset(); + void _zoom_plus(); + + void _toggle_snap(bool p_status); + HSplitContainer *palette_split; VSplitContainer *bottom_split; @@ -402,7 +436,18 @@ protected: static CanvasItemEditor *singleton; public: - Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const; + enum SnapMode { + SNAP_GRID = 1 << 0, + SNAP_PIXEL = 1 << 1, + SNAP_NODE_PARENT = 1 << 2, + SNAP_NODE_ANCHORS = 1 << 3, + SNAP_NODE_SIDES = 1 << 4, + SNAP_OTHER_NODES = 1 << 5, + + SNAP_DEFAULT = 0x03, + }; + + Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0); float snap_angle(float p_target, float p_start = 0) const; Transform2D get_canvas_transform() const { return transform; } diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 3917c700f0..8c4e1b8f27 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -52,7 +52,7 @@ void Polygon2DEditor::_notification(int p_what) { uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons")); b_snap_grid->set_icon(get_icon("Grid", "EditorIcons")); - b_snap_enable->set_icon(get_icon("Snap", "EditorIcons")); + b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons")); uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons")); get_tree()->connect("node_removed", this, "_node_removed"); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 2c42150cee..c1b0fdb5d6 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -2566,11 +2566,18 @@ void SpatialEditorViewport::_create_preview(const Vector<String> &files) const { String path = files[i]; RES res = ResourceLoader::load(path); Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res)); - if (scene != NULL) { - if (scene.is_valid()) { - Node *instance = scene->instance(); - if (instance) { - preview_node->add_child(instance); + Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res)); + if (mesh != NULL || scene != NULL) { + if (mesh != NULL) { + MeshInstance *mesh_instance = memnew(MeshInstance); + mesh_instance->set_mesh(mesh); + preview_node->add_child(mesh_instance); + } else { + if (scene.is_valid()) { + Node *instance = scene->instance(); + if (instance) { + preview_node->add_child(instance); + } } } editor->get_scene_root()->add_child(preview_node); @@ -2606,13 +2613,29 @@ bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_s } bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) { - Ref<PackedScene> sdata = ResourceLoader::load(path); - if (!sdata.is_valid()) { // invalid scene - return false; + RES res = ResourceLoader::load(path); + + Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res)); + Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res)); + + Node *instanced_scene = NULL; + + if (mesh != NULL || scene != NULL) { + if (mesh != NULL) { + MeshInstance *mesh_instance = memnew(MeshInstance); + mesh_instance->set_mesh(mesh); + mesh_instance->set_name(mesh->get_name()); + instanced_scene = mesh_instance; + } else { + if (!scene.is_valid()) { // invalid scene + return false; + } else { + instanced_scene = scene->instance(); + } + } } - Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); - if (!instanced_scene) { // error on instancing + if (instanced_scene == NULL) { return false; } @@ -2661,7 +2684,8 @@ void SpatialEditorViewport::_perform_drop_data() { continue; } Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res)); - if (scene != NULL) { + Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res)); + if (mesh != NULL || scene != NULL) { bool success = _create_instance(target_node, path, drop_pos); if (!success) { error_files.push_back(path); @@ -2694,9 +2718,11 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian List<String> scene_extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions); + List<String> mesh_extensions; + ResourceLoader::get_recognized_extensions_for_type("Mesh", &mesh_extensions); for (int i = 0; i < files.size(); i++) { - if (scene_extensions.find(files[i].get_extension())) { + if (mesh_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) { RES res = ResourceLoader::load(files[i]); if (res.is_null()) { continue; @@ -2710,6 +2736,13 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian continue; } memdelete(instanced_scene); + } else if (type == "Mesh" || "ArrayMesh" || "PrimitiveMesh") { + Ref<Mesh> mesh = ResourceLoader::load(files[i]); + if (!mesh.is_valid()) { + continue; + } + } else { + continue; } can_instance = true; break; @@ -2854,8 +2887,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed 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_Q); - ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E); + 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); preview_camera = memnew(Button); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 5b783493cb..2fcba7e3c0 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2016,6 +2016,5 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel clear_inherit_confirm->get_ok()->set_text(TTR("Clear!")); add_child(clear_inherit_confirm); - vbc->add_constant_override("separation", 4); set_process_input(true); } diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 284b25801c..76e75cff0a 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1622,7 +1622,6 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles")); tabs->add_style_override("tab_fg", editor->get_gui_base()->get_stylebox("DebuggerTabFG", "EditorStyles")); tabs->add_style_override("tab_bg", editor->get_gui_base()->get_stylebox("DebuggerTabBG", "EditorStyles")); - tabs->set_v_size_flags(SIZE_EXPAND_FILL); tabs->set_area_as_parent_rect(); add_child(tabs); diff --git a/main/main.cpp b/main/main.cpp index bb601198db..04375666a9 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -248,7 +248,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph performance = memnew(Performance); globals->add_singleton(ProjectSettings::Singleton("Performance", performance)); - GLOBAL_DEF("debug/settings/backtrace/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues")); + GLOBAL_DEF("debug/settings/crash_handler/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues")); MAIN_PRINT("Main: Parse CMDLine"); diff --git a/main/tests/test_main.cpp b/main/tests/test_main.cpp index 645db2826e..d9b20254a8 100644 --- a/main/tests/test_main.cpp +++ b/main/tests/test_main.cpp @@ -37,6 +37,7 @@ #include "test_image.h" #include "test_io.h" #include "test_math.h" +#include "test_oa_hash_map.h" #include "test_ordered_hash_map.h" #include "test_physics.h" #include "test_physics_2d.h" @@ -56,6 +57,7 @@ const char **tests_get_names() { "io", "shaderlang", "physics", + "oa_hash_map", NULL }; @@ -89,6 +91,11 @@ MainLoop *test_main(String p_test, const List<String> &p_args) { return TestRender::test(); } + if (p_test == "oa_hash_map") { + + return TestOAHashMap::test(); + } + #ifndef _3D_DISABLED if (p_test == "gui") { diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp new file mode 100644 index 0000000000..302c259262 --- /dev/null +++ b/main/tests/test_oa_hash_map.cpp @@ -0,0 +1,97 @@ +/*************************************************************************/ +/* test_oa_hash_map.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 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 "test_oa_hash_map.h" + +#include "core/os/os.h" + +#include "core/oa_hash_map.h" + +namespace TestOAHashMap { + +MainLoop *test() { + + OS::get_singleton()->print("\n\n\nHello from test\n"); + + // test element tracking. + { + OAHashMap<int, int> map; + + map.set(42, 1337); + map.set(1337, 21); + map.set(42, 11880); + + int value; + map.lookup(42, &value); + + OS::get_singleton()->print("capacity %d\n", map.get_capacity()); + OS::get_singleton()->print("elements %d\n", map.get_num_elements()); + + OS::get_singleton()->print("map[42] = %d\n", value); + } + + // rehashing and deletion + { + OAHashMap<int, int> map; + + for (int i = 0; i < 500; i++) { + map.set(i, i * 2); + } + + for (int i = 0; i < 500; i += 2) { + map.remove(i); + } + + uint32_t num_elems = 0; + for (int i = 0; i < 500; i++) { + int tmp; + if (map.lookup(i, &tmp)) + num_elems++; + } + + OS::get_singleton()->print("elements %d == %d.\n", map.get_num_elements(), num_elems); + } + + // iteration + { + OAHashMap<String, int> map; + + map.set("Hello", 1); + map.set("World", 2); + map.set("Godot rocks", 42); + + for (OAHashMap<String, int>::Iterator it = map.iter(); it.valid; it = map.next_iter(it)) { + OS::get_singleton()->print("map[\"%s\"] = %d\n", it.key->utf8().get_data(), *it.data); + } + } + + return NULL; +} +} // namespace TestOAHashMap diff --git a/main/tests/test_oa_hash_map.h b/main/tests/test_oa_hash_map.h new file mode 100644 index 0000000000..92b4bc5e5a --- /dev/null +++ b/main/tests/test_oa_hash_map.h @@ -0,0 +1,39 @@ +/*************************************************************************/ +/* test_oa_hash_map.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 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 TEST_OA_HASH_MAP_H +#define TEST_OA_HASH_MAP_H + +#include "os/main_loop.h" + +namespace TestOAHashMap { + +MainLoop *test(); +} +#endif // TEST_OA_HASH_MAP_H diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 6da538844a..93a9bac11c 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -40,6 +40,16 @@ const String init_symbol = "godot_gdnative_init"; const String terminate_symbol = "godot_gdnative_terminate"; +#define GDAPI_FUNC(name, ret_type, ...) name, +#define GDAPI_FUNC_VOID(name, ...) name, + +const godot_gdnative_api_struct api_struct = { + GODOT_GDNATIVE_API_FUNCTIONS +}; + +#undef GDAPI_FUNC +#undef GDAPI_FUNC_VOID + String GDNativeLibrary::platform_names[NUM_PLATFORMS + 1] = { "X11_32bit", "X11_64bit", @@ -91,7 +101,7 @@ GDNativeLibrary::Platform GDNativeLibrary::current_platform = #endif GDNativeLibrary::GDNativeLibrary() - : library_paths() { + : library_paths(), singleton_gdnative(false) { } GDNativeLibrary::~GDNativeLibrary() { @@ -249,6 +259,7 @@ bool GDNative::initialize() { godot_gdnative_init_options options; + options.api_struct = &api_struct; options.in_editor = Engine::get_singleton()->is_editor_hint(); options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE); options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index 4753c7efe5..29c6201641 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -36,6 +36,7 @@ #include "resource.h" #include "gdnative/gdnative.h" +#include "gdnative_api_struct.h" class GDNativeLibrary : public Resource { GDCLASS(GDNativeLibrary, Resource) @@ -77,7 +78,7 @@ class GDNativeLibrary : public Resource { String library_paths[NUM_PLATFORMS]; - bool singleton_gdnative = false; + bool singleton_gdnative; protected: bool _set(const StringName &p_name, const Variant &p_value); diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp index 1b2aae607f..9ba4166c1d 100644 --- a/modules/gdnative/gdnative/variant.cpp +++ b/modules/gdnative/gdnative/variant.cpp @@ -480,10 +480,9 @@ godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const g return self->hash_compare(*other); } -godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid) { +godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self) { const Variant *self = (const Variant *)p_self; - bool &valid = *r_valid; - return self->booleanize(valid); + return self->booleanize(); } void GDAPI godot_variant_destroy(godot_variant *p_self) { diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h index c574c56d5a..1c5e91d733 100644 --- a/modules/gdnative/include/gdnative/gdnative.h +++ b/modules/gdnative/include/gdnative/gdnative.h @@ -234,12 +234,15 @@ void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_obj godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error); ////// Script API +struct godot_gdnative_api_struct; // Forward declaration + typedef struct { godot_bool in_editor; uint64_t core_api_hash; uint64_t editor_api_hash; uint64_t no_api_hash; godot_object *gd_native_library; // pointer to GDNativeLibrary that is being initialized + const struct godot_gdnative_api_struct *api_struct; } godot_gdnative_init_options; typedef struct { diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h index 969506585d..7b804c1eaf 100644 --- a/modules/gdnative/include/gdnative/variant.h +++ b/modules/gdnative/include/gdnative/variant.h @@ -190,7 +190,7 @@ godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other); -godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid); +godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self); void GDAPI godot_variant_destroy(godot_variant *p_self); diff --git a/modules/gdnative/include/gdnative_api_struct.h b/modules/gdnative/include/gdnative_api_struct.h new file mode 100644 index 0000000000..c345e27227 --- /dev/null +++ b/modules/gdnative/include/gdnative_api_struct.h @@ -0,0 +1,723 @@ +/*************************************************************************/ +/* gdnative_api_struct.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 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 GODOT_GDNATIVE_API_STRUCT_H +#define GODOT_GDNATIVE_API_STRUCT_H + +#include <gdnative/gdnative.h> +#include <nativescript/godot_nativescript.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Using X_MACRO to keep api function signatures in a single list +#define GODOT_GDNATIVE_API_FUNCTIONS \ + GDAPI_FUNC_VOID(godot_color_new_rgba, godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a) \ + GDAPI_FUNC_VOID(godot_color_new_rgb, godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b) \ + GDAPI_FUNC(godot_color_get_r, godot_real, const godot_color *p_self) \ + GDAPI_FUNC_VOID(godot_color_set_r, godot_color *p_self, const godot_real r) \ + GDAPI_FUNC(godot_color_get_g, godot_real, const godot_color *p_self) \ + GDAPI_FUNC_VOID(godot_color_set_g, godot_color *p_self, const godot_real g) \ + GDAPI_FUNC(godot_color_get_b, godot_real, const godot_color *p_self) \ + GDAPI_FUNC_VOID(godot_color_set_b, godot_color *p_self, const godot_real b) \ + GDAPI_FUNC(godot_color_get_a, godot_real, const godot_color *p_self) \ + GDAPI_FUNC_VOID(godot_color_set_a, godot_color *p_self, const godot_real a) \ + GDAPI_FUNC(godot_color_get_h, godot_real, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_get_s, godot_real, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_get_v, godot_real, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_as_string, godot_string, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_to_rgba32, godot_int, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_to_argb32, godot_int, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_gray, godot_real, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_inverted, godot_color, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_contrasted, godot_color, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_linear_interpolate, godot_color, const godot_color *p_self, const godot_color *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_color_blend, godot_color, const godot_color *p_self, const godot_color *p_over) \ + GDAPI_FUNC(godot_color_to_html, godot_string, const godot_color *p_self, const godot_bool p_with_alpha) \ + GDAPI_FUNC(godot_color_operator_equal, godot_bool, const godot_color *p_self, const godot_color *p_b) \ + GDAPI_FUNC(godot_color_operator_less, godot_bool, const godot_color *p_self, const godot_color *p_b) \ + GDAPI_FUNC_VOID(godot_vector2_new, godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y) \ + GDAPI_FUNC(godot_vector2_as_string, godot_string, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_normalized, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_length, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_angle, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_length_squared, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_is_normalized, godot_bool, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_distance_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_vector2_distance_squared_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_vector2_angle_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_vector2_angle_to_point, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_vector2_linear_interpolate, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_vector2_cubic_interpolate, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_vector2 *p_pre_a, const godot_vector2 *p_post_b, const godot_real p_t) \ + GDAPI_FUNC(godot_vector2_rotated, godot_vector2, const godot_vector2 *p_self, const godot_real p_phi) \ + GDAPI_FUNC(godot_vector2_tangent, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_floor, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_snapped, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_by) \ + GDAPI_FUNC(godot_vector2_aspect, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_dot, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_with) \ + GDAPI_FUNC(godot_vector2_slide, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \ + GDAPI_FUNC(godot_vector2_bounce, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \ + GDAPI_FUNC(godot_vector2_reflect, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \ + GDAPI_FUNC(godot_vector2_abs, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_clamped, godot_vector2, const godot_vector2 *p_self, const godot_real p_length) \ + GDAPI_FUNC(godot_vector2_operator_add, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_substract, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_multiply_vector, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_multiply_scalar, godot_vector2, const godot_vector2 *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_vector2_operator_divide_vector, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_divide_scalar, godot_vector2, const godot_vector2 *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_vector2_operator_equal, godot_bool, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_less, godot_bool, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_neg, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC_VOID(godot_vector2_set_x, godot_vector2 *p_self, const godot_real p_x) \ + GDAPI_FUNC_VOID(godot_vector2_set_y, godot_vector2 *p_self, const godot_real p_y) \ + GDAPI_FUNC(godot_vector2_get_x, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_get_y, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC_VOID(godot_quat_new, godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w) \ + GDAPI_FUNC_VOID(godot_quat_new_with_axis_angle, godot_quat *r_dest, const godot_vector3 *p_axis, const godot_real p_angle) \ + GDAPI_FUNC(godot_quat_get_x, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_quat_set_x, godot_quat *p_self, const godot_real val) \ + GDAPI_FUNC(godot_quat_get_y, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_quat_set_y, godot_quat *p_self, const godot_real val) \ + GDAPI_FUNC(godot_quat_get_z, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_quat_set_z, godot_quat *p_self, const godot_real val) \ + GDAPI_FUNC(godot_quat_get_w, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_quat_set_w, godot_quat *p_self, const godot_real val) \ + GDAPI_FUNC(godot_quat_as_string, godot_string, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_length, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_length_squared, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_normalized, godot_quat, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_is_normalized, godot_bool, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_inverse, godot_quat, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_dot, godot_real, const godot_quat *p_self, const godot_quat *p_b) \ + GDAPI_FUNC(godot_quat_xform, godot_vector3, const godot_quat *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_quat_slerp, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_quat_slerpni, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_quat_cubic_slerp, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_quat *p_pre_a, const godot_quat *p_post_b, const godot_real p_t) \ + GDAPI_FUNC(godot_quat_operator_multiply, godot_quat, const godot_quat *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_quat_operator_add, godot_quat, const godot_quat *p_self, const godot_quat *p_b) \ + GDAPI_FUNC(godot_quat_operator_substract, godot_quat, const godot_quat *p_self, const godot_quat *p_b) \ + GDAPI_FUNC(godot_quat_operator_divide, godot_quat, const godot_quat *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_quat_operator_equal, godot_bool, const godot_quat *p_self, const godot_quat *p_b) \ + GDAPI_FUNC(godot_quat_operator_neg, godot_quat, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_basis_new_with_rows, godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis) \ + GDAPI_FUNC_VOID(godot_basis_new_with_axis_and_angle, godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi) \ + GDAPI_FUNC_VOID(godot_basis_new_with_euler, godot_basis *r_dest, const godot_vector3 *p_euler) \ + GDAPI_FUNC(godot_basis_as_string, godot_string, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_inverse, godot_basis, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_transposed, godot_basis, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_orthonormalized, godot_basis, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_determinant, godot_real, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_rotated, godot_basis, const godot_basis *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \ + GDAPI_FUNC(godot_basis_scaled, godot_basis, const godot_basis *p_self, const godot_vector3 *p_scale) \ + GDAPI_FUNC(godot_basis_get_scale, godot_vector3, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_get_euler, godot_vector3, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_tdotx, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \ + GDAPI_FUNC(godot_basis_tdoty, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \ + GDAPI_FUNC(godot_basis_tdotz, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \ + GDAPI_FUNC(godot_basis_xform, godot_vector3, const godot_basis *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_basis_xform_inv, godot_vector3, const godot_basis *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_basis_get_orthogonal_index, godot_int, const godot_basis *p_self) \ + GDAPI_FUNC_VOID(godot_basis_new, godot_basis *r_dest) \ + GDAPI_FUNC_VOID(godot_basis_new_with_euler_quat, godot_basis *r_dest, const godot_quat *p_euler) \ + GDAPI_FUNC_VOID(godot_basis_get_elements, godot_basis *p_self, godot_vector3 *p_elements) \ + GDAPI_FUNC(godot_basis_get_axis, godot_vector3, const godot_basis *p_self, const godot_int p_axis) \ + GDAPI_FUNC_VOID(godot_basis_set_axis, godot_basis *p_self, const godot_int p_axis, const godot_vector3 *p_value) \ + GDAPI_FUNC(godot_basis_get_row, godot_vector3, const godot_basis *p_self, const godot_int p_row) \ + GDAPI_FUNC_VOID(godot_basis_set_row, godot_basis *p_self, const godot_int p_row, const godot_vector3 *p_value) \ + GDAPI_FUNC(godot_basis_operator_equal, godot_bool, const godot_basis *p_self, const godot_basis *p_b) \ + GDAPI_FUNC(godot_basis_operator_add, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \ + GDAPI_FUNC(godot_basis_operator_substract, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \ + GDAPI_FUNC(godot_basis_operator_multiply_vector, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \ + GDAPI_FUNC(godot_basis_operator_multiply_scalar, godot_basis, const godot_basis *p_self, const godot_real p_b) \ + GDAPI_FUNC_VOID(godot_vector3_new, godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z) \ + GDAPI_FUNC(godot_vector3_as_string, godot_string, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_min_axis, godot_int, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_max_axis, godot_int, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_length, godot_real, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_length_squared, godot_real, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_is_normalized, godot_bool, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_normalized, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_inverse, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_snapped, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_by) \ + GDAPI_FUNC(godot_vector3_rotated, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \ + GDAPI_FUNC(godot_vector3_linear_interpolate, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_vector3_cubic_interpolate, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_vector3 *p_pre_a, const godot_vector3 *p_post_b, const godot_real p_t) \ + GDAPI_FUNC(godot_vector3_dot, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_cross, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_outer, godot_basis, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_to_diagonal_matrix, godot_basis, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_abs, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_floor, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_ceil, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_distance_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_distance_squared_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_angle_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_to) \ + GDAPI_FUNC(godot_vector3_slide, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \ + GDAPI_FUNC(godot_vector3_bounce, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \ + GDAPI_FUNC(godot_vector3_reflect, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \ + GDAPI_FUNC(godot_vector3_operator_add, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_substract, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_multiply_vector, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_multiply_scalar, godot_vector3, const godot_vector3 *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_vector3_operator_divide_vector, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_divide_scalar, godot_vector3, const godot_vector3 *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_vector3_operator_equal, godot_bool, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_less, godot_bool, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_neg, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC_VOID(godot_vector3_set_axis, godot_vector3 *p_self, const godot_vector3_axis p_axis, const godot_real p_val) \ + GDAPI_FUNC(godot_vector3_get_axis, godot_real, const godot_vector3 *p_self, const godot_vector3_axis p_axis) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_new, godot_pool_byte_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_new_copy, godot_pool_byte_array *r_dest, const godot_pool_byte_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_new_with_array, godot_pool_byte_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_append, godot_pool_byte_array *p_self, const uint8_t p_data) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_append_array, godot_pool_byte_array *p_self, const godot_pool_byte_array *p_array) \ + GDAPI_FUNC(godot_pool_byte_array_insert, godot_error, godot_pool_byte_array *p_self, const godot_int p_idx, const uint8_t p_data) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_invert, godot_pool_byte_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_push_back, godot_pool_byte_array *p_self, const uint8_t p_data) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_remove, godot_pool_byte_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_resize, godot_pool_byte_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_set, godot_pool_byte_array *p_self, const godot_int p_idx, const uint8_t p_data) \ + GDAPI_FUNC(godot_pool_byte_array_get, uint8_t, const godot_pool_byte_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_byte_array_size, godot_int, const godot_pool_byte_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_destroy, godot_pool_byte_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_int_array_new, godot_pool_int_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_int_array_new_copy, godot_pool_int_array *r_dest, const godot_pool_int_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_int_array_new_with_array, godot_pool_int_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_int_array_append, godot_pool_int_array *p_self, const godot_int p_data) \ + GDAPI_FUNC_VOID(godot_pool_int_array_append_array, godot_pool_int_array *p_self, const godot_pool_int_array *p_array) \ + GDAPI_FUNC(godot_pool_int_array_insert, godot_error, godot_pool_int_array *p_self, const godot_int p_idx, const godot_int p_data) \ + GDAPI_FUNC_VOID(godot_pool_int_array_invert, godot_pool_int_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_int_array_push_back, godot_pool_int_array *p_self, const godot_int p_data) \ + GDAPI_FUNC_VOID(godot_pool_int_array_remove, godot_pool_int_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_int_array_resize, godot_pool_int_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_int_array_set, godot_pool_int_array *p_self, const godot_int p_idx, const godot_int p_data) \ + GDAPI_FUNC(godot_pool_int_array_get, godot_int, const godot_pool_int_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_int_array_size, godot_int, const godot_pool_int_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_int_array_destroy, godot_pool_int_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_real_array_new, godot_pool_real_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_real_array_new_copy, godot_pool_real_array *r_dest, const godot_pool_real_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_real_array_new_with_array, godot_pool_real_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_real_array_append, godot_pool_real_array *p_self, const godot_real p_data) \ + GDAPI_FUNC_VOID(godot_pool_real_array_append_array, godot_pool_real_array *p_self, const godot_pool_real_array *p_array) \ + GDAPI_FUNC(godot_pool_real_array_insert, godot_error, godot_pool_real_array *p_self, const godot_int p_idx, const godot_real p_data) \ + GDAPI_FUNC_VOID(godot_pool_real_array_invert, godot_pool_real_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_real_array_push_back, godot_pool_real_array *p_self, const godot_real p_data) \ + GDAPI_FUNC_VOID(godot_pool_real_array_remove, godot_pool_real_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_real_array_resize, godot_pool_real_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_real_array_set, godot_pool_real_array *p_self, const godot_int p_idx, const godot_real p_data) \ + GDAPI_FUNC(godot_pool_real_array_get, godot_real, const godot_pool_real_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_real_array_size, godot_int, const godot_pool_real_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_real_array_destroy, godot_pool_real_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_string_array_new, godot_pool_string_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_string_array_new_copy, godot_pool_string_array *r_dest, const godot_pool_string_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_string_array_new_with_array, godot_pool_string_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_string_array_append, godot_pool_string_array *p_self, const godot_string *p_data) \ + GDAPI_FUNC_VOID(godot_pool_string_array_append_array, godot_pool_string_array *p_self, const godot_pool_string_array *p_array) \ + GDAPI_FUNC(godot_pool_string_array_insert, godot_error, godot_pool_string_array *p_self, const godot_int p_idx, const godot_string *p_data) \ + GDAPI_FUNC_VOID(godot_pool_string_array_invert, godot_pool_string_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_string_array_push_back, godot_pool_string_array *p_self, const godot_string *p_data) \ + GDAPI_FUNC_VOID(godot_pool_string_array_remove, godot_pool_string_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_string_array_resize, godot_pool_string_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_string_array_set, godot_pool_string_array *p_self, const godot_int p_idx, const godot_string *p_data) \ + GDAPI_FUNC(godot_pool_string_array_get, godot_string, const godot_pool_string_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_string_array_size, godot_int, const godot_pool_string_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_string_array_destroy, godot_pool_string_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_new, godot_pool_vector2_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_new_copy, godot_pool_vector2_array *r_dest, const godot_pool_vector2_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_new_with_array, godot_pool_vector2_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_append, godot_pool_vector2_array *p_self, const godot_vector2 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_append_array, godot_pool_vector2_array *p_self, const godot_pool_vector2_array *p_array) \ + GDAPI_FUNC(godot_pool_vector2_array_insert, godot_error, godot_pool_vector2_array *p_self, const godot_int p_idx, const godot_vector2 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_invert, godot_pool_vector2_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_push_back, godot_pool_vector2_array *p_self, const godot_vector2 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_remove, godot_pool_vector2_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_resize, godot_pool_vector2_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_set, godot_pool_vector2_array *p_self, const godot_int p_idx, const godot_vector2 *p_data) \ + GDAPI_FUNC(godot_pool_vector2_array_get, godot_vector2, const godot_pool_vector2_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_vector2_array_size, godot_int, const godot_pool_vector2_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_destroy, godot_pool_vector2_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_new, godot_pool_vector3_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_new_copy, godot_pool_vector3_array *r_dest, const godot_pool_vector3_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_new_with_array, godot_pool_vector3_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_append, godot_pool_vector3_array *p_self, const godot_vector3 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_append_array, godot_pool_vector3_array *p_self, const godot_pool_vector3_array *p_array) \ + GDAPI_FUNC(godot_pool_vector3_array_insert, godot_error, godot_pool_vector3_array *p_self, const godot_int p_idx, const godot_vector3 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_invert, godot_pool_vector3_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_push_back, godot_pool_vector3_array *p_self, const godot_vector3 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_remove, godot_pool_vector3_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_resize, godot_pool_vector3_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_set, godot_pool_vector3_array *p_self, const godot_int p_idx, const godot_vector3 *p_data) \ + GDAPI_FUNC(godot_pool_vector3_array_get, godot_vector3, const godot_pool_vector3_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_vector3_array_size, godot_int, const godot_pool_vector3_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_destroy, godot_pool_vector3_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_color_array_new, godot_pool_color_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_color_array_new_copy, godot_pool_color_array *r_dest, const godot_pool_color_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_color_array_new_with_array, godot_pool_color_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_color_array_append, godot_pool_color_array *p_self, const godot_color *p_data) \ + GDAPI_FUNC_VOID(godot_pool_color_array_append_array, godot_pool_color_array *p_self, const godot_pool_color_array *p_array) \ + GDAPI_FUNC(godot_pool_color_array_insert, godot_error, godot_pool_color_array *p_self, const godot_int p_idx, const godot_color *p_data) \ + GDAPI_FUNC_VOID(godot_pool_color_array_invert, godot_pool_color_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_color_array_push_back, godot_pool_color_array *p_self, const godot_color *p_data) \ + GDAPI_FUNC_VOID(godot_pool_color_array_remove, godot_pool_color_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_color_array_resize, godot_pool_color_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_color_array_set, godot_pool_color_array *p_self, const godot_int p_idx, const godot_color *p_data) \ + GDAPI_FUNC(godot_pool_color_array_get, godot_color, const godot_pool_color_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_color_array_size, godot_int, const godot_pool_color_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_color_array_destroy, godot_pool_color_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_new, godot_array *r_dest) \ + GDAPI_FUNC_VOID(godot_array_new_copy, godot_array *r_dest, const godot_array *p_src) \ + GDAPI_FUNC_VOID(godot_array_new_pool_color_array, godot_array *r_dest, const godot_pool_color_array *p_pca) \ + GDAPI_FUNC_VOID(godot_array_new_pool_vector3_array, godot_array *r_dest, const godot_pool_vector3_array *p_pv3a) \ + GDAPI_FUNC_VOID(godot_array_new_pool_vector2_array, godot_array *r_dest, const godot_pool_vector2_array *p_pv2a) \ + GDAPI_FUNC_VOID(godot_array_new_pool_string_array, godot_array *r_dest, const godot_pool_string_array *p_psa) \ + GDAPI_FUNC_VOID(godot_array_new_pool_real_array, godot_array *r_dest, const godot_pool_real_array *p_pra) \ + GDAPI_FUNC_VOID(godot_array_new_pool_int_array, godot_array *r_dest, const godot_pool_int_array *p_pia) \ + GDAPI_FUNC_VOID(godot_array_new_pool_byte_array, godot_array *r_dest, const godot_pool_byte_array *p_pba) \ + GDAPI_FUNC_VOID(godot_array_set, godot_array *p_self, const godot_int p_idx, const godot_variant *p_value) \ + GDAPI_FUNC(godot_array_get, godot_variant, const godot_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_array_operator_index, godot_variant *, godot_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_array_append, godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC_VOID(godot_array_clear, godot_array *p_self) \ + GDAPI_FUNC(godot_array_count, godot_int, const godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC(godot_array_empty, godot_bool, const godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_erase, godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC(godot_array_front, godot_variant, const godot_array *p_self) \ + GDAPI_FUNC(godot_array_back, godot_variant, const godot_array *p_self) \ + GDAPI_FUNC(godot_array_find, godot_int, const godot_array *p_self, const godot_variant *p_what, const godot_int p_from) \ + GDAPI_FUNC(godot_array_find_last, godot_int, const godot_array *p_self, const godot_variant *p_what) \ + GDAPI_FUNC(godot_array_has, godot_bool, const godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC(godot_array_hash, godot_int, const godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_insert, godot_array *p_self, const godot_int p_pos, const godot_variant *p_value) \ + GDAPI_FUNC_VOID(godot_array_invert, godot_array *p_self) \ + GDAPI_FUNC(godot_array_pop_back, godot_variant, godot_array *p_self) \ + GDAPI_FUNC(godot_array_pop_front, godot_variant, godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_push_back, godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC_VOID(godot_array_push_front, godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC_VOID(godot_array_remove, godot_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_array_resize, godot_array *p_self, const godot_int p_size) \ + GDAPI_FUNC(godot_array_rfind, godot_int, const godot_array *p_self, const godot_variant *p_what, const godot_int p_from) \ + GDAPI_FUNC(godot_array_size, godot_int, const godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_sort, godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_sort_custom, godot_array *p_self, godot_object *p_obj, const godot_string *p_func) \ + GDAPI_FUNC_VOID(godot_array_destroy, godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_dictionary_new, godot_dictionary *r_dest) \ + GDAPI_FUNC_VOID(godot_dictionary_new_copy, godot_dictionary *r_dest, const godot_dictionary *p_src) \ + GDAPI_FUNC_VOID(godot_dictionary_destroy, godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_size, godot_int, const godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_empty, godot_bool, const godot_dictionary *p_self) \ + GDAPI_FUNC_VOID(godot_dictionary_clear, godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_has, godot_bool, const godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC(godot_dictionary_has_all, godot_bool, const godot_dictionary *p_self, const godot_array *p_keys) \ + GDAPI_FUNC_VOID(godot_dictionary_erase, godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC(godot_dictionary_hash, godot_int, const godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_keys, godot_array, const godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_values, godot_array, const godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_get, godot_variant, const godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC_VOID(godot_dictionary_set, godot_dictionary *p_self, const godot_variant *p_key, const godot_variant *p_value) \ + GDAPI_FUNC(godot_dictionary_operator_index, godot_variant *, godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC(godot_dictionary_next, godot_variant *, const godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC(godot_dictionary_operator_equal, godot_bool, const godot_dictionary *p_self, const godot_dictionary *p_b) \ + GDAPI_FUNC(godot_dictionary_to_json, godot_string, const godot_dictionary *p_self) \ + GDAPI_FUNC_VOID(godot_node_path_new, godot_node_path *r_dest, const godot_string *p_from) \ + GDAPI_FUNC_VOID(godot_node_path_new_copy, godot_node_path *r_dest, const godot_node_path *p_src) \ + GDAPI_FUNC_VOID(godot_node_path_destroy, godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_as_string, godot_string, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_is_absolute, godot_bool, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_get_name_count, godot_int, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_get_name, godot_string, const godot_node_path *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_node_path_get_subname_count, godot_int, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_get_subname, godot_string, const godot_node_path *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_node_path_get_property, godot_string, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_is_empty, godot_bool, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_operator_equal, godot_bool, const godot_node_path *p_self, const godot_node_path *p_b) \ + GDAPI_FUNC_VOID(godot_plane_new_with_reals, godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d) \ + GDAPI_FUNC_VOID(godot_plane_new_with_vectors, godot_plane *r_dest, const godot_vector3 *p_v1, const godot_vector3 *p_v2, const godot_vector3 *p_v3) \ + GDAPI_FUNC_VOID(godot_plane_new_with_normal, godot_plane *r_dest, const godot_vector3 *p_normal, const godot_real p_d) \ + GDAPI_FUNC(godot_plane_as_string, godot_string, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_normalized, godot_plane, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_center, godot_vector3, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_get_any_point, godot_vector3, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_is_point_over, godot_bool, const godot_plane *p_self, const godot_vector3 *p_point) \ + GDAPI_FUNC(godot_plane_distance_to, godot_real, const godot_plane *p_self, const godot_vector3 *p_point) \ + GDAPI_FUNC(godot_plane_has_point, godot_bool, const godot_plane *p_self, const godot_vector3 *p_point, const godot_real p_epsilon) \ + GDAPI_FUNC(godot_plane_project, godot_vector3, const godot_plane *p_self, const godot_vector3 *p_point) \ + GDAPI_FUNC(godot_plane_intersect_3, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_plane *p_b, const godot_plane *p_c) \ + GDAPI_FUNC(godot_plane_intersects_ray, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_vector3 *p_from, const godot_vector3 *p_dir) \ + GDAPI_FUNC(godot_plane_intersects_segment, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_vector3 *p_begin, const godot_vector3 *p_end) \ + GDAPI_FUNC(godot_plane_operator_neg, godot_plane, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_operator_equal, godot_bool, const godot_plane *p_self, const godot_plane *p_b) \ + GDAPI_FUNC_VOID(godot_plane_set_normal, godot_plane *p_self, const godot_vector3 *p_normal) \ + GDAPI_FUNC(godot_plane_get_normal, godot_vector3, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_get_d, godot_real, const godot_plane *p_self) \ + GDAPI_FUNC_VOID(godot_plane_set_d, godot_plane *p_self, const godot_real p_d) \ + GDAPI_FUNC_VOID(godot_rect2_new_with_position_and_size, godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size) \ + GDAPI_FUNC_VOID(godot_rect2_new, godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height) \ + GDAPI_FUNC(godot_rect2_as_string, godot_string, const godot_rect2 *p_self) \ + GDAPI_FUNC(godot_rect2_get_area, godot_real, const godot_rect2 *p_self) \ + GDAPI_FUNC(godot_rect2_intersects, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_encloses, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_has_no_area, godot_bool, const godot_rect2 *p_self) \ + GDAPI_FUNC(godot_rect2_clip, godot_rect2, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_merge, godot_rect2, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_has_point, godot_bool, const godot_rect2 *p_self, const godot_vector2 *p_point) \ + GDAPI_FUNC(godot_rect2_grow, godot_rect2, const godot_rect2 *p_self, const godot_real p_by) \ + GDAPI_FUNC(godot_rect2_expand, godot_rect2, const godot_rect2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_rect2_operator_equal, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_get_position, godot_vector2, const godot_rect2 *p_self) \ + GDAPI_FUNC(godot_rect2_get_size, godot_vector2, const godot_rect2 *p_self) \ + GDAPI_FUNC_VOID(godot_rect2_set_position, godot_rect2 *p_self, const godot_vector2 *p_pos) \ + GDAPI_FUNC_VOID(godot_rect2_set_size, godot_rect2 *p_self, const godot_vector2 *p_size) \ + GDAPI_FUNC_VOID(godot_rect3_new, godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size) \ + GDAPI_FUNC(godot_rect3_get_position, godot_vector3, const godot_rect3 *p_self) \ + GDAPI_FUNC_VOID(godot_rect3_set_position, const godot_rect3 *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_rect3_get_size, godot_vector3, const godot_rect3 *p_self) \ + GDAPI_FUNC_VOID(godot_rect3_set_size, const godot_rect3 *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_rect3_as_string, godot_string, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_area, godot_real, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_has_no_area, godot_bool, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_has_no_surface, godot_bool, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_intersects, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_with) \ + GDAPI_FUNC(godot_rect3_encloses, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_with) \ + GDAPI_FUNC(godot_rect3_merge, godot_rect3, const godot_rect3 *p_self, const godot_rect3 *p_with) \ + GDAPI_FUNC(godot_rect3_intersection, godot_rect3, const godot_rect3 *p_self, const godot_rect3 *p_with) \ + GDAPI_FUNC(godot_rect3_intersects_plane, godot_bool, const godot_rect3 *p_self, const godot_plane *p_plane) \ + GDAPI_FUNC(godot_rect3_intersects_segment, godot_bool, const godot_rect3 *p_self, const godot_vector3 *p_from, const godot_vector3 *p_to) \ + GDAPI_FUNC(godot_rect3_has_point, godot_bool, const godot_rect3 *p_self, const godot_vector3 *p_point) \ + GDAPI_FUNC(godot_rect3_get_support, godot_vector3, const godot_rect3 *p_self, const godot_vector3 *p_dir) \ + GDAPI_FUNC(godot_rect3_get_longest_axis, godot_vector3, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_longest_axis_index, godot_int, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_longest_axis_size, godot_real, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_shortest_axis, godot_vector3, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_shortest_axis_index, godot_int, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_shortest_axis_size, godot_real, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_expand, godot_rect3, const godot_rect3 *p_self, const godot_vector3 *p_to_point) \ + GDAPI_FUNC(godot_rect3_grow, godot_rect3, const godot_rect3 *p_self, const godot_real p_by) \ + GDAPI_FUNC(godot_rect3_get_endpoint, godot_vector3, const godot_rect3 *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_rect3_operator_equal, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_b) \ + GDAPI_FUNC_VOID(godot_rid_new, godot_rid *r_dest) \ + GDAPI_FUNC(godot_rid_get_id, godot_int, const godot_rid *p_self) \ + GDAPI_FUNC_VOID(godot_rid_new_with_resource, godot_rid *r_dest, const godot_object *p_from) \ + GDAPI_FUNC(godot_rid_operator_equal, godot_bool, const godot_rid *p_self, const godot_rid *p_b) \ + GDAPI_FUNC(godot_rid_operator_less, godot_bool, const godot_rid *p_self, const godot_rid *p_b) \ + GDAPI_FUNC_VOID(godot_transform_new_with_axis_origin, godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin) \ + GDAPI_FUNC_VOID(godot_transform_new, godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin) \ + GDAPI_FUNC(godot_transform_get_basis, godot_basis, const godot_transform *p_self) \ + GDAPI_FUNC_VOID(godot_transform_set_basis, godot_transform *p_self, godot_basis *p_v) \ + GDAPI_FUNC(godot_transform_get_origin, godot_vector3, const godot_transform *p_self) \ + GDAPI_FUNC_VOID(godot_transform_set_origin, godot_transform *p_self, godot_vector3 *p_v) \ + GDAPI_FUNC(godot_transform_as_string, godot_string, const godot_transform *p_self) \ + GDAPI_FUNC(godot_transform_inverse, godot_transform, const godot_transform *p_self) \ + GDAPI_FUNC(godot_transform_affine_inverse, godot_transform, const godot_transform *p_self) \ + GDAPI_FUNC(godot_transform_orthonormalized, godot_transform, const godot_transform *p_self) \ + GDAPI_FUNC(godot_transform_rotated, godot_transform, const godot_transform *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \ + GDAPI_FUNC(godot_transform_scaled, godot_transform, const godot_transform *p_self, const godot_vector3 *p_scale) \ + GDAPI_FUNC(godot_transform_translated, godot_transform, const godot_transform *p_self, const godot_vector3 *p_ofs) \ + GDAPI_FUNC(godot_transform_looking_at, godot_transform, const godot_transform *p_self, const godot_vector3 *p_target, const godot_vector3 *p_up) \ + GDAPI_FUNC(godot_transform_xform_plane, godot_plane, const godot_transform *p_self, const godot_plane *p_v) \ + GDAPI_FUNC(godot_transform_xform_inv_plane, godot_plane, const godot_transform *p_self, const godot_plane *p_v) \ + GDAPI_FUNC_VOID(godot_transform_new_identity, godot_transform *r_dest) \ + GDAPI_FUNC(godot_transform_operator_equal, godot_bool, const godot_transform *p_self, const godot_transform *p_b) \ + GDAPI_FUNC(godot_transform_operator_multiply, godot_transform, const godot_transform *p_self, const godot_transform *p_b) \ + GDAPI_FUNC(godot_transform_xform_vector3, godot_vector3, const godot_transform *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_transform_xform_inv_vector3, godot_vector3, const godot_transform *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_transform_xform_rect3, godot_rect3, const godot_transform *p_self, const godot_rect3 *p_v) \ + GDAPI_FUNC(godot_transform_xform_inv_rect3, godot_rect3, const godot_transform *p_self, const godot_rect3 *p_v) \ + GDAPI_FUNC_VOID(godot_transform2d_new, godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos) \ + GDAPI_FUNC_VOID(godot_transform2d_new_axis_origin, godot_transform2d *r_dest, const godot_vector2 *p_x_axis, const godot_vector2 *p_y_axis, const godot_vector2 *p_origin) \ + GDAPI_FUNC(godot_transform2d_as_string, godot_string, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_inverse, godot_transform2d, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_affine_inverse, godot_transform2d, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_get_rotation, godot_real, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_get_origin, godot_vector2, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_get_scale, godot_vector2, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_orthonormalized, godot_transform2d, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_rotated, godot_transform2d, const godot_transform2d *p_self, const godot_real p_phi) \ + GDAPI_FUNC(godot_transform2d_scaled, godot_transform2d, const godot_transform2d *p_self, const godot_vector2 *p_scale) \ + GDAPI_FUNC(godot_transform2d_translated, godot_transform2d, const godot_transform2d *p_self, const godot_vector2 *p_offset) \ + GDAPI_FUNC(godot_transform2d_xform_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \ + GDAPI_FUNC(godot_transform2d_xform_inv_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \ + GDAPI_FUNC(godot_transform2d_basis_xform_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \ + GDAPI_FUNC(godot_transform2d_basis_xform_inv_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \ + GDAPI_FUNC(godot_transform2d_interpolate_with, godot_transform2d, const godot_transform2d *p_self, const godot_transform2d *p_m, const godot_real p_c) \ + GDAPI_FUNC(godot_transform2d_operator_equal, godot_bool, const godot_transform2d *p_self, const godot_transform2d *p_b) \ + GDAPI_FUNC(godot_transform2d_operator_multiply, godot_transform2d, const godot_transform2d *p_self, const godot_transform2d *p_b) \ + GDAPI_FUNC_VOID(godot_transform2d_new_identity, godot_transform2d *r_dest) \ + GDAPI_FUNC(godot_transform2d_xform_rect2, godot_rect2, const godot_transform2d *p_self, const godot_rect2 *p_v) \ + GDAPI_FUNC(godot_transform2d_xform_inv_rect2, godot_rect2, const godot_transform2d *p_self, const godot_rect2 *p_v) \ + GDAPI_FUNC(godot_variant_get_type, godot_variant_type, const godot_variant *p_v) \ + GDAPI_FUNC_VOID(godot_variant_new_copy, godot_variant *r_dest, const godot_variant *p_src) \ + GDAPI_FUNC_VOID(godot_variant_new_nil, godot_variant *r_dest) \ + GDAPI_FUNC_VOID(godot_variant_new_bool, godot_variant *p_v, const godot_bool p_b) \ + GDAPI_FUNC_VOID(godot_variant_new_uint, godot_variant *r_dest, const uint64_t p_i) \ + GDAPI_FUNC_VOID(godot_variant_new_int, godot_variant *r_dest, const int64_t p_i) \ + GDAPI_FUNC_VOID(godot_variant_new_real, godot_variant *r_dest, const double p_r) \ + GDAPI_FUNC_VOID(godot_variant_new_string, godot_variant *r_dest, const godot_string *p_s) \ + GDAPI_FUNC_VOID(godot_variant_new_vector2, godot_variant *r_dest, const godot_vector2 *p_v2) \ + GDAPI_FUNC_VOID(godot_variant_new_rect2, godot_variant *r_dest, const godot_rect2 *p_rect2) \ + GDAPI_FUNC_VOID(godot_variant_new_vector3, godot_variant *r_dest, const godot_vector3 *p_v3) \ + GDAPI_FUNC_VOID(godot_variant_new_transform2d, godot_variant *r_dest, const godot_transform2d *p_t2d) \ + GDAPI_FUNC_VOID(godot_variant_new_plane, godot_variant *r_dest, const godot_plane *p_plane) \ + GDAPI_FUNC_VOID(godot_variant_new_quat, godot_variant *r_dest, const godot_quat *p_quat) \ + GDAPI_FUNC_VOID(godot_variant_new_rect3, godot_variant *r_dest, const godot_rect3 *p_rect3) \ + GDAPI_FUNC_VOID(godot_variant_new_basis, godot_variant *r_dest, const godot_basis *p_basis) \ + GDAPI_FUNC_VOID(godot_variant_new_transform, godot_variant *r_dest, const godot_transform *p_trans) \ + GDAPI_FUNC_VOID(godot_variant_new_color, godot_variant *r_dest, const godot_color *p_color) \ + GDAPI_FUNC_VOID(godot_variant_new_node_path, godot_variant *r_dest, const godot_node_path *p_np) \ + GDAPI_FUNC_VOID(godot_variant_new_rid, godot_variant *r_dest, const godot_rid *p_rid) \ + GDAPI_FUNC_VOID(godot_variant_new_object, godot_variant *r_dest, const godot_object *p_obj) \ + GDAPI_FUNC_VOID(godot_variant_new_dictionary, godot_variant *r_dest, const godot_dictionary *p_dict) \ + GDAPI_FUNC_VOID(godot_variant_new_array, godot_variant *r_dest, const godot_array *p_arr) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_byte_array, godot_variant *r_dest, const godot_pool_byte_array *p_pba) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_int_array, godot_variant *r_dest, const godot_pool_int_array *p_pia) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_real_array, godot_variant *r_dest, const godot_pool_real_array *p_pra) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_string_array, godot_variant *r_dest, const godot_pool_string_array *p_psa) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_vector2_array, godot_variant *r_dest, const godot_pool_vector2_array *p_pv2a) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_vector3_array, godot_variant *r_dest, const godot_pool_vector3_array *p_pv3a) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_color_array, godot_variant *r_dest, const godot_pool_color_array *p_pca) \ + GDAPI_FUNC(godot_variant_as_bool, godot_bool, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_uint, uint64_t, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_int, int64_t, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_real, double, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_string, godot_string, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_vector2, godot_vector2, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_rect2, godot_rect2, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_vector3, godot_vector3, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_transform2d, godot_transform2d, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_plane, godot_plane, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_quat, godot_quat, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_rect3, godot_rect3, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_basis, godot_basis, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_transform, godot_transform, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_color, godot_color, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_node_path, godot_node_path, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_rid, godot_rid, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_object, godot_object *, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_dictionary, godot_dictionary, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_array, godot_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_byte_array, godot_pool_byte_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_int_array, godot_pool_int_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_real_array, godot_pool_real_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_string_array, godot_pool_string_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_vector2_array, godot_pool_vector2_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_vector3_array, godot_pool_vector3_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_color_array, godot_pool_color_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_call, godot_variant, godot_variant *p_self, const godot_string *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant_call_error *r_error) \ + GDAPI_FUNC(godot_variant_has_method, godot_bool, const godot_variant *p_self, const godot_string *p_method) \ + GDAPI_FUNC(godot_variant_operator_equal, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \ + GDAPI_FUNC(godot_variant_operator_less, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \ + GDAPI_FUNC(godot_variant_hash_compare, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \ + GDAPI_FUNC(godot_variant_booleanize, godot_bool, const godot_variant *p_self) \ + GDAPI_FUNC_VOID(godot_variant_destroy, godot_variant *p_self) \ + GDAPI_FUNC_VOID(godot_string_new, godot_string *r_dest) \ + GDAPI_FUNC_VOID(godot_string_new_copy, godot_string *r_dest, const godot_string *p_src) \ + GDAPI_FUNC_VOID(godot_string_new_data, godot_string *r_dest, const char *p_contents, const int p_size) \ + GDAPI_FUNC_VOID(godot_string_new_unicode_data, godot_string *r_dest, const wchar_t *p_contents, const int p_size) \ + GDAPI_FUNC_VOID(godot_string_get_data, const godot_string *p_self, char *p_dest, int *p_size) \ + GDAPI_FUNC(godot_string_operator_index, wchar_t *, godot_string *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_string_c_str, const char *, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_unicode_str, const wchar_t *, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_operator_equal, godot_bool, const godot_string *p_self, const godot_string *p_b) \ + GDAPI_FUNC(godot_string_operator_less, godot_bool, const godot_string *p_self, const godot_string *p_b) \ + GDAPI_FUNC(godot_string_operator_plus, godot_string, const godot_string *p_self, const godot_string *p_b) \ + GDAPI_FUNC(godot_string_length, godot_int, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_begins_with, godot_bool, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_begins_with_char_array, godot_bool, const godot_string *p_self, const char *p_char_array) \ + GDAPI_FUNC(godot_string_bigrams, godot_array, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_chr, godot_string, wchar_t p_character) \ + GDAPI_FUNC(godot_string_ends_with, godot_bool, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_find, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_find_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \ + GDAPI_FUNC(godot_string_findmk, godot_int, const godot_string *p_self, const godot_array *p_keys) \ + GDAPI_FUNC(godot_string_findmk_from, godot_int, const godot_string *p_self, const godot_array *p_keys, godot_int p_from) \ + GDAPI_FUNC(godot_string_findmk_from_in_place, godot_int, const godot_string *p_self, const godot_array *p_keys, godot_int p_from, godot_int *r_key) \ + GDAPI_FUNC(godot_string_findn, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_findn_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \ + GDAPI_FUNC(godot_string_find_last, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_format, godot_string, const godot_string *p_self, const godot_variant *p_values) \ + GDAPI_FUNC(godot_string_format_with_custom_placeholder, godot_string, const godot_string *p_self, const godot_variant *p_values, const char *p_placeholder) \ + GDAPI_FUNC(godot_string_hex_encode_buffer, godot_string, const uint8_t *p_buffer, godot_int p_len) \ + GDAPI_FUNC(godot_string_hex_to_int, godot_int, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_hex_to_int_without_prefix, godot_int, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_insert, godot_string, const godot_string *p_self, godot_int p_at_pos, godot_string p_string) \ + GDAPI_FUNC(godot_string_is_numeric, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_subsequence_of, godot_bool, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_is_subsequence_ofi, godot_bool, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_lpad, godot_string, const godot_string *p_self, godot_int p_min_length) \ + GDAPI_FUNC(godot_string_lpad_with_custom_character, godot_string, const godot_string *p_self, godot_int p_min_length, const godot_string *p_character) \ + GDAPI_FUNC(godot_string_match, godot_bool, const godot_string *p_self, const godot_string *p_wildcard) \ + GDAPI_FUNC(godot_string_matchn, godot_bool, const godot_string *p_self, const godot_string *p_wildcard) \ + GDAPI_FUNC(godot_string_md5, godot_string, const uint8_t *p_md5) \ + GDAPI_FUNC(godot_string_num, godot_string, double p_num) \ + GDAPI_FUNC(godot_string_num_int64, godot_string, int64_t p_num, godot_int p_base) \ + GDAPI_FUNC(godot_string_num_int64_capitalized, godot_string, int64_t p_num, godot_int p_base, godot_bool p_capitalize_hex) \ + GDAPI_FUNC(godot_string_num_real, godot_string, double p_num) \ + GDAPI_FUNC(godot_string_num_scientific, godot_string, double p_num) \ + GDAPI_FUNC(godot_string_num_with_decimals, godot_string, double p_num, godot_int p_decimals) \ + GDAPI_FUNC(godot_string_pad_decimals, godot_string, const godot_string *p_self, godot_int p_digits) \ + GDAPI_FUNC(godot_string_pad_zeros, godot_string, const godot_string *p_self, godot_int p_digits) \ + GDAPI_FUNC(godot_string_replace_first, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \ + GDAPI_FUNC(godot_string_replace, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \ + GDAPI_FUNC(godot_string_replacen, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \ + GDAPI_FUNC(godot_string_rfind, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_rfindn, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_rfind_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \ + GDAPI_FUNC(godot_string_rfindn_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \ + GDAPI_FUNC(godot_string_rpad, godot_string, const godot_string *p_self, godot_int p_min_length) \ + GDAPI_FUNC(godot_string_rpad_with_custom_character, godot_string, const godot_string *p_self, godot_int p_min_length, const godot_string *p_character) \ + GDAPI_FUNC(godot_string_similarity, godot_real, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_sprintf, godot_string, const godot_string *p_self, const godot_array *p_values, godot_bool *p_error) \ + GDAPI_FUNC(godot_string_substr, godot_string, const godot_string *p_self, godot_int p_from, godot_int p_chars) \ + GDAPI_FUNC(godot_string_to_double, double, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_to_float, godot_real, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_to_int, godot_int, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_camelcase_to_underscore, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_camelcase_to_underscore_lowercased, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_capitalize, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_char_to_double, double, const char *p_what) \ + GDAPI_FUNC(godot_string_char_to_int, godot_int, const char *p_what) \ + GDAPI_FUNC(godot_string_wchar_to_int, int64_t, const wchar_t *p_str) \ + GDAPI_FUNC(godot_string_char_to_int_with_len, godot_int, const char *p_what, godot_int p_len) \ + GDAPI_FUNC(godot_string_char_to_int64_with_len, int64_t, const wchar_t *p_str, int p_len) \ + GDAPI_FUNC(godot_string_hex_to_int64, int64_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_hex_to_int64_with_prefix, int64_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_to_int64, int64_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_unicode_char_to_double, double, const wchar_t *p_str, const wchar_t **r_end) \ + GDAPI_FUNC(godot_string_get_slice_count, godot_int, const godot_string *p_self, godot_string p_splitter) \ + GDAPI_FUNC(godot_string_get_slice, godot_string, const godot_string *p_self, godot_string p_splitter, godot_int p_slice) \ + GDAPI_FUNC(godot_string_get_slicec, godot_string, const godot_string *p_self, wchar_t p_splitter, godot_int p_slice) \ + GDAPI_FUNC(godot_string_split, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_allow_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_floats, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_floats_allows_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_floats_mk, godot_array, const godot_string *p_self, const godot_array *p_splitters) \ + GDAPI_FUNC(godot_string_split_floats_mk_allows_empty, godot_array, const godot_string *p_self, const godot_array *p_splitters) \ + GDAPI_FUNC(godot_string_split_ints, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_ints_allows_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_ints_mk, godot_array, const godot_string *p_self, const godot_array *p_splitters) \ + GDAPI_FUNC(godot_string_split_ints_mk_allows_empty, godot_array, const godot_string *p_self, const godot_array *p_splitters) \ + GDAPI_FUNC(godot_string_split_spaces, godot_array, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_char_lowercase, wchar_t, wchar_t p_char) \ + GDAPI_FUNC(godot_string_char_uppercase, wchar_t, wchar_t p_char) \ + GDAPI_FUNC(godot_string_to_lower, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_to_upper, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_get_basename, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_get_extension, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_left, godot_string, const godot_string *p_self, godot_int p_pos) \ + GDAPI_FUNC(godot_string_ord_at, wchar_t, const godot_string *p_self, godot_int p_idx) \ + GDAPI_FUNC(godot_string_plus_file, godot_string, const godot_string *p_self, const godot_string *p_file) \ + GDAPI_FUNC(godot_string_right, godot_string, const godot_string *p_self, godot_int p_pos) \ + GDAPI_FUNC(godot_string_strip_edges, godot_string, const godot_string *p_self, godot_bool p_left, godot_bool p_right) \ + GDAPI_FUNC(godot_string_strip_escapes, godot_string, const godot_string *p_self) \ + GDAPI_FUNC_VOID(godot_string_erase, godot_string *p_self, godot_int p_pos, godot_int p_chars) \ + GDAPI_FUNC_VOID(godot_string_ascii, godot_string *p_self, char *result) \ + GDAPI_FUNC_VOID(godot_string_ascii_extended, godot_string *p_self, char *result) \ + GDAPI_FUNC_VOID(godot_string_utf8, godot_string *p_self, char *result) \ + GDAPI_FUNC(godot_string_parse_utf8, godot_bool, godot_string *p_self, const char *p_utf8) \ + GDAPI_FUNC(godot_string_parse_utf8_with_len, godot_bool, godot_string *p_self, const char *p_utf8, godot_int p_len) \ + GDAPI_FUNC(godot_string_chars_to_utf8, godot_string, const char *p_utf8) \ + GDAPI_FUNC(godot_string_chars_to_utf8_with_len, godot_string, const char *p_utf8, godot_int p_len) \ + GDAPI_FUNC(godot_string_hash, uint32_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_hash64, uint64_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_hash_chars, uint32_t, const char *p_cstr) \ + GDAPI_FUNC(godot_string_hash_chars_with_len, uint32_t, const char *p_cstr, godot_int p_len) \ + GDAPI_FUNC(godot_string_hash_utf8_chars, uint32_t, const wchar_t *p_str) \ + GDAPI_FUNC(godot_string_hash_utf8_chars_with_len, uint32_t, const wchar_t *p_str, godot_int p_len) \ + GDAPI_FUNC(godot_string_md5_buffer, godot_pool_byte_array, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_md5_text, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_sha256_buffer, godot_pool_byte_array, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_sha256_text, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_empty, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_get_base_dir, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_get_file, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_humanize_size, godot_string, size_t p_size) \ + GDAPI_FUNC(godot_string_is_abs_path, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_rel_path, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_resource_file, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_path_to, godot_string, const godot_string *p_self, const godot_string *p_path) \ + GDAPI_FUNC(godot_string_path_to_file, godot_string, const godot_string *p_self, const godot_string *p_path) \ + GDAPI_FUNC(godot_string_simplify_path, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_c_escape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_c_escape_multiline, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_c_unescape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_http_escape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_http_unescape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_json_escape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_word_wrap, godot_string, const godot_string *p_self, godot_int p_chars_per_line) \ + GDAPI_FUNC(godot_string_xml_escape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_xml_escape_with_quotes, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_xml_unescape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_percent_decode, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_percent_encode, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_float, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_hex_number, godot_bool, const godot_string *p_self, godot_bool p_with_prefix) \ + GDAPI_FUNC(godot_string_is_valid_html_color, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_identifier, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_integer, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_ip_address, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC_VOID(godot_string_destroy, godot_string *p_self) \ + GDAPI_FUNC_VOID(godot_object_destroy, godot_object *p_o) \ + GDAPI_FUNC(godot_global_get_singleton, godot_object *, char *p_name) \ + GDAPI_FUNC(godot_get_stack_bottom, void *) \ + GDAPI_FUNC(godot_method_bind_get_method, godot_method_bind *, const char *p_classname, const char *p_methodname) \ + GDAPI_FUNC_VOID(godot_method_bind_ptrcall, godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret) \ + GDAPI_FUNC(godot_method_bind_call, godot_variant, godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error) \ + GDAPI_FUNC(godot_get_class_constructor, godot_class_constructor, const char *p_classname) \ + GDAPI_FUNC(godot_get_global_constants, godot_dictionary) \ + GDAPI_FUNC(godot_alloc, void *, int p_bytes) \ + GDAPI_FUNC(godot_realloc, void *, void *p_ptr, int p_bytes) \ + GDAPI_FUNC_VOID(godot_free, void *p_ptr) \ + GDAPI_FUNC_VOID(godot_print_error, const char *p_description, const char *p_function, const char *p_file, int p_line) \ + GDAPI_FUNC_VOID(godot_print_warning, const char *p_description, const char *p_function, const char *p_file, int p_line) \ + GDAPI_FUNC_VOID(godot_print, const godot_string *p_message) \ + GDAPI_FUNC_VOID(godot_nativescript_register_class, void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) \ + GDAPI_FUNC_VOID(godot_nativescript_register_tool_class, void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) \ + GDAPI_FUNC_VOID(godot_nativescript_register_method, void *p_gdnative_handle, const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method) \ + GDAPI_FUNC_VOID(godot_nativescript_register_property, void *p_gdnative_handle, const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func) \ + GDAPI_FUNC_VOID(godot_nativescript_register_signal, void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal) \ + GDAPI_FUNC(godot_nativescript_get_userdata, void *, godot_object *p_instance) + +#define GDAPI_FUNC(name, ret_type, ...) \ + ret_type (*name)(__VA_ARGS__); +#define GDAPI_FUNC_VOID(name, ...) \ + void (*name)(__VA_ARGS__); + +typedef struct godot_gdnative_api_struct { + GODOT_GDNATIVE_API_FUNCTIONS +} godot_gdnative_api_struct; + +#undef GDAPI_FUNC +#undef GDAPI_FUNC_VOID + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_GDNATIVE_API_STRUCT_H diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index 4803781c67..7036a708e5 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -131,7 +131,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDParser: switch (p_expression->op) { case GDParser::OperatorNode::OP_ASSIGN_ADD: var_op = Variant::OP_ADD; break; - case GDParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBSTRACT; break; + case GDParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBTRACT; break; case GDParser::OperatorNode::OP_ASSIGN_MUL: var_op = Variant::OP_MULTIPLY; break; case GDParser::OperatorNode::OP_ASSIGN_DIV: var_op = Variant::OP_DIVIDE; break; case GDParser::OperatorNode::OP_ASSIGN_MOD: var_op = Variant::OP_MODULE; break; @@ -759,7 +759,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr if (!_create_binary_operator(codegen, on, Variant::OP_ADD, p_stack_level)) return -1; } break; case GDParser::OperatorNode::OP_SUB: { - if (!_create_binary_operator(codegen, on, Variant::OP_SUBSTRACT, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_SUBTRACT, p_stack_level)) return -1; } break; case GDParser::OperatorNode::OP_MUL: { if (!_create_binary_operator(codegen, on, Variant::OP_MULTIPLY, p_stack_level)) return -1; diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index bc51b84047..aa39ad92c4 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -908,7 +908,7 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser: Variant::Operator vop = Variant::OP_MAX; switch (op->op) { case GDParser::OperatorNode::OP_ADD: vop = Variant::OP_ADD; break; - case GDParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBSTRACT; break; + case GDParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBTRACT; break; case GDParser::OperatorNode::OP_MUL: vop = Variant::OP_MULTIPLY; break; case GDParser::OperatorNode::OP_DIV: vop = Variant::OP_DIVIDE; break; case GDParser::OperatorNode::OP_MOD: vop = Variant::OP_MODULE; break; diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp index ddee7b2521..df7b16c96e 100644 --- a/modules/gdscript/gd_function.cpp +++ b/modules/gdscript/gd_function.cpp @@ -271,6 +271,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a if (ScriptDebugger::get_singleton()) GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line); +#define GD_ERR_BREAK(m_cond) ERR_BREAK(m_cond) + #define CHECK_SPACE(m_space) \ ERR_BREAK((ip + m_space) > _code_size) @@ -281,6 +283,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a break; #else +#define GD_ERR_BREAK(m_cond) #define CHECK_SPACE(m_space) #define GET_VARIANT_PTR(m_v, m_code_ofs) \ Variant *m_v; \ @@ -302,9 +305,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a #endif bool exit_ok = false; +#ifdef DEBUG_ENABLED while (ip < _code_size) { - int last_opcode = _code_ptr[ip]; +#else + while (true) { +#endif + switch (_code_ptr[ip]) { case OPCODE_OPERATOR: { @@ -313,21 +320,21 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; Variant::Operator op = (Variant::Operator)_code_ptr[ip + 1]; - ERR_BREAK(op >= Variant::OP_MAX); + GD_ERR_BREAK(op >= Variant::OP_MAX); GET_VARIANT_PTR(a, 2); GET_VARIANT_PTR(b, 3); GET_VARIANT_PTR(dst, 4); #ifdef DEBUG_ENABLED + Variant ret; Variant::evaluate(op, *a, *b, ret, valid); #else Variant::evaluate(op, *a, *b, *dst, valid); #endif - - if (!valid) { #ifdef DEBUG_ENABLED + if (!valid) { if (ret.get_type() == Variant::STRING) { //return a string when invalid with the error @@ -336,13 +343,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } else { err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'."; } -#endif break; } -#ifdef DEBUG_ENABLED *dst = ret; #endif - ip += 5; continue; } @@ -355,7 +359,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(dst, 3); #ifdef DEBUG_ENABLED - if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) { err_text = "Left operand of 'is' is not an instance of anything."; @@ -367,7 +370,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a break; } #endif - Object *obj_A = *a; Object *obj_B = *b; @@ -399,12 +401,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GDNativeClass *nc = Object::cast_to<GDNativeClass>(obj_B); +#ifdef DEBUG_ENABLED if (!nc) { err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "')."; break; } - +#endif extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name()); } @@ -423,6 +426,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; dst->set(*index, *value, &valid); +#ifdef DEBUG_ENABLED if (!valid) { String v = index->operator String(); if (v != "") { @@ -433,7 +437,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "')."; break; } - +#endif ip += 4; continue; } @@ -453,6 +457,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a *dst = src->get(*index, &valid); #endif +#ifdef DEBUG_ENABLED if (!valid) { String v = index->operator String(); if (v != "") { @@ -463,7 +468,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "')."; break; } -#ifdef DEBUG_ENABLED *dst = ret; #endif ip += 4; @@ -478,18 +482,19 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a int indexname = _code_ptr[ip + 2]; - ERR_BREAK(indexname < 0 || indexname >= _global_names_count); + GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; bool valid; dst->set_named(*index, *value, &valid); +#ifdef DEBUG_ENABLED if (!valid) { String err_type; err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "')."; break; } - +#endif ip += 4; continue; } @@ -502,7 +507,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a int indexname = _code_ptr[ip + 2]; - ERR_BREAK(indexname < 0 || indexname >= _global_names_count); + GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; bool valid; @@ -513,7 +518,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a #else *dst = src->get_named(*index, &valid); #endif - +#ifdef DEBUG_ENABLED if (!valid) { if (src->has_method(*index)) { err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' ?"; @@ -522,7 +527,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } break; } -#ifdef DEBUG_ENABLED *dst = ret; #endif ip += 4; @@ -532,7 +536,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a CHECK_SPACE(3); int indexname = _code_ptr[ip + 1]; - ERR_BREAK(indexname < 0 || indexname >= _global_names_count); + GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; GET_VARIANT_PTR(src, 2); @@ -554,7 +558,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a CHECK_SPACE(3); int indexname = _code_ptr[ip + 1]; - ERR_BREAK(indexname < 0 || indexname >= _global_names_count); + GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; GET_VARIANT_PTR(dst, 2); bool ok = ClassDB::get_property(p_instance->owner, *index, *dst); @@ -615,11 +619,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a Variant::CallError err; *dst = Variant::construct(t, (const Variant **)argptrs, argc, err); +#ifdef DEBUG_ENABLED if (err.error != Variant::CallError::CALL_OK) { err_text = _get_call_error(err, "'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs); break; } +#endif ip += 4 + argc; //construct a basic type @@ -677,10 +683,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(base, 2); int nameg = _code_ptr[ip + 3]; - ERR_BREAK(nameg < 0 || nameg >= _global_names_count); + GD_ERR_BREAK(nameg < 0 || nameg >= _global_names_count); const StringName *methodname = &_global_names_ptr[nameg]; - ERR_BREAK(argc < 0); + GD_ERR_BREAK(argc < 0); ip += 4; CHECK_SPACE(argc + 1); Variant **argptrs = call_args; @@ -711,7 +717,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a if (GDScriptLanguage::get_singleton()->profiling) { function_call_time += OS::get_singleton()->get_ticks_usec() - call_time; } -#endif if (err.error != Variant::CallError::CALL_OK) { @@ -742,6 +747,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text = _get_call_error(err, "function '" + methodstr + "' in base '" + basestr + "'", (const Variant **)argptrs); break; } +#endif //_call_func(NULL,base,*methodname,ip,argc,p_instance,stack); ip += argc + 1; @@ -753,7 +759,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GDFunctions::Function func = GDFunctions::Function(_code_ptr[ip + 1]); int argc = _code_ptr[ip + 2]; - ERR_BREAK(argc < 0); + GD_ERR_BREAK(argc < 0); ip += 3; CHECK_SPACE(argc + 1); @@ -770,6 +776,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GDFunctions::call(func, (const Variant **)argptrs, argc, *dst, err); +#ifdef DEBUG_ENABLED if (err.error != Variant::CallError::CALL_OK) { String methodstr = GDFunctions::get_func_name(func); @@ -781,6 +788,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } break; } +#endif ip += argc + 1; continue; } @@ -792,8 +800,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a CHECK_SPACE(2); int self_fun = _code_ptr[ip + 1]; -#ifdef DEBUG_ENABLED +#ifdef DEBUG_ENABLED if (self_fun < 0 || self_fun >= _global_names_count) { err_text = "compiler bug, function name not found"; @@ -898,10 +906,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a retvalue = gdfs; if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) { + //do the oneshot connect GET_VARIANT_PTR(argobj, 1); GET_VARIANT_PTR(argname, 2); - //do the oneshot connect +#ifdef DEBUG_ENABLED if (argobj->get_type() != Variant::OBJECT) { err_text = "First argument of yield() not of type object."; break; @@ -910,6 +919,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text = "Second argument of yield() not a string (for signal name)."; break; } +#endif Object *obj = argobj->operator Object *(); String signal = argname->operator String(); #ifdef DEBUG_ENABLED @@ -932,10 +942,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a #endif Error err = obj->connect(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT); +#ifdef DEBUG_ENABLED if (err != OK) { err_text = "Error connecting to signal: " + signal + " during yield()."; break; } +#endif } exit_ok = true; @@ -944,10 +956,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a case OPCODE_YIELD_RESUME: { CHECK_SPACE(2); +#ifdef DEBUG_ENABLED if (!p_state) { err_text = ("Invalid Resume (bug?)"); break; } +#endif GET_VARIANT_PTR(result, 1); *result = p_state->result; ip += 2; @@ -958,7 +972,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a CHECK_SPACE(2); int to = _code_ptr[ip + 1]; - ERR_BREAK(to < 0 || to > _code_size); + GD_ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } @@ -968,18 +982,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(test, 1); - bool valid; - bool result = test->booleanize(valid); -#ifdef DEBUG_ENABLED - if (!valid) { + bool result = test->booleanize(); - err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); - break; - } -#endif if (result) { int to = _code_ptr[ip + 2]; - ERR_BREAK(to < 0 || to > _code_size); + GD_ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } @@ -992,18 +999,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(test, 1); - bool valid; - bool result = test->booleanize(valid); -#ifdef DEBUG_ENABLED - if (!valid) { + bool result = test->booleanize(); - err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); - break; - } -#endif if (!result) { int to = _code_ptr[ip + 2]; - ERR_BREAK(to < 0 || to > _code_size); + GD_ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } @@ -1033,23 +1033,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; if (!container->iter_init(*counter, valid)) { +#ifdef DEBUG_ENABLED if (!valid) { err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "'."; break; } +#endif int jumpto = _code_ptr[ip + 3]; - ERR_BREAK(jumpto < 0 || jumpto > _code_size); + GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); ip = jumpto; continue; } GET_VARIANT_PTR(iterator, 4); *iterator = container->iter_get(*counter, valid); +#ifdef DEBUG_ENABLED if (!valid) { err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "'."; break; } - +#endif ip += 5; //skip regular iterate which is always next continue; } @@ -1062,23 +1065,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; if (!container->iter_next(*counter, valid)) { +#ifdef DEBUG_ENABLED if (!valid) { err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "' (type changed since first iteration?)."; break; } +#endif int jumpto = _code_ptr[ip + 3]; - ERR_BREAK(jumpto < 0 || jumpto > _code_size); + GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); ip = jumpto; continue; } GET_VARIANT_PTR(iterator, 4); *iterator = container->iter_get(*counter, valid); +#ifdef DEBUG_ENABLED if (!valid) { err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?)."; break; } - +#endif ip += 5; //loop again continue; } @@ -1087,14 +1093,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(test, 1); #ifdef DEBUG_ENABLED - bool valid; - bool result = test->booleanize(valid); - - if (!valid) { - - err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); - break; - } + bool result = test->booleanize(); if (!result) { @@ -1103,7 +1102,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } #endif - ip += 2; continue; } @@ -1157,6 +1155,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } } +#ifdef DEBUG_ENABLED if (exit_ok) break; //error @@ -1182,6 +1181,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), ERR_HANDLER_SCRIPT); } +#endif break; } diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index 72c3f9612a..36aaa1f807 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -1699,7 +1699,7 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) { _REDUCE_BINARY(Variant::OP_ADD); } break; case OperatorNode::OP_SUB: { - _REDUCE_BINARY(Variant::OP_SUBSTRACT); + _REDUCE_BINARY(Variant::OP_SUBTRACT); } break; case OperatorNode::OP_MUL: { _REDUCE_BINARY(Variant::OP_MULTIPLY); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 671a507377..ee83c44793 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -491,10 +491,6 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->set_overlay(GraphNode::OVERLAY_BREAKPOINT); } - if (node_styles.has(node->get_category())) { - gnode->add_style_override("frame", node_styles[node->get_category()]); - } - gnode->set_meta("__vnode", node); gnode->set_name(itos(E->get())); gnode->connect("dragged", this, "_node_moved", varray(E->get())); @@ -527,6 +523,25 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->connect("resize_request", this, "_comment_node_resized", varray(E->get())); } + if (node_styles.has(node->get_category())) { + Ref<StyleBoxFlat> sbf = node_styles[node->get_category()]; + if (gnode->is_comment()) + sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox("comment", "GraphNode"); + + Color c = sbf->get_border_color(MARGIN_TOP); + c.a = 1; + if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { + Color mono_color = ((c.r + c.g + c.b) / 3) < 0.5 ? Color(1.0, 1.0, 1.0) : Color(0, 0, 0); + mono_color.a = 0.85; + c = mono_color; + } + + gnode->add_color_override("title_color", c); + c.a = 0.7; + gnode->add_color_override("close_color", c); + gnode->add_style_override("frame", sbf); + } + int slot_idx = 0; bool single_seq_output = node->get_output_sequence_port_count() == 1 && node->get_output_sequence_port_text(0) == String(); @@ -2753,12 +2768,12 @@ void VisualScriptEditor::_notification(int p_what) { signal_editor->connect("changed", this, "_update_members"); List<Pair<String, Color> > colors; - colors.push_back(Pair<String, Color>("functions", Color(1, 0.9, 0.9))); - colors.push_back(Pair<String, Color>("data", Color(0.9, 1.0, 0.9))); - colors.push_back(Pair<String, Color>("operators", Color(0.9, 0.9, 1.0))); - colors.push_back(Pair<String, Color>("flow_control", Color(1.0, 1.0, 1.0))); - colors.push_back(Pair<String, Color>("custom", Color(0.8, 1.0, 1.0))); - colors.push_back(Pair<String, Color>("constants", Color(1.0, 0.8, 1.0))); + colors.push_back(Pair<String, Color>("flow_control", Color::html("#f4f4f4"))); + colors.push_back(Pair<String, Color>("functions", Color::html("#f58581"))); + colors.push_back(Pair<String, Color>("data", Color::html("#80f6cf"))); + colors.push_back(Pair<String, Color>("operators", Color::html("#ab97df"))); + colors.push_back(Pair<String, Color>("custom", Color::html("#80bbf6"))); + colors.push_back(Pair<String, Color>("constants", Color::html("#f680b0"))); for (List<Pair<String, Color> >::Element *E = colors.front(); E; E = E->next()) { print_line(E->get().first); diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index eae866d167..897e910f20 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -1023,7 +1023,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { case TK_OP_OR: op = Variant::OP_OR; break; case TK_OP_NOT: op = Variant::OP_NOT; break; case TK_OP_ADD: op = Variant::OP_ADD; break; - case TK_OP_SUB: op = Variant::OP_SUBSTRACT; break; + case TK_OP_SUB: op = Variant::OP_SUBTRACT; break; case TK_OP_MUL: op = Variant::OP_MULTIPLY; break; case TK_OP_DIV: op = Variant::OP_DIVIDE; break; case TK_OP_MOD: op = Variant::OP_MODULE; break; @@ -1085,7 +1085,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { case Variant::OP_MODULE: priority = 2; break; case Variant::OP_ADD: priority = 3; break; - case Variant::OP_SUBSTRACT: priority = 3; break; + case Variant::OP_SUBTRACT: priority = 3; break; case Variant::OP_SHIFT_LEFT: priority = 4; break; case Variant::OP_SHIFT_RIGHT: priority = 4; break; diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 267946750f..f02e797fe6 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -1546,7 +1546,7 @@ public: value = Variant::evaluate(Variant::OP_ADD, value, p_argument); } break; case VisualScriptPropertySet::ASSIGN_OP_SUB: { - value = Variant::evaluate(Variant::OP_SUBSTRACT, value, p_argument); + value = Variant::evaluate(Variant::OP_SUBTRACT, value, p_argument); } break; case VisualScriptPropertySet::ASSIGN_OP_MUL: { value = Variant::evaluate(Variant::OP_MULTIPLY, value, p_argument); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index b617c11bab..16aec76e57 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -3762,7 +3762,7 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("operators/compare/greater_equal", create_op_node<Variant::OP_GREATER_EQUAL>); //mathematic VisualScriptLanguage::singleton->add_register_func("operators/math/add", create_op_node<Variant::OP_ADD>); - VisualScriptLanguage::singleton->add_register_func("operators/math/subtract", create_op_node<Variant::OP_SUBSTRACT>); + VisualScriptLanguage::singleton->add_register_func("operators/math/subtract", create_op_node<Variant::OP_SUBTRACT>); VisualScriptLanguage::singleton->add_register_func("operators/math/multiply", create_op_node<Variant::OP_MULTIPLY>); VisualScriptLanguage::singleton->add_register_func("operators/math/divide", create_op_node<Variant::OP_DIVIDE>); VisualScriptLanguage::singleton->add_register_func("operators/math/negate", create_op_node<Variant::OP_NEGATE>); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 1de2608b9e..dbea2d7531 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -137,12 +137,7 @@ void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int visual_server->init(); // visual_server->cursor_set_visible(false, 0); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); physics_server = memnew(PhysicsServerSW); physics_server->init(); diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index de2f79a0ac..9f2f88bb4e 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -137,11 +137,7 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_ //physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>(); physics_2d_server->init(); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); power_manager = memnew(PowerHaiku); } diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 543d028576..f103035b27 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -172,14 +172,14 @@ static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent if (!is_canvas_focused()) { focus_canvas(); } - mask |= 1 << ev->get_button_index(); - } else if (mask & (1 << ev->get_button_index())) { - mask &= ~(1 << ev->get_button_index()); + mask |= ev->get_button_index(); + } else if (mask & ev->get_button_index()) { + mask &= ~ev->get_button_index(); } else { // release event, but press was outside the canvas, so ignore return false; } - ev->set_button_mask(mask >> 1); + ev->set_button_mask(mask); _input->parse_input_event(ev); // prevent selection dragging @@ -200,7 +200,7 @@ static EM_BOOL _mousemove_callback(int event_type, const EmscriptenMouseEvent *m Ref<InputEventMouseMotion> ev; ev.instance(); dom2godot_mod(mouse_event, ev); - ev->set_button_mask(input_mask >> 1); + ev->set_button_mask(input_mask); ev->set_position(pos); ev->set_global_position(ev->get_position()); @@ -227,7 +227,7 @@ static EM_BOOL _wheel_callback(int event_type, const EmscriptenWheelEvent *wheel Ref<InputEventMouseButton> ev; ev.instance(); - ev->set_button_mask(_input->get_mouse_button_mask() >> 1); + ev->set_button_mask(_input->get_mouse_button_mask()); ev->set_position(_input->get_mouse_position()); ev->set_global_position(ev->get_position()); @@ -291,7 +291,7 @@ static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent * Ref<InputEventMouseButton> ev_mouse; ev_mouse.instance(); - ev_mouse->set_button_mask(_input->get_mouse_button_mask() >> 1); + ev_mouse->set_button_mask(_input->get_mouse_button_mask()); dom2godot_mod(touch_event, ev_mouse); const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index]; @@ -334,7 +334,7 @@ static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *t Ref<InputEventMouseMotion> ev_mouse; ev_mouse.instance(); dom2godot_mod(touch_event, ev_mouse); - ev_mouse->set_button_mask(_input->get_mouse_button_mask() >> 1); + ev_mouse->set_button_mask(_input->get_mouse_button_mask()); const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index]; ev_mouse->set_position(Point2(first_touch.canvasX, first_touch.canvasY)); @@ -464,11 +464,7 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i print_line("Init Audio"); AudioDriverManager::add_driver(&audio_driver_javascript); - audio_driver_javascript.set_singleton(); - if (audio_driver_javascript.init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm index 9239573734..2ed88db309 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/osx/crash_handler_osx.mm @@ -43,6 +43,7 @@ #include <dlfcn.h> #include <execinfo.h> #include <signal.h> +#include <stdlib.h> #include <mach-o/dyld.h> #include <mach-o/getsect.h> @@ -77,7 +78,7 @@ static void handle_crash(int sig) { void *bt_buffer[256]; size_t size = backtrace(bt_buffer, 256); String _execpath = OS::get_singleton()->get_executable_path(); - String msg = GLOBAL_GET("debug/settings/backtrace/message"); + String msg = GLOBAL_GET("debug/settings/crash_handler/message"); // Dump the backtrace to stderr with a message to the user fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 5a23d76755..111cdb0cf1 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1088,12 +1088,7 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au visual_server->init(); // visual_server->cursor_set_visible(false, 0); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); // physics_server = memnew(PhysicsServerSW); diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index e2bb464e76..300c5cffcc 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -62,12 +62,7 @@ void OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p //visual_server = memnew( VisualServerRaster(rasterizer) ); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); sample_manager = memnew(SampleManagerMallocSW); audio_server = memnew(AudioServerSW(sample_manager)); @@ -232,7 +227,6 @@ void OS_Server::run() { OS_Server::OS_Server() { - AudioDriverManager::add_driver(&driver_dummy); //adriver here grab = false; }; diff --git a/platform/server/os_server.h b/platform/server/os_server.h index 8c0ca1a58d..ba12f649be 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -34,7 +34,6 @@ #include "drivers/rtaudio/audio_driver_rtaudio.h" #include "drivers/unix/os_unix.h" #include "main/input_default.h" -#include "servers/audio/audio_driver_dummy.h" #include "servers/audio_server.h" #include "servers/physics_2d/physics_2d_server_sw.h" #include "servers/physics_server.h" @@ -55,7 +54,6 @@ class OS_Server : public OS_Unix { List<String> args; MainLoop *main_loop; - AudioDriverDummy driver_dummy; bool grab; PhysicsServer *physics_server; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index fd8904fa0a..b909ccccd6 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -268,12 +268,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud joypad = ref new JoypadUWP(input); joypad->register_events(); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); power_manager = memnew(PowerUWP); diff --git a/platform/windows/crash_handler_win.cpp b/platform/windows/crash_handler_win.cpp index c9385f36d6..2f5ee7956e 100644 --- a/platform/windows/crash_handler_win.cpp +++ b/platform/windows/crash_handler_win.cpp @@ -116,7 +116,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) { DWORD cbNeeded; std::vector<HMODULE> module_handles(1); - if (OS::get_singleton() == NULL || OS::get_singleton()->is_disable_crash_handler()) { + if (OS::get_singleton() == NULL || OS::get_singleton()->is_disable_crash_handler() || IsDebuggerPresent()) { return EXCEPTION_CONTINUE_SEARCH; } @@ -159,7 +159,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) { IMAGE_NT_HEADERS *h = ImageNtHeader(base); DWORD image_type = h->FileHeader.Machine; int n = 0; - String msg = GLOBAL_GET("debug/settings/backtrace/message"); + String msg = GLOBAL_GET("debug/settings/crash_handler/message"); fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str()); diff --git a/platform/windows/godot_win.cpp b/platform/windows/godot_win.cpp index 4450cb3670..cff2cbad42 100644 --- a/platform/windows/godot_win.cpp +++ b/platform/windows/godot_win.cpp @@ -156,32 +156,36 @@ int widechar_main(int argc, wchar_t **argv) { return os.get_exit_code(); }; -int main(int _argc, char **_argv) { -// _argc and _argv are ignored -// we are going to use the WideChar version of them instead +int _main() { + LPWSTR *wc_argv; + int argc; + int result; -#ifdef CRASH_HANDLER_EXCEPTION - __try { -#endif - LPWSTR *wc_argv; - int argc; - int result; + wc_argv = CommandLineToArgvW(GetCommandLineW(), &argc); + + if (NULL == wc_argv) { + wprintf(L"CommandLineToArgvW failed\n"); + return 0; + } - wc_argv = CommandLineToArgvW(GetCommandLineW(), &argc); + result = widechar_main(argc, wc_argv); - if (NULL == wc_argv) { - wprintf(L"CommandLineToArgvW failed\n"); - return 0; - } + LocalFree(wc_argv); + return result; +} - result = widechar_main(argc, wc_argv); +int main(int _argc, char **_argv) { +// _argc and _argv are ignored +// we are going to use the WideChar version of them instead - LocalFree(wc_argv); - return result; #ifdef CRASH_HANDLER_EXCEPTION + __try { + return _main(); } __except (CrashHandlerException(GetExceptionInformation())) { return 1; } +#else + return _main(); #endif } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 62954e1a56..461caf479c 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1081,12 +1081,7 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int power_manager = memnew(PowerWindows); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); TRACKMOUSEEVENT tme; tme.cbSize = sizeof(TRACKMOUSEEVENT); diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp index c926b7799d..3c54d5cbc2 100644 --- a/platform/x11/crash_handler_x11.cpp +++ b/platform/x11/crash_handler_x11.cpp @@ -39,6 +39,7 @@ #include <dlfcn.h> #include <execinfo.h> #include <signal.h> +#include <stdlib.h> static void handle_crash(int sig) { if (OS::get_singleton() == NULL) @@ -47,7 +48,7 @@ static void handle_crash(int sig) { void *bt_buffer[256]; size_t size = backtrace(bt_buffer, 256); String _execpath = OS::get_singleton()->get_executable_path(); - String msg = GLOBAL_GET("debug/settings/backtrace/message"); + String msg = GLOBAL_GET("debug/settings/crash_handler/message"); // Dump the backtrace to stderr with a message to the user fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig); diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp index 59b1a44247..fdb43c9ae0 100644 --- a/platform/x11/export/export.cpp +++ b/platform/x11/export/export.cpp @@ -50,6 +50,7 @@ void register_x11_exporter() { platform->set_release_64("linux_x11_64_release"); platform->set_debug_64("linux_x11_64_debug"); platform->set_os_name("X11"); + platform->set_chmod_flags(0755); EditorExport::get_singleton()->add_export_platform(platform); } diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 4e78e0318c..3e8709a11e 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -313,29 +313,7 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au XFree(xsh); } - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - audio_driver_index = p_audio_driver; - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - bool success = false; - audio_driver_index = -1; - for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) { - if (i == p_audio_driver) - continue; - AudioDriverManager::get_driver(i)->set_singleton(); - if (AudioDriverManager::get_driver(i)->init() == OK) { - success = true; - print_line("Audio Driver Failed: " + String(AudioDriverManager::get_driver(p_audio_driver)->get_name())); - print_line("Using alternate audio driver: " + String(AudioDriverManager::get_driver(i)->get_name())); - audio_driver_index = i; - break; - } - } - if (!success) { - ERR_PRINT("Initializing audio failed."); - } - } + AudioDriverManager::initialize(p_audio_driver); ERR_FAIL_COND(!visual_server); ERR_FAIL_COND(x11_window == 0); @@ -2189,10 +2167,6 @@ bool OS_X11::is_disable_crash_handler() const { OS_X11::OS_X11() { -#ifdef RTAUDIO_ENABLED - AudioDriverManager::add_driver(&driver_rtaudio); -#endif - #ifdef PULSEAUDIO_ENABLED AudioDriverManager::add_driver(&driver_pulseaudio); #endif @@ -2201,11 +2175,6 @@ OS_X11::OS_X11() { AudioDriverManager::add_driver(&driver_alsa); #endif - if (AudioDriverManager::get_driver_count() == 0) { - WARN_PRINT("No sound driver found... Defaulting to dummy driver"); - AudioDriverManager::add_driver(&driver_dummy); - } - minimized = false; xim_style = 0L; mouse_mode = MOUSE_MODE_VISIBLE; diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 2ba7f07cef..0e2430c650 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -38,11 +38,9 @@ //#include "servers/visual/visual_server_wrap_mt.h" #include "drivers/alsa/audio_driver_alsa.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" -#include "drivers/rtaudio/audio_driver_rtaudio.h" #include "joypad_linux.h" #include "main/input_default.h" #include "power_x11.h" -#include "servers/audio/audio_driver_dummy.h" #include "servers/audio_server.h" #include "servers/physics_2d/physics_2d_server_sw.h" #include "servers/physics_2d/physics_2d_server_wrap_mt.h" @@ -154,10 +152,6 @@ class OS_X11 : public OS_Unix { JoypadLinux *joypad; #endif -#ifdef RTAUDIO_ENABLED - AudioDriverRtAudio driver_rtaudio; -#endif - #ifdef ALSA_ENABLED AudioDriverALSA driver_alsa; #endif @@ -165,7 +159,6 @@ class OS_X11 : public OS_Unix { #ifdef PULSEAUDIO_ENABLED AudioDriverPulseAudio driver_pulseaudio; #endif - AudioDriverDummy driver_dummy; Atom net_wm_icon; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 5b00aab2ef..4477e9ecf9 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -283,7 +283,7 @@ void GraphEdit::_notification(int p_what) { zoom_minus->set_icon(get_icon("minus")); zoom_reset->set_icon(get_icon("reset")); zoom_plus->set_icon(get_icon("more")); - snap_button->set_icon(get_icon("snap")); + snap_button->set_icon(get_icon("SnapGrid")); //zoom_icon->set_texture( get_icon("Zoom", "EditorIcons")); } if (p_what == NOTIFICATION_DRAW) { diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index bef0808fd0..26732e070b 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -208,8 +208,11 @@ void GraphNode::_notification(int p_what) { Ref<Texture> close = get_icon("close"); Ref<Texture> resizer = get_icon("resizer"); int close_offset = get_constant("close_offset"); + int close_h_offset = get_constant("close_h_offset"); + Color close_color = get_color("close_color"); Ref<Font> title_font = get_font("title_font"); int title_offset = get_constant("title_offset"); + int title_h_offset = get_constant("title_h_offset"); Color title_color = get_color("title_color"); Point2i icofs = -port->get_size() * 0.5; int edgeofs = get_constant("port_offset"); @@ -236,10 +239,10 @@ void GraphNode::_notification(int p_what) { if (show_close) w -= close->get_width(); - draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT), -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w); + draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w); if (show_close) { - Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT), -close->get_height() + close_offset); - draw_texture(close, cpos); + Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT) + close_h_offset, -close->get_height() + close_offset); + draw_texture(close, cpos, close_color); close_rect.position = cpos; close_rect.size = close->get_size(); } else { diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index 16d1b320b7..41f4beb1c9 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -106,9 +106,9 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { if (ofs < grabber_ofs) { if (scrolling) { - target_scroll = target_scroll - get_page(); + target_scroll = CLAMP(target_scroll - get_page(), get_min(), get_max() - get_page()); } else { - target_scroll = get_value() - get_page(); + target_scroll = CLAMP(get_value() - get_page(), get_min(), get_max() - get_page()); } if (smooth_scroll_enabled) { @@ -130,9 +130,9 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { update(); } else { if (scrolling) { - target_scroll = target_scroll + get_page(); + target_scroll = CLAMP(target_scroll + get_page(), get_min(), get_max() - get_page()); } else { - target_scroll = get_value() + get_page(); + target_scroll = CLAMP(get_value() + get_page(), get_min(), get_max() - get_page()); } if (smooth_scroll_enabled) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index db6d257640..d30e0b9f25 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2804,8 +2804,12 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { _remove_text(i, 0, i, 1); } } else { - if (get_line(cursor.line).begins_with("#")) + if (get_line(cursor.line).begins_with("#")) { _remove_text(cursor.line, 0, cursor.line, 1); + if (cursor.column >= get_line(cursor.line).length()) { + cursor.column = MAX(0, get_line(cursor.line).length() - 1); + } + } } update(); } @@ -4262,6 +4266,10 @@ bool TextEdit::is_insert_mode() const { return insert_mode; } +bool TextEdit::is_insert_text_operation() { + return (current_op.type == TextOperation::TYPE_INSERT); +} + uint32_t TextEdit::get_version() const { return current_op.version; } diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 68ef559f46..7e61c4e8b1 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -386,6 +386,8 @@ public: void begin_complex_operation(); void end_complex_operation(); + bool is_insert_text_operation(); + void set_text(String p_text); void insert_text_at_cursor(const String &p_text); void insert_at(const String &p_text, int at); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 7fa29d312e..1aaea98798 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2010,7 +2010,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { if (!k->is_pressed()) return; - if (k->get_alt() || k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) + if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) return; if (!root) return; @@ -2025,48 +2025,47 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { break; \ } case KEY_RIGHT: { + bool dobreak = true; //TreeItem *next = NULL; if (!selected_item) break; - if (select_mode == SELECT_ROW) + if (select_mode == SELECT_ROW) { EXIT_BREAK; - if (selected_col >= (columns.size() - 1)) + } + if (selected_col > (columns.size() - 1)) { EXIT_BREAK; - if (select_mode == SELECT_MULTI) { - selected_col++; - emit_signal("cell_selected"); + } + if (k->get_alt()) { + selected_item->set_collapsed(false); + TreeItem *next = selected_item->get_children(); + while (next && next != selected_item->next) { + next->set_collapsed(false); + next = next->get_next_visible(); + } + } else if (selected_col == (columns.size() - 1)) { + if (selected_item->get_children() != NULL && selected_item->is_collapsed()) { + selected_item->set_collapsed(false); + } else { + selected_col = 0; + dobreak = false; // fall through to key_down + } } else { + if (select_mode == SELECT_MULTI) { + selected_col++; + emit_signal("cell_selected"); + } else { - selected_item->select(selected_col + 1); + selected_item->select(selected_col + 1); + } } - update(); ensure_cursor_is_visible(); accept_event(); - - } break; - case KEY_LEFT: { - - //TreeItem *next = NULL; - if (!selected_item) + if (dobreak) { break; - if (select_mode == SELECT_ROW) - EXIT_BREAK; - if (selected_col <= 0) - EXIT_BREAK; - if (select_mode == SELECT_MULTI) { - selected_col--; - emit_signal("cell_selected"); - } else { - - selected_item->select(selected_col - 1); } - - update(); - accept_event(); - - } break; + } case KEY_DOWN: { TreeItem *next = NULL; @@ -2113,6 +2112,48 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { accept_event(); } break; + case KEY_LEFT: { + bool dobreak = true; + + //TreeItem *next = NULL; + if (!selected_item) + break; + if (select_mode == SELECT_ROW) { + EXIT_BREAK; + } + if (selected_col < 0) { + EXIT_BREAK; + } + if (k->get_alt()) { + selected_item->set_collapsed(true); + TreeItem *next = selected_item->get_children(); + while (next && next != selected_item->next) { + next->set_collapsed(true); + next = next->get_next_visible(); + } + } else if (selected_col == 0) { + if (selected_item->get_children() != NULL && !selected_item->is_collapsed()) { + selected_item->set_collapsed(true); + } else { + selected_col = columns.size() - 1; + dobreak = false; // fall through to key_up + } + } else { + if (select_mode == SELECT_MULTI) { + selected_col--; + emit_signal("cell_selected"); + } else { + + selected_item->select(selected_col - 1); + } + } + update(); + accept_event(); + + if (dobreak) { + break; + } + } case KEY_UP: { TreeItem *prev = NULL; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 1272e5a946..2fbd5ebdd3 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -879,7 +879,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("minus", "GraphEdit", make_icon(icon_zoom_less_png)); theme->set_icon("reset", "GraphEdit", make_icon(icon_zoom_reset_png)); theme->set_icon("more", "GraphEdit", make_icon(icon_zoom_more_png)); - theme->set_icon("snap", "GraphEdit", make_icon(icon_snap_png)); + theme->set_icon("SnapGrid", "GraphEdit", make_icon(icon_snap_grid_png)); theme->set_stylebox("bg", "GraphEdit", make_stylebox(tree_bg_png, 4, 4, 4, 5)); theme->set_color("grid_minor", "GraphEdit", Color(1, 1, 1, 0.05)); theme->set_color("grid_major", "GraphEdit", Color(1, 1, 1, 0.2)); diff --git a/scene/resources/default_theme/icon_snap.png b/scene/resources/default_theme/icon_snap_grid.png Binary files differindex 93194d34e7..44db9bdfdc 100644 --- a/scene/resources/default_theme/icon_snap.png +++ b/scene/resources/default_theme/icon_snap_grid.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index bed4bdb760..6643b4ccc1 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -182,8 +182,8 @@ static const unsigned char icon_reload_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x1, 0x59, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0x92, 0x31, 0x4b, 0x3, 0x31, 0x18, 0x86, 0x9f, 0x5c, 0xe, 0xec, 0x20, 0x76, 0x70, 0x39, 0xd0, 0xe3, 0xba, 0x74, 0x51, 0x41, 0xdd, 0xfc, 0x7, 0xba, 0xb8, 0x8, 0x52, 0xec, 0x2e, 0x4e, 0x3a, 0x88, 0x3f, 0xa3, 0xa3, 0x53, 0x7, 0x47, 0x67, 0x41, 0x17, 0xdd, 0x9c, 0x5c, 0x3b, 0xd8, 0x82, 0x64, 0x68, 0xca, 0xd5, 0x55, 0x11, 0x3c, 0x1a, 0x87, 0x24, 0x2e, 0xd7, 0x72, 0x9e, 0x9e, 0xab, 0xbe, 0xd3, 0xc7, 0x1b, 0x9e, 0x37, 0xf9, 0xbe, 0x7c, 0xf0, 0xd7, 0x12, 0x3f, 0x99, 0x4a, 0xa9, 0xb9, 0x30, 0xc, 0x8f, 0x84, 0x10, 0x7, 0xc0, 0x5a, 0x6e, 0x3f, 0x3a, 0xe7, 0x2e, 0xad, 0xb5, 0xdd, 0x66, 0xb3, 0xf9, 0x51, 0x19, 0x90, 0xa6, 0xe9, 0x92, 0xb5, 0xf6, 0x6, 0x58, 0xaf, 0xb8, 0xb4, 0x27, 0xa5, 0xdc, 0x8d, 0xe3, 0xf8, 0x19, 0x20, 0x28, 0xdf, 0x5c, 0x80, 0x53, 0x60, 0xdf, 0x18, 0x53, 0x37, 0xc6, 0xd4, 0xbd, 0xf7, 0x7b, 0xc0, 0x13, 0xb0, 0x61, 0xad, 0xbd, 0x56, 0x4a, 0xcd, 0x1, 0x84, 0xc5, 0x80, 0x30, 0xc, 0x8f, 0xa6, 0xb0, 0x94, 0x72, 0x33, 0x8e, 0xe3, 0x97, 0xc2, 0xf1, 0xd5, 0x68, 0x34, 0xba, 0xf7, 0xde, 0xf7, 0x80, 0xd, 0x29, 0xe5, 0x21, 0x70, 0xfe, 0xe5, 0x5, 0x42, 0x88, 0x76, 0x5e, 0x9e, 0x96, 0x60, 0x0, 0x92, 0x24, 0x79, 0x75, 0xce, 0x9d, 0x1, 0x4, 0x41, 0xd0, 0xfe, 0xd6, 0x2, 0xb0, 0x2, 0x60, 0x8c, 0xb9, 0xab, 0xe8, 0x1f, 0x6b, 0xed, 0x6d, 0x5e, 0xae, 0xce, 0x2, 0xb4, 0xd6, 0x17, 0x5a, 0x6b, 0x7, 0xcc, 0x3, 0xd4, 0x6a, 0xb5, 0x37, 0xad, 0xf5, 0xc5, 0x4f, 0x1, 0x41, 0x10, 0x7c, 0x19, 0x7c, 0x90, 0x3, 0xc7, 0xc0, 0xa0, 0xe0, 0xf, 0x72, 0xef, 0x9b, 0x84, 0x10, 0xdb, 0x79, 0xd9, 0x9f, 0x5, 0x44, 0x51, 0x94, 0x9, 0x21, 0x5a, 0x40, 0x6, 0x64, 0x42, 0x88, 0x56, 0x14, 0x45, 0x59, 0x19, 0x1e, 0x8f, 0xc7, 0x8b, 0x52, 0xca, 0xe, 0x80, 0x73, 0xee, 0x12, 0xa, 0xbf, 0x90, 0x24, 0x49, 0x7f, 0x38, 0x1c, 0x1e, 0x3, 0x34, 0x1a, 0x8d, 0x7e, 0x11, 0x54, 0x4a, 0x2d, 0x48, 0x29, 0x77, 0xac, 0xb5, 0x1d, 0xef, 0xfd, 0x32, 0xd0, 0x9b, 0x4c, 0x26, 0x5d, 0xa8, 0xd8, 0xc4, 0xb2, 0xf2, 0xf9, 0x4c, 0x55, 0xbd, 0x48, 0xbf, 0xe8, 0x1d, 0x78, 0x70, 0xce, 0x9d, 0x64, 0x59, 0xb6, 0x35, 0x85, 0xff, 0x87, 0x3e, 0x1, 0x53, 0x7, 0x87, 0x11, 0xd3, 0x3a, 0x9b, 0x9e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; -static const unsigned char icon_snap_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xad, 0x90, 0xbd, 0xa, 0xc2, 0x30, 0x14, 0x85, 0xbf, 0x5b, 0x5c, 0x23, 0xe8, 0x6c, 0x9f, 0xc1, 0xb7, 0xd0, 0x47, 0xd1, 0x47, 0x70, 0x48, 0xa1, 0x43, 0x57, 0xe9, 0xd3, 0x88, 0x93, 0xef, 0xe0, 0xea, 0x5c, 0x9d, 0x1d, 0xb2, 0x96, 0xc6, 0xa1, 0x9, 0xd4, 0xd8, 0xd8, 0x4a, 0xfd, 0x20, 0x10, 0xee, 0xcf, 0xe1, 0xdc, 0x3, 0x1d, 0x8c, 0x31, 0xd6, 0x18, 0x63, 0x9, 0x88, 0xd5, 0x1, 0x92, 0xbe, 0xe2, 0x2f, 0x4c, 0x16, 0x90, 0x98, 0xb5, 0x21, 0x94, 0x52, 0xf2, 0x17, 0x7, 0x6f, 0x7c, 0xb, 0x2b, 0xc6, 0x64, 0x7, 0xb3, 0xa1, 0x1, 0x5b, 0x14, 0x29, 0x50, 0x2, 0x1b, 0x0, 0x44, 0x2e, 0x34, 0xcd, 0x41, 0xb2, 0xec, 0x6, 0x20, 0xdd, 0x61, 0x6f, 0xdf, 0x7, 0xe4, 0x96, 0xaf, 0xc0, 0x32, 0xd0, 0x7d, 0x2, 0x6b, 0xd1, 0xba, 0x4a, 0xfc, 0xdd, 0x91, 0xdb, 0x4b, 0xb7, 0x7c, 0x2, 0x56, 0xd4, 0x75, 0xa, 0x9c, 0x81, 0x5, 0x70, 0x84, 0xe1, 0xc, 0x5a, 0xdb, 0x75, 0xbd, 0x17, 0xad, 0x1f, 0x92, 0xe7, 0x77, 0x60, 0xe7, 0x7a, 0x5b, 0x80, 0x44, 0x29, 0x25, 0xfe, 0xf5, 0x8, 0x28, 0x0, 0xb7, 0xd8, 0x46, 0xa0, 0x75, 0xe5, 0xbe, 0xf3, 0x31, 0xe, 0x7e, 0x23, 0xcc, 0xc2, 0x3a, 0xc2, 0xb9, 0x58, 0xfd, 0x83, 0xc9, 0x2, 0x63, 0x78, 0x1, 0x4a, 0x50, 0x70, 0x86, 0xcc, 0x86, 0x2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +static const unsigned char icon_snap_grid_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc4, 0x0, 0x0, 0xe, 0xc4, 0x1, 0x95, 0x2b, 0xe, 0x1b, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xad, 0x90, 0xbd, 0xa, 0xc2, 0x30, 0x14, 0x85, 0xbf, 0x5b, 0x5c, 0x23, 0xe8, 0x6c, 0x9f, 0xc1, 0xb7, 0xd0, 0x47, 0xd1, 0x47, 0x70, 0x48, 0xa1, 0x43, 0x57, 0xe9, 0xd3, 0x88, 0x93, 0xef, 0xe0, 0xea, 0x5c, 0x9d, 0x1d, 0xb2, 0x96, 0xc6, 0xa1, 0x9, 0xd4, 0xd8, 0xd8, 0x4a, 0xfd, 0x20, 0x10, 0xee, 0xcf, 0xe1, 0xdc, 0x3, 0x1d, 0x8c, 0x31, 0xd6, 0x18, 0x63, 0x9, 0x88, 0xd5, 0x1, 0x92, 0xbe, 0xe2, 0x2f, 0x4c, 0x16, 0x90, 0x98, 0xb5, 0x21, 0x94, 0x52, 0xf2, 0x17, 0x7, 0x6f, 0x7c, 0xb, 0x2b, 0xc6, 0x64, 0x7, 0xb3, 0xa1, 0x1, 0x5b, 0x14, 0x29, 0x50, 0x2, 0x1b, 0x0, 0x44, 0x2e, 0x34, 0xcd, 0x41, 0xb2, 0xec, 0x6, 0x20, 0xdd, 0x61, 0x6f, 0xdf, 0x7, 0xe4, 0x96, 0xaf, 0xc0, 0x32, 0xd0, 0x7d, 0x2, 0x6b, 0xd1, 0xba, 0x4a, 0xfc, 0xdd, 0x91, 0xdb, 0x4b, 0xb7, 0x7c, 0x2, 0x56, 0xd4, 0x75, 0xa, 0x9c, 0x81, 0x5, 0x70, 0x84, 0xe1, 0xc, 0x5a, 0xdb, 0x75, 0xbd, 0x17, 0xad, 0x1f, 0x92, 0xe7, 0x77, 0x60, 0xe7, 0x7a, 0x5b, 0x80, 0x44, 0x29, 0x25, 0xfe, 0xf5, 0x8, 0x28, 0x0, 0xb7, 0xd8, 0x46, 0xa0, 0x75, 0xe5, 0xbe, 0xf3, 0x31, 0xe, 0x7e, 0x23, 0xcc, 0xc2, 0x3a, 0xc2, 0xb9, 0x58, 0xfd, 0x83, 0xc9, 0x2, 0x63, 0x78, 0x1, 0x4a, 0x50, 0x70, 0x86, 0xcc, 0x86, 0x2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; static const unsigned char icon_stop_png[] = { diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 4b728f821a..78efe85e16 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -32,6 +32,7 @@ #include "os/file_access.h" #include "os/os.h" #include "project_settings.h" +#include "servers/audio/audio_driver_dummy.h" #include "servers/audio/effects/audio_effect_compressor.h" #ifdef TOOLS_ENABLED @@ -107,6 +108,7 @@ AudioDriver::AudioDriver() { AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS]; int AudioDriverManager::driver_count = 0; +AudioDriverDummy AudioDriverManager::dummy_driver; void AudioDriverManager::add_driver(AudioDriver *p_driver) { @@ -118,6 +120,43 @@ int AudioDriverManager::get_driver_count() { return driver_count; } + +void AudioDriverManager::initialize(int p_driver) { + AudioDriver *driver; + int failed_driver = -1; + + // Check if there is a selected driver + if (p_driver >= 0 && p_driver < driver_count) { + if (drivers[p_driver]->init() == OK) { + drivers[p_driver]->set_singleton(); + return; + } else { + failed_driver = p_driver; + } + } + + // No selected driver, try them all in order + for (int i = 0; i < driver_count; i++) { + // Don't re-init the driver if it failed above + if (i == failed_driver) { + continue; + } + + if (drivers[i]->init() == OK) { + drivers[i]->set_singleton(); + return; + } + } + + // Fallback to our dummy driver + if (dummy_driver.init() == OK) { + ERR_PRINT("AudioDriverManager: all drivers failed, falling back to dummy driver"); + dummy_driver.set_singleton(); + } else { + ERR_PRINT("AudioDriverManager: dummy driver faild to init()"); + } +} + AudioDriver *AudioDriverManager::get_driver(int p_driver) { ERR_FAIL_INDEX_V(p_driver, driver_count, NULL); diff --git a/servers/audio_server.h b/servers/audio_server.h index c479d09a3c..55e9367308 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -35,6 +35,8 @@ #include "servers/audio/audio_effect.h" #include "variant.h" +class AudioDriverDummy; + class AudioDriver { static AudioDriver *singleton; @@ -90,8 +92,11 @@ class AudioDriverManager { static AudioDriver *drivers[MAX_DRIVERS]; static int driver_count; + static AudioDriverDummy dummy_driver; + public: static void add_driver(AudioDriver *p_driver); + static void initialize(int p_driver); static int get_driver_count(); static AudioDriver *get_driver(int p_driver); }; |