diff options
84 files changed, 2358 insertions, 1568 deletions
diff --git a/core/dictionary.cpp b/core/dictionary.cpp index 42d9eab310..9cc913fa0d 100644 --- a/core/dictionary.cpp +++ b/core/dictionary.cpp @@ -135,12 +135,7 @@ bool Dictionary::has_all(const Array &p_keys) const { return true; } -void Dictionary::erase(const Variant &p_key) { - - _p->variant_map.erase(p_key); -} - -bool Dictionary::erase_checked(const Variant &p_key) { +bool Dictionary::erase(const Variant &p_key) { return _p->variant_map.erase(p_key); } diff --git a/core/dictionary.h b/core/dictionary.h index 00ec67fb99..dbf2233819 100644 --- a/core/dictionary.h +++ b/core/dictionary.h @@ -65,8 +65,7 @@ public: bool has(const Variant &p_key) const; bool has_all(const Array &p_keys) const; - void erase(const Variant &p_key); - bool erase_checked(const Variant &p_key); + bool erase(const Variant &p_key); bool operator==(const Dictionary &p_dictionary) const; diff --git a/core/image.cpp b/core/image.cpp index 65905c83e8..c94f2c3534 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -36,8 +36,8 @@ #include "math_funcs.h" #include "print_string.h" +#include "io/resource_loader.h" #include "thirdparty/misc/hq2x.h" - #include <stdio.h> const char *Image::format_names[Image::FORMAT_MAX] = { @@ -1582,7 +1582,11 @@ Image::AlphaMode Image::detect_alpha() const { } Error Image::load(const String &p_path) { - +#ifdef DEBUG_ENABLED + if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) { + WARN_PRINTS("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource."); + } +#endif return ImageLoader::load_image(p_path, this); } diff --git a/core/image.h b/core/image.h index c8dd647c31..c450e88290 100644 --- a/core/image.h +++ b/core/image.h @@ -33,7 +33,7 @@ #include "color.h" #include "dvector.h" -#include "math_2d.h" +#include "rect2.h" #include "resource.h" /** diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index 226b4d572b..a689c7238a 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -31,7 +31,7 @@ #ifndef CAMERA_MATRIX_H #define CAMERA_MATRIX_H -#include "math_2d.h" +#include "rect2.h" #include "transform.h" /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/core/math/delaunay.h b/core/math/delaunay.h index 13fbc0c6ae..46535d5ce9 100644 --- a/core/math/delaunay.h +++ b/core/math/delaunay.h @@ -1,7 +1,7 @@ #ifndef DELAUNAY_H #define DELAUNAY_H -#include "math_2d.h" +#include "rect2.h" class Delaunay2D { public: diff --git a/core/math/geometry.h b/core/math/geometry.h index 186a05fb37..83b9467a30 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -33,9 +33,9 @@ #include "dvector.h" #include "face3.h" -#include "math_2d.h" #include "object.h" #include "print_string.h" +#include "rect2.h" #include "triangulate.h" #include "vector.h" #include "vector3.h" diff --git a/core/math/math_2d.h b/core/math/math_2d.h deleted file mode 100644 index 25c39e5d7a..0000000000 --- a/core/math/math_2d.h +++ /dev/null @@ -1,1002 +0,0 @@ -/*************************************************************************/ -/* math_2d.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 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 MATH_2D_H -#define MATH_2D_H - -#include "math_funcs.h" -#include "ustring.h" -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -enum Margin { - - MARGIN_LEFT, - MARGIN_TOP, - MARGIN_RIGHT, - MARGIN_BOTTOM -}; - -enum Corner { - - CORNER_TOP_LEFT, - CORNER_TOP_RIGHT, - CORNER_BOTTOM_RIGHT, - CORNER_BOTTOM_LEFT -}; - -enum Orientation { - - HORIZONTAL, - VERTICAL -}; - -enum HAlign { - - HALIGN_LEFT, - HALIGN_CENTER, - HALIGN_RIGHT -}; - -enum VAlign { - - VALIGN_TOP, - VALIGN_CENTER, - VALIGN_BOTTOM -}; - -struct Vector2 { - - union { - real_t x; - real_t width; - }; - union { - real_t y; - real_t height; - }; - - _FORCE_INLINE_ real_t &operator[](int p_idx) { - return p_idx ? y : x; - } - _FORCE_INLINE_ const real_t &operator[](int p_idx) const { - return p_idx ? y : x; - } - - void normalize(); - Vector2 normalized() const; - bool is_normalized() const; - - real_t length() const; - real_t length_squared() const; - - real_t distance_to(const Vector2 &p_vector2) const; - real_t distance_squared_to(const Vector2 &p_vector2) const; - real_t angle_to(const Vector2 &p_vector2) const; - real_t angle_to_point(const Vector2 &p_vector2) const; - - real_t dot(const Vector2 &p_other) const; - real_t cross(const Vector2 &p_other) const; - Vector2 project(const Vector2 &p_vec) const; - - Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const; - - Vector2 clamped(real_t p_len) const; - - _FORCE_INLINE_ static Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t); - _FORCE_INLINE_ Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const; - _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_b, real_t p_t) const; - Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const; - - Vector2 slide(const Vector2 &p_normal) const; - Vector2 bounce(const Vector2 &p_normal) const; - Vector2 reflect(const Vector2 &p_normal) const; - - Vector2 operator+(const Vector2 &p_v) const; - void operator+=(const Vector2 &p_v); - Vector2 operator-(const Vector2 &p_v) const; - void operator-=(const Vector2 &p_v); - Vector2 operator*(const Vector2 &p_v1) const; - - Vector2 operator*(const real_t &rvalue) const; - void operator*=(const real_t &rvalue); - void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; } - - Vector2 operator/(const Vector2 &p_v1) const; - - Vector2 operator/(const real_t &rvalue) const; - - void operator/=(const real_t &rvalue); - - Vector2 operator-() const; - - bool operator==(const Vector2 &p_vec2) const; - bool operator!=(const Vector2 &p_vec2) const; - - bool operator<(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } - bool operator<=(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y <= p_vec2.y) : (x <= p_vec2.x); } - - real_t angle() const; - - void set_rotation(real_t p_radians) { - - x = Math::cos(p_radians); - y = Math::sin(p_radians); - } - - _FORCE_INLINE_ Vector2 abs() const { - - return Vector2(Math::abs(x), Math::abs(y)); - } - - Vector2 rotated(real_t p_by) const; - Vector2 tangent() const { - - return Vector2(y, -x); - } - - Vector2 floor() const; - Vector2 ceil() const; - Vector2 round() const; - Vector2 snapped(const Vector2 &p_by) const; - real_t aspect() const { return width / height; } - - operator String() const { return String::num(x) + ", " + String::num(y); } - - _FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) { - x = p_x; - y = p_y; - } - _FORCE_INLINE_ Vector2() { - x = 0; - y = 0; - } -}; - -_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const { - - return p_vec - *this * (dot(p_vec) - p_d); -} - -_FORCE_INLINE_ Vector2 operator*(real_t p_scalar, const Vector2 &p_vec) { - - return p_vec * p_scalar; -} - -_FORCE_INLINE_ Vector2 Vector2::operator+(const Vector2 &p_v) const { - - return Vector2(x + p_v.x, y + p_v.y); -} -_FORCE_INLINE_ void Vector2::operator+=(const Vector2 &p_v) { - - x += p_v.x; - y += p_v.y; -} -_FORCE_INLINE_ Vector2 Vector2::operator-(const Vector2 &p_v) const { - - return Vector2(x - p_v.x, y - p_v.y); -} -_FORCE_INLINE_ void Vector2::operator-=(const Vector2 &p_v) { - - x -= p_v.x; - y -= p_v.y; -} - -_FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const { - - return Vector2(x * p_v1.x, y * p_v1.y); -}; - -_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const { - - return Vector2(x * rvalue, y * rvalue); -}; -_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) { - - x *= rvalue; - y *= rvalue; -}; - -_FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const { - - return Vector2(x / p_v1.x, y / p_v1.y); -}; - -_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const { - - return Vector2(x / rvalue, y / rvalue); -}; - -_FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) { - - x /= rvalue; - y /= rvalue; -}; - -_FORCE_INLINE_ Vector2 Vector2::operator-() const { - - return Vector2(-x, -y); -} - -_FORCE_INLINE_ bool Vector2::operator==(const Vector2 &p_vec2) const { - - return x == p_vec2.x && y == p_vec2.y; -} -_FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const { - - return x != p_vec2.x || y != p_vec2.y; -} - -Vector2 Vector2::linear_interpolate(const Vector2 &p_b, real_t p_t) const { - - Vector2 res = *this; - - res.x += (p_t * (p_b.x - x)); - res.y += (p_t * (p_b.y - y)); - - return res; -} - -Vector2 Vector2::slerp(const Vector2 &p_b, real_t p_t) const { -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(is_normalized() == false, Vector2()); -#endif - real_t theta = angle_to(p_b); - return rotated(theta * p_t); -} - -Vector2 Vector2::linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t) { - - Vector2 res = p_a; - - res.x += (p_t * (p_b.x - p_a.x)); - res.y += (p_t * (p_b.y - p_a.y)); - - return res; -} - -typedef Vector2 Size2; -typedef Vector2 Point2; - -struct Transform2D; - -struct Rect2 { - - Point2 position; - Size2 size; - - const Vector2 &get_position() const { return position; } - void set_position(const Vector2 &p_pos) { position = p_pos; } - const Vector2 &get_size() const { return size; } - void set_size(const Vector2 &p_size) { size = p_size; } - - real_t get_area() const { return size.width * size.height; } - - inline bool intersects(const Rect2 &p_rect) const { - if (position.x >= (p_rect.position.x + p_rect.size.width)) - return false; - if ((position.x + size.width) <= p_rect.position.x) - return false; - if (position.y >= (p_rect.position.y + p_rect.size.height)) - return false; - if ((position.y + size.height) <= p_rect.position.y) - return false; - - return true; - } - - inline real_t distance_to(const Vector2 &p_point) const { - - real_t dist = 0.0; - bool inside = true; - - if (p_point.x < position.x) { - real_t d = position.x - p_point.x; - dist = inside ? d : MIN(dist, d); - inside = false; - } - if (p_point.y < position.y) { - real_t d = position.y - p_point.y; - dist = inside ? d : MIN(dist, d); - inside = false; - } - if (p_point.x >= (position.x + size.x)) { - real_t d = p_point.x - (position.x + size.x); - dist = inside ? d : MIN(dist, d); - inside = false; - } - if (p_point.y >= (position.y + size.y)) { - real_t d = p_point.y - (position.y + size.y); - dist = inside ? d : MIN(dist, d); - inside = false; - } - - if (inside) - return 0; - else - return dist; - } - - _FORCE_INLINE_ bool intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const; - - bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = NULL, Point2 *r_normal = NULL) const; - - inline bool encloses(const Rect2 &p_rect) const { - - return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && - ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) && - ((p_rect.position.y + p_rect.size.y) < (position.y + size.y)); - } - - inline bool has_no_area() const { - - return (size.x <= 0 || size.y <= 0); - } - inline Rect2 clip(const Rect2 &p_rect) const { /// return a clipped rect - - Rect2 new_rect = p_rect; - - if (!intersects(new_rect)) - return Rect2(); - - new_rect.position.x = MAX(p_rect.position.x, position.x); - new_rect.position.y = MAX(p_rect.position.y, position.y); - - Point2 p_rect_end = p_rect.position + p_rect.size; - Point2 end = position + size; - - new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x; - new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y; - - return new_rect; - } - - inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect - - Rect2 new_rect; - - new_rect.position.x = MIN(p_rect.position.x, position.x); - new_rect.position.y = MIN(p_rect.position.y, position.y); - - new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, position.x + size.x); - new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, position.y + size.y); - - new_rect.size = new_rect.size - new_rect.position; //make relative again - - return new_rect; - }; - inline bool has_point(const Point2 &p_point) const { - if (p_point.x < position.x) - return false; - if (p_point.y < position.y) - return false; - - if (p_point.x >= (position.x + size.x)) - return false; - if (p_point.y >= (position.y + size.y)) - return false; - - return true; - } - - inline bool no_area() const { return (size.width <= 0 || size.height <= 0); } - - bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; } - bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } - - inline Rect2 grow(real_t p_by) const { - - Rect2 g = *this; - g.position.x -= p_by; - g.position.y -= p_by; - g.size.width += p_by * 2; - g.size.height += p_by * 2; - return g; - } - - inline Rect2 grow_margin(Margin p_margin, real_t p_amount) const { - Rect2 g = *this; - g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0, - (MARGIN_TOP == p_margin) ? p_amount : 0, - (MARGIN_RIGHT == p_margin) ? p_amount : 0, - (MARGIN_BOTTOM == p_margin) ? p_amount : 0); - return g; - } - - inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const { - - Rect2 g = *this; - g.position.x -= p_left; - g.position.y -= p_top; - g.size.width += p_left + p_right; - g.size.height += p_top + p_bottom; - - return g; - } - - inline Rect2 expand(const Vector2 &p_vector) const { - - Rect2 r = *this; - r.expand_to(p_vector); - return r; - } - - inline void expand_to(const Vector2 &p_vector) { //in place function for speed - - Vector2 begin = position; - Vector2 end = position + size; - - if (p_vector.x < begin.x) - begin.x = p_vector.x; - if (p_vector.y < begin.y) - begin.y = p_vector.y; - - if (p_vector.x > end.x) - end.x = p_vector.x; - if (p_vector.y > end.y) - end.y = p_vector.y; - - position = begin; - size = end - begin; - } - - inline Rect2 abs() const { - - return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs()); - } - - operator String() const { return String(position) + ", " + String(size); } - - Rect2() {} - Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) : - position(Point2(p_x, p_y)), - size(Size2(p_width, p_height)) { - } - Rect2(const Point2 &p_pos, const Size2 &p_size) : - position(p_pos), - size(p_size) { - } -}; - -/* INTEGER STUFF */ - -struct Point2i { - - union { - int x; - int width; - }; - union { - int y; - int height; - }; - - _FORCE_INLINE_ int &operator[](int p_idx) { - return p_idx ? y : x; - } - _FORCE_INLINE_ const int &operator[](int p_idx) const { - return p_idx ? y : x; - } - - Point2i operator+(const Point2i &p_v) const; - void operator+=(const Point2i &p_v); - Point2i operator-(const Point2i &p_v) const; - void operator-=(const Point2i &p_v); - Point2i operator*(const Point2i &p_v1) const; - - Point2i operator*(const int &rvalue) const; - void operator*=(const int &rvalue); - - Point2i operator/(const Point2i &p_v1) const; - - Point2i operator/(const int &rvalue) const; - - void operator/=(const int &rvalue); - - Point2i operator-() const; - bool operator<(const Point2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } - bool operator>(const Point2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); } - - bool operator==(const Point2i &p_vec2) const; - bool operator!=(const Point2i &p_vec2) const; - - real_t get_aspect() const { return width / (real_t)height; } - - operator String() const { return String::num(x) + ", " + String::num(y); } - - operator Vector2() const { return Vector2(x, y); } - inline Point2i(const Vector2 &p_vec2) { - x = (int)p_vec2.x; - y = (int)p_vec2.y; - } - inline Point2i(int p_x, int p_y) { - x = p_x; - y = p_y; - } - inline Point2i() { - x = 0; - y = 0; - } -}; - -typedef Point2i Size2i; - -struct Rect2i { - - Point2i position; - Size2i size; - - const Point2i &get_position() const { return position; } - void set_position(const Point2i &p_pos) { position = p_pos; } - const Point2i &get_size() const { return size; } - void set_size(const Point2i &p_size) { size = p_size; } - - int get_area() const { return size.width * size.height; } - - inline bool intersects(const Rect2i &p_rect) const { - if (position.x > (p_rect.position.x + p_rect.size.width)) - return false; - if ((position.x + size.width) < p_rect.position.x) - return false; - if (position.y > (p_rect.position.y + p_rect.size.height)) - return false; - if ((position.y + size.height) < p_rect.position.y) - return false; - - return true; - } - - inline bool encloses(const Rect2i &p_rect) const { - - return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && - ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) && - ((p_rect.position.y + p_rect.size.y) < (position.y + size.y)); - } - - inline bool has_no_area() const { - - return (size.x <= 0 || size.y <= 0); - } - inline Rect2i clip(const Rect2i &p_rect) const { /// return a clipped rect - - Rect2i new_rect = p_rect; - - if (!intersects(new_rect)) - return Rect2i(); - - new_rect.position.x = MAX(p_rect.position.x, position.x); - new_rect.position.y = MAX(p_rect.position.y, position.y); - - Point2 p_rect_end = p_rect.position + p_rect.size; - Point2 end = position + size; - - new_rect.size.x = (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x); - new_rect.size.y = (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y); - - return new_rect; - } - - inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect - - Rect2i new_rect; - - new_rect.position.x = MIN(p_rect.position.x, position.x); - new_rect.position.y = MIN(p_rect.position.y, position.y); - - new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, position.x + size.x); - new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, position.y + size.y); - - new_rect.size = new_rect.size - new_rect.position; //make relative again - - return new_rect; - }; - bool has_point(const Point2 &p_point) const { - if (p_point.x < position.x) - return false; - if (p_point.y < position.y) - return false; - - if (p_point.x >= (position.x + size.x)) - return false; - if (p_point.y >= (position.y + size.y)) - return false; - - return true; - } - - bool no_area() { return (size.width <= 0 || size.height <= 0); } - - bool operator==(const Rect2i &p_rect) const { return position == p_rect.position && size == p_rect.size; } - bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; } - - Rect2i grow(int p_by) const { - - Rect2i g = *this; - g.position.x -= p_by; - g.position.y -= p_by; - g.size.width += p_by * 2; - g.size.height += p_by * 2; - return g; - } - - inline void expand_to(const Point2i &p_vector) { - - Point2i begin = position; - Point2i end = position + size; - - if (p_vector.x < begin.x) - begin.x = p_vector.x; - if (p_vector.y < begin.y) - begin.y = p_vector.y; - - if (p_vector.x > end.x) - end.x = p_vector.x; - if (p_vector.y > end.y) - end.y = p_vector.y; - - position = begin; - size = end - begin; - } - - operator String() const { return String(position) + ", " + String(size); } - - operator Rect2() const { return Rect2(position, size); } - Rect2i(const Rect2 &p_r2) : - position(p_r2.position), - size(p_r2.size) { - } - Rect2i() {} - Rect2i(int p_x, int p_y, int p_width, int p_height) : - position(Point2(p_x, p_y)), - size(Size2(p_width, p_height)) { - } - Rect2i(const Point2 &p_pos, const Size2 &p_size) : - position(p_pos), - size(p_size) { - } -}; - -struct Transform2D { - // Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper": - // M = (elements[0][0] elements[1][0]) - // (elements[0][1] elements[1][1]) - // This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as elements[i]. - // Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to elements[1][0] here. - // This requires additional care when working with explicit indices. - // See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading. - - // Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down, - // and angle is measure from +X to +Y in a clockwise-fashion. - - Vector2 elements[3]; - - _FORCE_INLINE_ real_t tdotx(const Vector2 &v) const { return elements[0][0] * v.x + elements[1][0] * v.y; } - _FORCE_INLINE_ real_t tdoty(const Vector2 &v) const { return elements[0][1] * v.x + elements[1][1] * v.y; } - - const Vector2 &operator[](int p_idx) const { return elements[p_idx]; } - Vector2 &operator[](int p_idx) { return elements[p_idx]; } - - _FORCE_INLINE_ Vector2 get_axis(int p_axis) const { - ERR_FAIL_INDEX_V(p_axis, 3, Vector2()); - return elements[p_axis]; - } - _FORCE_INLINE_ void set_axis(int p_axis, const Vector2 &p_vec) { - ERR_FAIL_INDEX(p_axis, 3); - elements[p_axis] = p_vec; - } - - void invert(); - Transform2D inverse() const; - - void affine_invert(); - Transform2D affine_inverse() const; - - void set_rotation(real_t p_rot); - real_t get_rotation() const; - _FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale); - void rotate(real_t p_phi); - - void scale(const Size2 &p_scale); - void scale_basis(const Size2 &p_scale); - void translate(real_t p_tx, real_t p_ty); - void translate(const Vector2 &p_translation); - - real_t basis_determinant() const; - - Size2 get_scale() const; - - _FORCE_INLINE_ const Vector2 &get_origin() const { return elements[2]; } - _FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { elements[2] = p_origin; } - - Transform2D scaled(const Size2 &p_scale) const; - Transform2D basis_scaled(const Size2 &p_scale) const; - Transform2D translated(const Vector2 &p_offset) const; - Transform2D rotated(real_t p_phi) const; - - Transform2D untranslated() const; - - void orthonormalize(); - Transform2D orthonormalized() const; - - bool operator==(const Transform2D &p_transform) const; - bool operator!=(const Transform2D &p_transform) const; - - void operator*=(const Transform2D &p_transform); - Transform2D operator*(const Transform2D &p_transform) const; - - Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const; - - _FORCE_INLINE_ Vector2 basis_xform(const Vector2 &p_vec) const; - _FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2 &p_vec) const; - _FORCE_INLINE_ Vector2 xform(const Vector2 &p_vec) const; - _FORCE_INLINE_ Vector2 xform_inv(const Vector2 &p_vec) const; - _FORCE_INLINE_ Rect2 xform(const Rect2 &p_rect) const; - _FORCE_INLINE_ Rect2 xform_inv(const Rect2 &p_rect) const; - - operator String() const; - - Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { - - elements[0][0] = xx; - elements[0][1] = xy; - elements[1][0] = yx; - elements[1][1] = yy; - elements[2][0] = ox; - elements[2][1] = oy; - } - - Transform2D(real_t p_rot, const Vector2 &p_pos); - Transform2D() { - elements[0][0] = 1.0; - elements[1][1] = 1.0; - } -}; - -bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const { - - //SAT intersection between local and transformed rect2 - - Vector2 xf_points[4] = { - p_xform.xform(p_rect.position), - p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y)), - p_xform.xform(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)), - p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)), - }; - - real_t low_limit; - - //base rect2 first (faster) - - if (xf_points[0].y > position.y) - goto next1; - if (xf_points[1].y > position.y) - goto next1; - if (xf_points[2].y > position.y) - goto next1; - if (xf_points[3].y > position.y) - goto next1; - - return false; - -next1: - - low_limit = position.y + size.y; - - if (xf_points[0].y < low_limit) - goto next2; - if (xf_points[1].y < low_limit) - goto next2; - if (xf_points[2].y < low_limit) - goto next2; - if (xf_points[3].y < low_limit) - goto next2; - - return false; - -next2: - - if (xf_points[0].x > position.x) - goto next3; - if (xf_points[1].x > position.x) - goto next3; - if (xf_points[2].x > position.x) - goto next3; - if (xf_points[3].x > position.x) - goto next3; - - return false; - -next3: - - low_limit = position.x + size.x; - - if (xf_points[0].x < low_limit) - goto next4; - if (xf_points[1].x < low_limit) - goto next4; - if (xf_points[2].x < low_limit) - goto next4; - if (xf_points[3].x < low_limit) - goto next4; - - return false; - -next4: - - Vector2 xf_points2[4] = { - position, - Vector2(position.x + size.x, position.y), - Vector2(position.x, position.y + size.y), - Vector2(position.x + size.x, position.y + size.y), - }; - - real_t maxa = p_xform.elements[0].dot(xf_points2[0]); - real_t mina = maxa; - - real_t dp = p_xform.elements[0].dot(xf_points2[1]); - maxa = MAX(dp, maxa); - mina = MIN(dp, mina); - - dp = p_xform.elements[0].dot(xf_points2[2]); - maxa = MAX(dp, maxa); - mina = MIN(dp, mina); - - dp = p_xform.elements[0].dot(xf_points2[3]); - maxa = MAX(dp, maxa); - mina = MIN(dp, mina); - - real_t maxb = p_xform.elements[0].dot(xf_points[0]); - real_t minb = maxb; - - dp = p_xform.elements[0].dot(xf_points[1]); - maxb = MAX(dp, maxb); - minb = MIN(dp, minb); - - dp = p_xform.elements[0].dot(xf_points[2]); - maxb = MAX(dp, maxb); - minb = MIN(dp, minb); - - dp = p_xform.elements[0].dot(xf_points[3]); - maxb = MAX(dp, maxb); - minb = MIN(dp, minb); - - if (mina > maxb) - return false; - if (minb > maxa) - return false; - - maxa = p_xform.elements[1].dot(xf_points2[0]); - mina = maxa; - - dp = p_xform.elements[1].dot(xf_points2[1]); - maxa = MAX(dp, maxa); - mina = MIN(dp, mina); - - dp = p_xform.elements[1].dot(xf_points2[2]); - maxa = MAX(dp, maxa); - mina = MIN(dp, mina); - - dp = p_xform.elements[1].dot(xf_points2[3]); - maxa = MAX(dp, maxa); - mina = MIN(dp, mina); - - maxb = p_xform.elements[1].dot(xf_points[0]); - minb = maxb; - - dp = p_xform.elements[1].dot(xf_points[1]); - maxb = MAX(dp, maxb); - minb = MIN(dp, minb); - - dp = p_xform.elements[1].dot(xf_points[2]); - maxb = MAX(dp, maxb); - minb = MIN(dp, minb); - - dp = p_xform.elements[1].dot(xf_points[3]); - maxb = MAX(dp, maxb); - minb = MIN(dp, minb); - - if (mina > maxb) - return false; - if (minb > maxa) - return false; - - return true; -} - -Vector2 Transform2D::basis_xform(const Vector2 &p_vec) const { - - return Vector2( - tdotx(p_vec), - tdoty(p_vec)); -} - -Vector2 Transform2D::basis_xform_inv(const Vector2 &p_vec) const { - - return Vector2( - elements[0].dot(p_vec), - elements[1].dot(p_vec)); -} - -Vector2 Transform2D::xform(const Vector2 &p_vec) const { - - return Vector2( - tdotx(p_vec), - tdoty(p_vec)) + - elements[2]; -} -Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const { - - Vector2 v = p_vec - elements[2]; - - return Vector2( - elements[0].dot(v), - elements[1].dot(v)); -} -Rect2 Transform2D::xform(const Rect2 &p_rect) const { - - Vector2 x = elements[0] * p_rect.size.x; - Vector2 y = elements[1] * p_rect.size.y; - Vector2 pos = xform(p_rect.position); - - Rect2 new_rect; - new_rect.position = pos; - new_rect.expand_to(pos + x); - new_rect.expand_to(pos + y); - new_rect.expand_to(pos + x + y); - return new_rect; -} - -void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) { - - elements[0][0] = Math::cos(p_rot) * p_scale.x; - elements[1][1] = Math::cos(p_rot) * p_scale.y; - elements[1][0] = -Math::sin(p_rot) * p_scale.y; - elements[0][1] = Math::sin(p_rot) * p_scale.x; -} - -Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const { - - Vector2 ends[4] = { - xform_inv(p_rect.position), - xform_inv(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)), - xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)), - xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y)) - }; - - Rect2 new_rect; - new_rect.position = ends[0]; - new_rect.expand_to(ends[1]); - new_rect.expand_to(ends[2]); - new_rect.expand_to(ends[3]); - - return new_rect; -} - -#endif diff --git a/core/math/math_defs.h b/core/math/math_defs.h index d3484d8d02..a5feee6eb5 100644 --- a/core/math/math_defs.h +++ b/core/math/math_defs.h @@ -36,30 +36,71 @@ #define CMP_NORMALIZE_TOLERANCE 0.000001 #define CMP_POINT_IN_PLANE_EPSILON 0.00001 +#define Math_SQRT12 0.7071067811865475244008443621048490 +#define Math_SQRT2 1.4142135623730950488016887242 +#define Math_LN2 0.6931471805599453094172321215 +#define Math_TAU 6.2831853071795864769252867666 +#define Math_PI 3.1415926535897932384626433833 +#define Math_E 2.7182818284590452353602874714 +#define Math_INF INFINITY +#define Math_NAN NAN + #ifdef DEBUG_ENABLED #define MATH_CHECKS #endif #define USEC_TO_SEC(m_usec) ((m_usec) / 1000000.0) -/** - * "Real" is a type that will be translated to either floats or fixed depending - * on the compilation setting - */ enum ClockDirection { - CLOCKWISE, COUNTERCLOCKWISE }; -#ifdef REAL_T_IS_DOUBLE +enum Orientation { -typedef double real_t; + HORIZONTAL, + VERTICAL +}; -#else +enum HAlign { -typedef float real_t; + HALIGN_LEFT, + HALIGN_CENTER, + HALIGN_RIGHT +}; + +enum VAlign { + + VALIGN_TOP, + VALIGN_CENTER, + VALIGN_BOTTOM +}; +enum Margin { + + MARGIN_LEFT, + MARGIN_TOP, + MARGIN_RIGHT, + MARGIN_BOTTOM +}; + +enum Corner { + + CORNER_TOP_LEFT, + CORNER_TOP_RIGHT, + CORNER_BOTTOM_RIGHT, + CORNER_BOTTOM_LEFT +}; + +/** + * The "Real" type is an abstract type used for real numbers, such as 1.5, + * in contrast to integer numbers. Precision can be controlled with the + * presence or absence of the REAL_T_IS_DOUBLE define. + */ +#ifdef REAL_T_IS_DOUBLE +typedef double real_t; +#else +typedef float real_t; #endif #endif // MATH_DEFS_H diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index f0c0268f31..992084a653 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -39,13 +39,6 @@ #include <float.h> #include <math.h> -#define Math_PI 3.14159265358979323846 -#define Math_TAU 6.28318530717958647692 -#define Math_SQRT12 0.7071067811865475244008443621048490 -#define Math_LN2 0.693147180559945309417 -#define Math_INF INFINITY -#define Math_NAN NAN - class Math { static pcg32_random_t default_pcg; diff --git a/core/math/rect2.cpp b/core/math/rect2.cpp new file mode 100644 index 0000000000..480bccdff1 --- /dev/null +++ b/core/math/rect2.cpp @@ -0,0 +1,240 @@ +/*************************************************************************/ +/* rect2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "transform_2d.h" // Includes rect2.h but Rect2 needs Transform2D + +bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const { + + real_t min = 0, max = 1; + int axis = 0; + real_t sign = 0; + + for (int i = 0; i < 2; i++) { + real_t seg_from = p_from[i]; + real_t seg_to = p_to[i]; + real_t box_begin = position[i]; + real_t box_end = box_begin + size[i]; + real_t cmin, cmax; + real_t csign; + + if (seg_from < seg_to) { + + if (seg_from > box_end || seg_to < box_begin) + return false; + real_t length = seg_to - seg_from; + cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0; + cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1; + csign = -1.0; + + } else { + + if (seg_to > box_end || seg_from < box_begin) + return false; + real_t length = seg_to - seg_from; + cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0; + cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1; + csign = 1.0; + } + + if (cmin > min) { + min = cmin; + axis = i; + sign = csign; + } + if (cmax < max) + max = cmax; + if (max < min) + return false; + } + + Vector2 rel = p_to - p_from; + + if (r_normal) { + Vector2 normal; + normal[axis] = sign; + *r_normal = normal; + } + + if (r_pos) + *r_pos = p_from + rel * min; + + return true; +} + +bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const { + + //SAT intersection between local and transformed rect2 + + Vector2 xf_points[4] = { + p_xform.xform(p_rect.position), + p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y)), + p_xform.xform(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)), + p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)), + }; + + real_t low_limit; + + //base rect2 first (faster) + + if (xf_points[0].y > position.y) + goto next1; + if (xf_points[1].y > position.y) + goto next1; + if (xf_points[2].y > position.y) + goto next1; + if (xf_points[3].y > position.y) + goto next1; + + return false; + +next1: + + low_limit = position.y + size.y; + + if (xf_points[0].y < low_limit) + goto next2; + if (xf_points[1].y < low_limit) + goto next2; + if (xf_points[2].y < low_limit) + goto next2; + if (xf_points[3].y < low_limit) + goto next2; + + return false; + +next2: + + if (xf_points[0].x > position.x) + goto next3; + if (xf_points[1].x > position.x) + goto next3; + if (xf_points[2].x > position.x) + goto next3; + if (xf_points[3].x > position.x) + goto next3; + + return false; + +next3: + + low_limit = position.x + size.x; + + if (xf_points[0].x < low_limit) + goto next4; + if (xf_points[1].x < low_limit) + goto next4; + if (xf_points[2].x < low_limit) + goto next4; + if (xf_points[3].x < low_limit) + goto next4; + + return false; + +next4: + + Vector2 xf_points2[4] = { + position, + Vector2(position.x + size.x, position.y), + Vector2(position.x, position.y + size.y), + Vector2(position.x + size.x, position.y + size.y), + }; + + real_t maxa = p_xform.elements[0].dot(xf_points2[0]); + real_t mina = maxa; + + real_t dp = p_xform.elements[0].dot(xf_points2[1]); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); + + dp = p_xform.elements[0].dot(xf_points2[2]); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); + + dp = p_xform.elements[0].dot(xf_points2[3]); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); + + real_t maxb = p_xform.elements[0].dot(xf_points[0]); + real_t minb = maxb; + + dp = p_xform.elements[0].dot(xf_points[1]); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); + + dp = p_xform.elements[0].dot(xf_points[2]); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); + + dp = p_xform.elements[0].dot(xf_points[3]); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); + + if (mina > maxb) + return false; + if (minb > maxa) + return false; + + maxa = p_xform.elements[1].dot(xf_points2[0]); + mina = maxa; + + dp = p_xform.elements[1].dot(xf_points2[1]); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); + + dp = p_xform.elements[1].dot(xf_points2[2]); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); + + dp = p_xform.elements[1].dot(xf_points2[3]); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); + + maxb = p_xform.elements[1].dot(xf_points[0]); + minb = maxb; + + dp = p_xform.elements[1].dot(xf_points[1]); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); + + dp = p_xform.elements[1].dot(xf_points[2]); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); + + dp = p_xform.elements[1].dot(xf_points[3]); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); + + if (mina > maxb) + return false; + if (minb > maxa) + return false; + + return true; +} diff --git a/core/math/rect2.h b/core/math/rect2.h new file mode 100644 index 0000000000..20329bee0d --- /dev/null +++ b/core/math/rect2.h @@ -0,0 +1,371 @@ +/*************************************************************************/ +/* rect2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 RECT2_H +#define RECT2_H + +#include "vector2.h" // also includes math_funcs and ustring + +struct Transform2D; + +struct Rect2 { + + Point2 position; + Size2 size; + + const Vector2 &get_position() const { return position; } + void set_position(const Vector2 &p_pos) { position = p_pos; } + const Vector2 &get_size() const { return size; } + void set_size(const Vector2 &p_size) { size = p_size; } + + real_t get_area() const { return size.width * size.height; } + + inline bool intersects(const Rect2 &p_rect) const { + if (position.x >= (p_rect.position.x + p_rect.size.width)) + return false; + if ((position.x + size.width) <= p_rect.position.x) + return false; + if (position.y >= (p_rect.position.y + p_rect.size.height)) + return false; + if ((position.y + size.height) <= p_rect.position.y) + return false; + + return true; + } + + inline real_t distance_to(const Vector2 &p_point) const { + + real_t dist = 0.0; + bool inside = true; + + if (p_point.x < position.x) { + real_t d = position.x - p_point.x; + dist = inside ? d : MIN(dist, d); + inside = false; + } + if (p_point.y < position.y) { + real_t d = position.y - p_point.y; + dist = inside ? d : MIN(dist, d); + inside = false; + } + if (p_point.x >= (position.x + size.x)) { + real_t d = p_point.x - (position.x + size.x); + dist = inside ? d : MIN(dist, d); + inside = false; + } + if (p_point.y >= (position.y + size.y)) { + real_t d = p_point.y - (position.y + size.y); + dist = inside ? d : MIN(dist, d); + inside = false; + } + + if (inside) + return 0; + else + return dist; + } + + bool intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const; + + bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = NULL, Point2 *r_normal = NULL) const; + + inline bool encloses(const Rect2 &p_rect) const { + + return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && + ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) && + ((p_rect.position.y + p_rect.size.y) < (position.y + size.y)); + } + + inline bool has_no_area() const { + + return (size.x <= 0 || size.y <= 0); + } + inline Rect2 clip(const Rect2 &p_rect) const { /// return a clipped rect + + Rect2 new_rect = p_rect; + + if (!intersects(new_rect)) + return Rect2(); + + new_rect.position.x = MAX(p_rect.position.x, position.x); + new_rect.position.y = MAX(p_rect.position.y, position.y); + + Point2 p_rect_end = p_rect.position + p_rect.size; + Point2 end = position + size; + + new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x; + new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y; + + return new_rect; + } + + inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect + + Rect2 new_rect; + + new_rect.position.x = MIN(p_rect.position.x, position.x); + new_rect.position.y = MIN(p_rect.position.y, position.y); + + new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, position.x + size.x); + new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, position.y + size.y); + + new_rect.size = new_rect.size - new_rect.position; //make relative again + + return new_rect; + }; + inline bool has_point(const Point2 &p_point) const { + if (p_point.x < position.x) + return false; + if (p_point.y < position.y) + return false; + + if (p_point.x >= (position.x + size.x)) + return false; + if (p_point.y >= (position.y + size.y)) + return false; + + return true; + } + + inline bool no_area() const { return (size.width <= 0 || size.height <= 0); } + + bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; } + bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } + + inline Rect2 grow(real_t p_by) const { + + Rect2 g = *this; + g.position.x -= p_by; + g.position.y -= p_by; + g.size.width += p_by * 2; + g.size.height += p_by * 2; + return g; + } + + inline Rect2 grow_margin(Margin p_margin, real_t p_amount) const { + Rect2 g = *this; + g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0, + (MARGIN_TOP == p_margin) ? p_amount : 0, + (MARGIN_RIGHT == p_margin) ? p_amount : 0, + (MARGIN_BOTTOM == p_margin) ? p_amount : 0); + return g; + } + + inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const { + + Rect2 g = *this; + g.position.x -= p_left; + g.position.y -= p_top; + g.size.width += p_left + p_right; + g.size.height += p_top + p_bottom; + + return g; + } + + inline Rect2 expand(const Vector2 &p_vector) const { + + Rect2 r = *this; + r.expand_to(p_vector); + return r; + } + + inline void expand_to(const Vector2 &p_vector) { //in place function for speed + + Vector2 begin = position; + Vector2 end = position + size; + + if (p_vector.x < begin.x) + begin.x = p_vector.x; + if (p_vector.y < begin.y) + begin.y = p_vector.y; + + if (p_vector.x > end.x) + end.x = p_vector.x; + if (p_vector.y > end.y) + end.y = p_vector.y; + + position = begin; + size = end - begin; + } + + inline Rect2 abs() const { + + return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs()); + } + + operator String() const { return String(position) + ", " + String(size); } + + Rect2() {} + Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) : + position(Point2(p_x, p_y)), + size(Size2(p_width, p_height)) { + } + Rect2(const Point2 &p_pos, const Size2 &p_size) : + position(p_pos), + size(p_size) { + } +}; + +struct Rect2i { + + Point2i position; + Size2i size; + + const Point2i &get_position() const { return position; } + void set_position(const Point2i &p_position) { position = p_position; } + const Size2i &get_size() const { return size; } + void set_size(const Size2i &p_size) { size = p_size; } + + int get_area() const { return size.width * size.height; } + + inline bool intersects(const Rect2i &p_rect) const { + if (position.x > (p_rect.position.x + p_rect.size.width)) + return false; + if ((position.x + size.width) < p_rect.position.x) + return false; + if (position.y > (p_rect.position.y + p_rect.size.height)) + return false; + if ((position.y + size.height) < p_rect.position.y) + return false; + + return true; + } + + inline bool encloses(const Rect2i &p_rect) const { + + return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && + ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) && + ((p_rect.position.y + p_rect.size.y) < (position.y + size.y)); + } + + inline bool has_no_area() const { + + return (size.x <= 0 || size.y <= 0); + } + inline Rect2i clip(const Rect2i &p_rect) const { /// return a clipped rect + + Rect2i new_rect = p_rect; + + if (!intersects(new_rect)) + return Rect2i(); + + new_rect.position.x = MAX(p_rect.position.x, position.x); + new_rect.position.y = MAX(p_rect.position.y, position.y); + + Point2 p_rect_end = p_rect.position + p_rect.size; + Point2 end = position + size; + + new_rect.size.x = (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x); + new_rect.size.y = (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y); + + return new_rect; + } + + inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect + + Rect2i new_rect; + + new_rect.position.x = MIN(p_rect.position.x, position.x); + new_rect.position.y = MIN(p_rect.position.y, position.y); + + new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, position.x + size.x); + new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, position.y + size.y); + + new_rect.size = new_rect.size - new_rect.position; //make relative again + + return new_rect; + }; + bool has_point(const Point2 &p_point) const { + if (p_point.x < position.x) + return false; + if (p_point.y < position.y) + return false; + + if (p_point.x >= (position.x + size.x)) + return false; + if (p_point.y >= (position.y + size.y)) + return false; + + return true; + } + + bool no_area() { return (size.width <= 0 || size.height <= 0); } + + bool operator==(const Rect2i &p_rect) const { return position == p_rect.position && size == p_rect.size; } + bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; } + + Rect2i grow(int p_by) const { + + Rect2i g = *this; + g.position.x -= p_by; + g.position.y -= p_by; + g.size.width += p_by * 2; + g.size.height += p_by * 2; + return g; + } + + inline void expand_to(const Point2i &p_vector) { + + Point2i begin = position; + Point2i end = position + size; + + if (p_vector.x < begin.x) + begin.x = p_vector.x; + if (p_vector.y < begin.y) + begin.y = p_vector.y; + + if (p_vector.x > end.x) + end.x = p_vector.x; + if (p_vector.y > end.y) + end.y = p_vector.y; + + position = begin; + size = end - begin; + } + + operator String() const { return String(position) + ", " + String(size); } + + operator Rect2() const { return Rect2(position, size); } + Rect2i(const Rect2 &p_r2) : + position(p_r2.position), + size(p_r2.size) { + } + Rect2i() {} + Rect2i(int p_x, int p_y, int p_width, int p_height) : + position(Point2(p_x, p_y)), + size(Size2(p_width, p_height)) { + } + Rect2i(const Point2 &p_pos, const Size2 &p_size) : + position(p_pos), + size(p_size) { + } +}; + +#endif // RECT2_H diff --git a/core/math/math_2d.cpp b/core/math/transform_2d.cpp index a053ffbd93..4bb763c879 100644 --- a/core/math/math_2d.cpp +++ b/core/math/transform_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* math_2d.cpp */ +/* transform_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,287 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "math_2d.h" - -real_t Vector2::angle() const { - - return Math::atan2(y, x); -} - -real_t Vector2::length() const { - - return Math::sqrt(x * x + y * y); -} - -real_t Vector2::length_squared() const { - - return x * x + y * y; -} - -void Vector2::normalize() { - - real_t l = x * x + y * y; - if (l != 0) { - - l = Math::sqrt(l); - x /= l; - y /= l; - } -} - -Vector2 Vector2::normalized() const { - - Vector2 v = *this; - v.normalize(); - return v; -} - -bool Vector2::is_normalized() const { - // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. - return Math::is_equal_approx(length_squared(), 1.0); -} - -real_t Vector2::distance_to(const Vector2 &p_vector2) const { - - return Math::sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y)); -} - -real_t Vector2::distance_squared_to(const Vector2 &p_vector2) const { - - return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y); -} - -real_t Vector2::angle_to(const Vector2 &p_vector2) const { - - return Math::atan2(cross(p_vector2), dot(p_vector2)); -} - -real_t Vector2::angle_to_point(const Vector2 &p_vector2) const { - - return Math::atan2(y - p_vector2.y, x - p_vector2.x); -} - -real_t Vector2::dot(const Vector2 &p_other) const { - - return x * p_other.x + y * p_other.y; -} - -real_t Vector2::cross(const Vector2 &p_other) const { - - return x * p_other.y - y * p_other.x; -} - -Vector2 Vector2::floor() const { - - return Vector2(Math::floor(x), Math::floor(y)); -} - -Vector2 Vector2::ceil() const { - - return Vector2(Math::ceil(x), Math::ceil(y)); -} - -Vector2 Vector2::round() const { - - return Vector2(Math::round(x), Math::round(y)); -} - -Vector2 Vector2::rotated(real_t p_by) const { - - Vector2 v; - v.set_rotation(angle() + p_by); - v *= length(); - return v; -} - -Vector2 Vector2::project(const Vector2 &p_vec) const { - - Vector2 v1 = p_vec; - Vector2 v2 = *this; - return v2 * (v1.dot(v2) / v2.dot(v2)); -} - -Vector2 Vector2::snapped(const Vector2 &p_by) const { - - return Vector2( - Math::stepify(x, p_by.x), - Math::stepify(y, p_by.y)); -} - -Vector2 Vector2::clamped(real_t p_len) const { - - real_t l = length(); - Vector2 v = *this; - if (l > 0 && p_len < l) { - - v /= l; - v *= p_len; - } - - return v; -} - -Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const { - - Vector2 p0 = p_pre_a; - Vector2 p1 = *this; - Vector2 p2 = p_b; - Vector2 p3 = p_post_b; - - real_t t = p_t; - real_t t2 = t * t; - real_t t3 = t2 * t; - - Vector2 out; - out = 0.5 * ((p1 * 2.0) + - (-p0 + p2) * t + - (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 + - (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3); - return out; -} - -// slide returns the component of the vector along the given plane, specified by its normal vector. -Vector2 Vector2::slide(const Vector2 &p_normal) const { -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector2()); -#endif - return *this - p_normal * this->dot(p_normal); -} - -Vector2 Vector2::bounce(const Vector2 &p_normal) const { - return -reflect(p_normal); -} - -Vector2 Vector2::reflect(const Vector2 &p_normal) const { -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector2()); -#endif - return 2.0 * p_normal * this->dot(p_normal) - *this; -} - -bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const { - - real_t min = 0, max = 1; - int axis = 0; - real_t sign = 0; - - for (int i = 0; i < 2; i++) { - real_t seg_from = p_from[i]; - real_t seg_to = p_to[i]; - real_t box_begin = position[i]; - real_t box_end = box_begin + size[i]; - real_t cmin, cmax; - real_t csign; - - if (seg_from < seg_to) { - - if (seg_from > box_end || seg_to < box_begin) - return false; - real_t length = seg_to - seg_from; - cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0; - cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1; - csign = -1.0; - - } else { - - if (seg_to > box_end || seg_from < box_begin) - return false; - real_t length = seg_to - seg_from; - cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0; - cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1; - csign = 1.0; - } - - if (cmin > min) { - min = cmin; - axis = i; - sign = csign; - } - if (cmax < max) - max = cmax; - if (max < min) - return false; - } - - Vector2 rel = p_to - p_from; - - if (r_normal) { - Vector2 normal; - normal[axis] = sign; - *r_normal = normal; - } - - if (r_pos) - *r_pos = p_from + rel * min; - - return true; -} - -/* Point2i */ - -Point2i Point2i::operator+(const Point2i &p_v) const { - - return Point2i(x + p_v.x, y + p_v.y); -} -void Point2i::operator+=(const Point2i &p_v) { - - x += p_v.x; - y += p_v.y; -} -Point2i Point2i::operator-(const Point2i &p_v) const { - - return Point2i(x - p_v.x, y - p_v.y); -} -void Point2i::operator-=(const Point2i &p_v) { - - x -= p_v.x; - y -= p_v.y; -} - -Point2i Point2i::operator*(const Point2i &p_v1) const { - - return Point2i(x * p_v1.x, y * p_v1.y); -}; - -Point2i Point2i::operator*(const int &rvalue) const { - - return Point2i(x * rvalue, y * rvalue); -}; -void Point2i::operator*=(const int &rvalue) { - - x *= rvalue; - y *= rvalue; -}; - -Point2i Point2i::operator/(const Point2i &p_v1) const { - - return Point2i(x / p_v1.x, y / p_v1.y); -}; - -Point2i Point2i::operator/(const int &rvalue) const { - - return Point2i(x / rvalue, y / rvalue); -}; - -void Point2i::operator/=(const int &rvalue) { - - x /= rvalue; - y /= rvalue; -}; - -Point2i Point2i::operator-() const { - - return Point2i(-x, -y); -} - -bool Point2i::operator==(const Point2i &p_vec2) const { - - return x == p_vec2.x && y == p_vec2.y; -} -bool Point2i::operator!=(const Point2i &p_vec2) const { - - return x != p_vec2.x || y != p_vec2.y; -} +#include "transform_2d.h" void Transform2D::invert() { // FIXME: this function assumes the basis is a rotation matrix, with no scaling. diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h new file mode 100644 index 0000000000..bf73755f0d --- /dev/null +++ b/core/math/transform_2d.h @@ -0,0 +1,201 @@ +/*************************************************************************/ +/* transform_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 TRANSFORM_2D_H +#define TRANSFORM_2D_H + +#include "rect2.h" // also includes vector2, math_funcs, and ustring + +struct Transform2D { + // Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper": + // M = (elements[0][0] elements[1][0]) + // (elements[0][1] elements[1][1]) + // This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as elements[i]. + // Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to elements[1][0] here. + // This requires additional care when working with explicit indices. + // See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading. + + // Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down, + // and angle is measure from +X to +Y in a clockwise-fashion. + + Vector2 elements[3]; + + _FORCE_INLINE_ real_t tdotx(const Vector2 &v) const { return elements[0][0] * v.x + elements[1][0] * v.y; } + _FORCE_INLINE_ real_t tdoty(const Vector2 &v) const { return elements[0][1] * v.x + elements[1][1] * v.y; } + + const Vector2 &operator[](int p_idx) const { return elements[p_idx]; } + Vector2 &operator[](int p_idx) { return elements[p_idx]; } + + _FORCE_INLINE_ Vector2 get_axis(int p_axis) const { + ERR_FAIL_INDEX_V(p_axis, 3, Vector2()); + return elements[p_axis]; + } + _FORCE_INLINE_ void set_axis(int p_axis, const Vector2 &p_vec) { + ERR_FAIL_INDEX(p_axis, 3); + elements[p_axis] = p_vec; + } + + void invert(); + Transform2D inverse() const; + + void affine_invert(); + Transform2D affine_inverse() const; + + void set_rotation(real_t p_rot); + real_t get_rotation() const; + _FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale); + void rotate(real_t p_phi); + + void scale(const Size2 &p_scale); + void scale_basis(const Size2 &p_scale); + void translate(real_t p_tx, real_t p_ty); + void translate(const Vector2 &p_translation); + + real_t basis_determinant() const; + + Size2 get_scale() const; + + _FORCE_INLINE_ const Vector2 &get_origin() const { return elements[2]; } + _FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { elements[2] = p_origin; } + + Transform2D scaled(const Size2 &p_scale) const; + Transform2D basis_scaled(const Size2 &p_scale) const; + Transform2D translated(const Vector2 &p_offset) const; + Transform2D rotated(real_t p_phi) const; + + Transform2D untranslated() const; + + void orthonormalize(); + Transform2D orthonormalized() const; + + bool operator==(const Transform2D &p_transform) const; + bool operator!=(const Transform2D &p_transform) const; + + void operator*=(const Transform2D &p_transform); + Transform2D operator*(const Transform2D &p_transform) const; + + Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const; + + _FORCE_INLINE_ Vector2 basis_xform(const Vector2 &p_vec) const; + _FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2 &p_vec) const; + _FORCE_INLINE_ Vector2 xform(const Vector2 &p_vec) const; + _FORCE_INLINE_ Vector2 xform_inv(const Vector2 &p_vec) const; + _FORCE_INLINE_ Rect2 xform(const Rect2 &p_rect) const; + _FORCE_INLINE_ Rect2 xform_inv(const Rect2 &p_rect) const; + + operator String() const; + + Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { + + elements[0][0] = xx; + elements[0][1] = xy; + elements[1][0] = yx; + elements[1][1] = yy; + elements[2][0] = ox; + elements[2][1] = oy; + } + + Transform2D(real_t p_rot, const Vector2 &p_pos); + Transform2D() { + elements[0][0] = 1.0; + elements[1][1] = 1.0; + } +}; + +Vector2 Transform2D::basis_xform(const Vector2 &p_vec) const { + + return Vector2( + tdotx(p_vec), + tdoty(p_vec)); +} + +Vector2 Transform2D::basis_xform_inv(const Vector2 &p_vec) const { + + return Vector2( + elements[0].dot(p_vec), + elements[1].dot(p_vec)); +} + +Vector2 Transform2D::xform(const Vector2 &p_vec) const { + + return Vector2( + tdotx(p_vec), + tdoty(p_vec)) + + elements[2]; +} +Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const { + + Vector2 v = p_vec - elements[2]; + + return Vector2( + elements[0].dot(v), + elements[1].dot(v)); +} +Rect2 Transform2D::xform(const Rect2 &p_rect) const { + + Vector2 x = elements[0] * p_rect.size.x; + Vector2 y = elements[1] * p_rect.size.y; + Vector2 pos = xform(p_rect.position); + + Rect2 new_rect; + new_rect.position = pos; + new_rect.expand_to(pos + x); + new_rect.expand_to(pos + y); + new_rect.expand_to(pos + x + y); + return new_rect; +} + +void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) { + + elements[0][0] = Math::cos(p_rot) * p_scale.x; + elements[1][1] = Math::cos(p_rot) * p_scale.y; + elements[1][0] = -Math::sin(p_rot) * p_scale.y; + elements[0][1] = Math::sin(p_rot) * p_scale.x; +} + +Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const { + + Vector2 ends[4] = { + xform_inv(p_rect.position), + xform_inv(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)), + xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)), + xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y)) + }; + + Rect2 new_rect; + new_rect.position = ends[0]; + new_rect.expand_to(ends[1]); + new_rect.expand_to(ends[2]); + new_rect.expand_to(ends[3]); + + return new_rect; +} + +#endif // TRANSFORM_2D_H diff --git a/core/math/triangulate.h b/core/math/triangulate.h index b1a583d0c5..a0f56f5f27 100644 --- a/core/math/triangulate.h +++ b/core/math/triangulate.h @@ -31,7 +31,7 @@ #ifndef TRIANGULATE_H #define TRIANGULATE_H -#include "math_2d.h" +#include "vector2.h" /* http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp new file mode 100644 index 0000000000..441e7d8907 --- /dev/null +++ b/core/math/vector2.cpp @@ -0,0 +1,253 @@ +/*************************************************************************/ +/* vector2.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "vector2.h" + +real_t Vector2::angle() const { + + return Math::atan2(y, x); +} + +real_t Vector2::length() const { + + return Math::sqrt(x * x + y * y); +} + +real_t Vector2::length_squared() const { + + return x * x + y * y; +} + +void Vector2::normalize() { + + real_t l = x * x + y * y; + if (l != 0) { + + l = Math::sqrt(l); + x /= l; + y /= l; + } +} + +Vector2 Vector2::normalized() const { + + Vector2 v = *this; + v.normalize(); + return v; +} + +bool Vector2::is_normalized() const { + // use length_squared() instead of length() to avoid sqrt(), makes it more stringent. + return Math::is_equal_approx(length_squared(), 1.0); +} + +real_t Vector2::distance_to(const Vector2 &p_vector2) const { + + return Math::sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y)); +} + +real_t Vector2::distance_squared_to(const Vector2 &p_vector2) const { + + return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y); +} + +real_t Vector2::angle_to(const Vector2 &p_vector2) const { + + return Math::atan2(cross(p_vector2), dot(p_vector2)); +} + +real_t Vector2::angle_to_point(const Vector2 &p_vector2) const { + + return Math::atan2(y - p_vector2.y, x - p_vector2.x); +} + +real_t Vector2::dot(const Vector2 &p_other) const { + + return x * p_other.x + y * p_other.y; +} + +real_t Vector2::cross(const Vector2 &p_other) const { + + return x * p_other.y - y * p_other.x; +} + +Vector2 Vector2::floor() const { + + return Vector2(Math::floor(x), Math::floor(y)); +} + +Vector2 Vector2::ceil() const { + + return Vector2(Math::ceil(x), Math::ceil(y)); +} + +Vector2 Vector2::round() const { + + return Vector2(Math::round(x), Math::round(y)); +} + +Vector2 Vector2::rotated(real_t p_by) const { + + Vector2 v; + v.set_rotation(angle() + p_by); + v *= length(); + return v; +} + +Vector2 Vector2::project(const Vector2 &p_vec) const { + + Vector2 v1 = p_vec; + Vector2 v2 = *this; + return v2 * (v1.dot(v2) / v2.dot(v2)); +} + +Vector2 Vector2::snapped(const Vector2 &p_by) const { + + return Vector2( + Math::stepify(x, p_by.x), + Math::stepify(y, p_by.y)); +} + +Vector2 Vector2::clamped(real_t p_len) const { + + real_t l = length(); + Vector2 v = *this; + if (l > 0 && p_len < l) { + + v /= l; + v *= p_len; + } + + return v; +} + +Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const { + + Vector2 p0 = p_pre_a; + Vector2 p1 = *this; + Vector2 p2 = p_b; + Vector2 p3 = p_post_b; + + real_t t = p_t; + real_t t2 = t * t; + real_t t3 = t2 * t; + + Vector2 out; + out = 0.5 * ((p1 * 2.0) + + (-p0 + p2) * t + + (2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 + + (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3); + return out; +} + +// slide returns the component of the vector along the given plane, specified by its normal vector. +Vector2 Vector2::slide(const Vector2 &p_normal) const { +#ifdef MATH_CHECKS + ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector2()); +#endif + return *this - p_normal * this->dot(p_normal); +} + +Vector2 Vector2::bounce(const Vector2 &p_normal) const { + return -reflect(p_normal); +} + +Vector2 Vector2::reflect(const Vector2 &p_normal) const { +#ifdef MATH_CHECKS + ERR_FAIL_COND_V(p_normal.is_normalized() == false, Vector2()); +#endif + return 2.0 * p_normal * this->dot(p_normal) - *this; +} + +/* Vector2i */ + +Vector2i Vector2i::operator+(const Vector2i &p_v) const { + + return Vector2i(x + p_v.x, y + p_v.y); +} +void Vector2i::operator+=(const Vector2i &p_v) { + + x += p_v.x; + y += p_v.y; +} +Vector2i Vector2i::operator-(const Vector2i &p_v) const { + + return Vector2i(x - p_v.x, y - p_v.y); +} +void Vector2i::operator-=(const Vector2i &p_v) { + + x -= p_v.x; + y -= p_v.y; +} + +Vector2i Vector2i::operator*(const Vector2i &p_v1) const { + + return Vector2i(x * p_v1.x, y * p_v1.y); +}; + +Vector2i Vector2i::operator*(const int &rvalue) const { + + return Vector2i(x * rvalue, y * rvalue); +}; +void Vector2i::operator*=(const int &rvalue) { + + x *= rvalue; + y *= rvalue; +}; + +Vector2i Vector2i::operator/(const Vector2i &p_v1) const { + + return Vector2i(x / p_v1.x, y / p_v1.y); +}; + +Vector2i Vector2i::operator/(const int &rvalue) const { + + return Vector2i(x / rvalue, y / rvalue); +}; + +void Vector2i::operator/=(const int &rvalue) { + + x /= rvalue; + y /= rvalue; +}; + +Vector2i Vector2i::operator-() const { + + return Vector2i(-x, -y); +} + +bool Vector2i::operator==(const Vector2i &p_vec2) const { + + return x == p_vec2.x && y == p_vec2.y; +} +bool Vector2i::operator!=(const Vector2i &p_vec2) const { + + return x != p_vec2.x || y != p_vec2.y; +} diff --git a/core/math/vector2.h b/core/math/vector2.h new file mode 100644 index 0000000000..7c8882f6e2 --- /dev/null +++ b/core/math/vector2.h @@ -0,0 +1,316 @@ +/*************************************************************************/ +/* vector2.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 VECTOR2_H +#define VECTOR2_H + +#include "math_funcs.h" +#include "ustring.h" + +struct Vector2i; + +struct Vector2 { + + union { + real_t x; + real_t width; + }; + union { + real_t y; + real_t height; + }; + + _FORCE_INLINE_ real_t &operator[](int p_idx) { + return p_idx ? y : x; + } + _FORCE_INLINE_ const real_t &operator[](int p_idx) const { + return p_idx ? y : x; + } + + void normalize(); + Vector2 normalized() const; + bool is_normalized() const; + + real_t length() const; + real_t length_squared() const; + + real_t distance_to(const Vector2 &p_vector2) const; + real_t distance_squared_to(const Vector2 &p_vector2) const; + real_t angle_to(const Vector2 &p_vector2) const; + real_t angle_to_point(const Vector2 &p_vector2) const; + + real_t dot(const Vector2 &p_other) const; + real_t cross(const Vector2 &p_other) const; + Vector2 project(const Vector2 &p_vec) const; + + Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const; + + Vector2 clamped(real_t p_len) const; + + _FORCE_INLINE_ static Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t); + _FORCE_INLINE_ Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const; + _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_b, real_t p_t) const; + Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const; + + Vector2 slide(const Vector2 &p_normal) const; + Vector2 bounce(const Vector2 &p_normal) const; + Vector2 reflect(const Vector2 &p_normal) const; + + Vector2 operator+(const Vector2 &p_v) const; + void operator+=(const Vector2 &p_v); + Vector2 operator-(const Vector2 &p_v) const; + void operator-=(const Vector2 &p_v); + Vector2 operator*(const Vector2 &p_v1) const; + + Vector2 operator*(const real_t &rvalue) const; + void operator*=(const real_t &rvalue); + void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; } + + Vector2 operator/(const Vector2 &p_v1) const; + + Vector2 operator/(const real_t &rvalue) const; + + void operator/=(const real_t &rvalue); + + Vector2 operator-() const; + + bool operator==(const Vector2 &p_vec2) const; + bool operator!=(const Vector2 &p_vec2) const; + + bool operator<(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } + bool operator<=(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y <= p_vec2.y) : (x <= p_vec2.x); } + + real_t angle() const; + + void set_rotation(real_t p_radians) { + + x = Math::cos(p_radians); + y = Math::sin(p_radians); + } + + _FORCE_INLINE_ Vector2 abs() const { + + return Vector2(Math::abs(x), Math::abs(y)); + } + + Vector2 rotated(real_t p_by) const; + Vector2 tangent() const { + + return Vector2(y, -x); + } + + Vector2 floor() const; + Vector2 ceil() const; + Vector2 round() const; + Vector2 snapped(const Vector2 &p_by) const; + real_t aspect() const { return width / height; } + + operator String() const { return String::num(x) + ", " + String::num(y); } + + _FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) { + x = p_x; + y = p_y; + } + _FORCE_INLINE_ Vector2() { + x = 0; + y = 0; + } +}; + +_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const { + + return p_vec - *this * (dot(p_vec) - p_d); +} + +_FORCE_INLINE_ Vector2 operator*(real_t p_scalar, const Vector2 &p_vec) { + + return p_vec * p_scalar; +} + +_FORCE_INLINE_ Vector2 Vector2::operator+(const Vector2 &p_v) const { + + return Vector2(x + p_v.x, y + p_v.y); +} +_FORCE_INLINE_ void Vector2::operator+=(const Vector2 &p_v) { + + x += p_v.x; + y += p_v.y; +} +_FORCE_INLINE_ Vector2 Vector2::operator-(const Vector2 &p_v) const { + + return Vector2(x - p_v.x, y - p_v.y); +} +_FORCE_INLINE_ void Vector2::operator-=(const Vector2 &p_v) { + + x -= p_v.x; + y -= p_v.y; +} + +_FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const { + + return Vector2(x * p_v1.x, y * p_v1.y); +}; + +_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const { + + return Vector2(x * rvalue, y * rvalue); +}; +_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) { + + x *= rvalue; + y *= rvalue; +}; + +_FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const { + + return Vector2(x / p_v1.x, y / p_v1.y); +}; + +_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const { + + return Vector2(x / rvalue, y / rvalue); +}; + +_FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) { + + x /= rvalue; + y /= rvalue; +}; + +_FORCE_INLINE_ Vector2 Vector2::operator-() const { + + return Vector2(-x, -y); +} + +_FORCE_INLINE_ bool Vector2::operator==(const Vector2 &p_vec2) const { + + return x == p_vec2.x && y == p_vec2.y; +} +_FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const { + + return x != p_vec2.x || y != p_vec2.y; +} + +Vector2 Vector2::linear_interpolate(const Vector2 &p_b, real_t p_t) const { + + Vector2 res = *this; + + res.x += (p_t * (p_b.x - x)); + res.y += (p_t * (p_b.y - y)); + + return res; +} + +Vector2 Vector2::slerp(const Vector2 &p_b, real_t p_t) const { +#ifdef MATH_CHECKS + ERR_FAIL_COND_V(is_normalized() == false, Vector2()); +#endif + real_t theta = angle_to(p_b); + return rotated(theta * p_t); +} + +Vector2 Vector2::linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t) { + + Vector2 res = p_a; + + res.x += (p_t * (p_b.x - p_a.x)); + res.y += (p_t * (p_b.y - p_a.y)); + + return res; +} + +typedef Vector2 Size2; +typedef Vector2 Point2; + +/* INTEGER STUFF */ + +struct Vector2i { + + union { + int x; + int width; + }; + union { + int y; + int height; + }; + + _FORCE_INLINE_ int &operator[](int p_idx) { + return p_idx ? y : x; + } + _FORCE_INLINE_ const int &operator[](int p_idx) const { + return p_idx ? y : x; + } + + Vector2i operator+(const Vector2i &p_v) const; + void operator+=(const Vector2i &p_v); + Vector2i operator-(const Vector2i &p_v) const; + void operator-=(const Vector2i &p_v); + Vector2i operator*(const Vector2i &p_v1) const; + + Vector2i operator*(const int &rvalue) const; + void operator*=(const int &rvalue); + + Vector2i operator/(const Vector2i &p_v1) const; + + Vector2i operator/(const int &rvalue) const; + + void operator/=(const int &rvalue); + + Vector2i operator-() const; + bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } + bool operator>(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); } + + bool operator==(const Vector2i &p_vec2) const; + bool operator!=(const Vector2i &p_vec2) const; + + real_t get_aspect() const { return width / (real_t)height; } + + operator String() const { return String::num(x) + ", " + String::num(y); } + + operator Vector2() const { return Vector2(x, y); } + inline Vector2i(const Vector2 &p_vec2) { + x = (int)p_vec2.x; + y = (int)p_vec2.y; + } + inline Vector2i(int p_x, int p_y) { + x = p_x; + y = p_y; + } + inline Vector2i() { + x = 0; + y = 0; + } +}; + +typedef Vector2i Size2i; +typedef Vector2i Point2i; + +#endif // VECTOR2_H diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h index 2f6dcb3178..6a33cf4d70 100644 --- a/core/method_ptrcall.h +++ b/core/method_ptrcall.h @@ -31,7 +31,7 @@ #ifndef METHOD_PTRCALL_H #define METHOD_PTRCALL_H -#include "math_2d.h" +#include "transform_2d.h" #include "typedefs.h" #include "variant.h" diff --git a/core/os/input_event.h b/core/os/input_event.h index 07df81488b..8732c7e377 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -31,9 +31,9 @@ #ifndef INPUT_EVENT_H #define INPUT_EVENT_H -#include "math_2d.h" #include "os/copymem.h" #include "resource.h" +#include "transform_2d.h" #include "typedefs.h" #include "ustring.h" /** diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 146b4870e8..87a5c3e493 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -953,7 +953,8 @@ ProjectSettings::ProjectSettings() { disable_feature_overrides = false; registering_order = true; - Array va; + Array events; + Dictionary action; Ref<InputEventKey> key; Ref<InputEventJoypadButton> joyb; @@ -965,122 +966,162 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("application/config/use_custom_user_dir", false); GLOBAL_DEF("application/config/custom_user_dir_name", ""); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_ENTER); - va.push_back(key); + events.push_back(key); key.instance(); key->set_scancode(KEY_KP_ENTER); - va.push_back(key); + events.push_back(key); key.instance(); key->set_scancode(KEY_SPACE); - va.push_back(key); + events.push_back(key); joyb.instance(); joyb->set_button_index(JOY_BUTTON_0); - va.push_back(joyb); - GLOBAL_DEF("input/ui_accept", va); + events.push_back(joyb); + action["events"] = events; + GLOBAL_DEF("input/ui_accept", action); input_presets.push_back("input/ui_accept"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_SPACE); - va.push_back(key); + events.push_back(key); joyb.instance(); joyb->set_button_index(JOY_BUTTON_3); - va.push_back(joyb); - GLOBAL_DEF("input/ui_select", va); + events.push_back(joyb); + action["events"] = events; + GLOBAL_DEF("input/ui_select", action); input_presets.push_back("input/ui_select"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_ESCAPE); - va.push_back(key); + events.push_back(key); joyb.instance(); joyb->set_button_index(JOY_BUTTON_1); - va.push_back(joyb); - GLOBAL_DEF("input/ui_cancel", va); + events.push_back(joyb); + action["events"] = events; + GLOBAL_DEF("input/ui_cancel", action); input_presets.push_back("input/ui_cancel"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_TAB); - va.push_back(key); - GLOBAL_DEF("input/ui_focus_next", va); + events.push_back(key); + action["events"] = events; + GLOBAL_DEF("input/ui_focus_next", action); input_presets.push_back("input/ui_focus_next"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_TAB); key->set_shift(true); - va.push_back(key); - GLOBAL_DEF("input/ui_focus_prev", va); + events.push_back(key); + action["events"] = events; + GLOBAL_DEF("input/ui_focus_prev", action); input_presets.push_back("input/ui_focus_prev"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_LEFT); - va.push_back(key); + events.push_back(key); joyb.instance(); joyb->set_button_index(JOY_DPAD_LEFT); - va.push_back(joyb); - GLOBAL_DEF("input/ui_left", va); + events.push_back(joyb); + action["events"] = events; + GLOBAL_DEF("input/ui_left", action); input_presets.push_back("input/ui_left"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_RIGHT); - va.push_back(key); + events.push_back(key); joyb.instance(); joyb->set_button_index(JOY_DPAD_RIGHT); - va.push_back(joyb); - GLOBAL_DEF("input/ui_right", va); + events.push_back(joyb); + action["events"] = events; + GLOBAL_DEF("input/ui_right", action); input_presets.push_back("input/ui_right"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_UP); - va.push_back(key); + events.push_back(key); joyb.instance(); joyb->set_button_index(JOY_DPAD_UP); - va.push_back(joyb); - GLOBAL_DEF("input/ui_up", va); + events.push_back(joyb); + action["events"] = events; + GLOBAL_DEF("input/ui_up", action); input_presets.push_back("input/ui_up"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_DOWN); - va.push_back(key); + events.push_back(key); joyb.instance(); joyb->set_button_index(JOY_DPAD_DOWN); - va.push_back(joyb); - GLOBAL_DEF("input/ui_down", va); + events.push_back(joyb); + action["events"] = events; + GLOBAL_DEF("input/ui_down", action); input_presets.push_back("input/ui_down"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_PAGEUP); - va.push_back(key); - GLOBAL_DEF("input/ui_page_up", va); + events.push_back(key); + action["events"] = events; + GLOBAL_DEF("input/ui_page_up", action); input_presets.push_back("input/ui_page_up"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_PAGEDOWN); - va.push_back(key); - GLOBAL_DEF("input/ui_page_down", va); + events.push_back(key); + action["events"] = events; + GLOBAL_DEF("input/ui_page_down", action); input_presets.push_back("input/ui_page_down"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_HOME); - va.push_back(key); - GLOBAL_DEF("input/ui_home", va); + events.push_back(key); + action["events"] = events; + GLOBAL_DEF("input/ui_home", action); input_presets.push_back("input/ui_home"); - va = Array(); + action = Dictionary(); + action["deadzone"] = Variant(0.5f); + events = Array(); key.instance(); key->set_scancode(KEY_END); - va.push_back(key); - GLOBAL_DEF("input/ui_end", va); + events.push_back(key); + action["events"] = events; + GLOBAL_DEF("input/ui_end", action); input_presets.push_back("input/ui_end"); //GLOBAL_DEF("display/window/handheld/orientation", "landscape"); diff --git a/core/script_language.h b/core/script_language.h index a5987e2a78..71b705e960 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -315,7 +315,7 @@ public: virtual void frame(); virtual bool handles_global_class_type(const String &p_type) const { return false; } - virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL) const { return String(); } + virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL, String *r_icon_path = NULL) const { return String(); } virtual ~ScriptLanguage() {} }; diff --git a/core/typedefs.h b/core/typedefs.h index 57afa3bdb4..094f1bbfd5 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -33,7 +33,7 @@ #include <stddef.h> /** - * Basic definitions and simple functions to be used everywhere.. + * Basic definitions and simple functions to be used everywhere. */ #include "platform_config.h" @@ -71,7 +71,7 @@ T *_nullptr() { #define OFFSET_OF(st, m) \ ((size_t)((char *)&(_nullptr<st>()->m) - (char *)0)) /** - * Some platforms (devices) not define NULL + * Some platforms (devices) don't define NULL */ #ifndef NULL @@ -79,7 +79,7 @@ T *_nullptr() { #endif /** - * Windows defines a lot of badly stuff we'll never ever use. undefine it. + * Windows badly defines a lot of stuff we'll never use. Undefine it. */ #ifdef _WIN32 @@ -296,4 +296,4 @@ struct _GlobalLock { #define unlikely(x) x #endif -#endif /* typedefs.h */ +#endif // TYPEDEFS_H diff --git a/core/variant.h b/core/variant.h index b48a0b3e73..577a33aa4d 100644 --- a/core/variant.h +++ b/core/variant.h @@ -42,7 +42,6 @@ #include "dvector.h" #include "face3.h" #include "io/ip_address.h" -#include "math_2d.h" #include "matrix3.h" #include "node_path.h" #include "plane.h" @@ -50,6 +49,7 @@ #include "ref_ptr.h" #include "rid.h" #include "transform.h" +#include "transform_2d.h" #include "ustring.h" #include "vector3.h" diff --git a/core/variant_call.cpp b/core/variant_call.cpp index b312316f9a..80cb869db2 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -1668,7 +1668,7 @@ void register_variant_methods() { ADDFUNC0NC(DICTIONARY, NIL, Dictionary, clear, varray()); ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray()); ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray()); - ADDFUNC1(DICTIONARY, NIL, Dictionary, erase, NIL, "key", varray()); + ADDFUNC1R(DICTIONARY, BOOL, Dictionary, erase, NIL, "key", varray()); ADDFUNC0R(DICTIONARY, INT, Dictionary, hash, varray()); ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray()); ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray()); diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml index 20d8bebd6b..7e871d68cb 100644 --- a/doc/classes/AcceptDialog.xml +++ b/doc/classes/AcceptDialog.xml @@ -60,7 +60,8 @@ </methods> <members> <member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok"> - If [code]true[/code] the dialog is hidden when accepted. Default value: [code]true[/code]. + If [code]true[/code] the dialog is hidden when the OK button is pressed. You can set it to [code]false[/code] if you want to do e.g. input validation when receiving the [signal confirmed] signal, and handle hiding the dialog in your own logic. Default value: [code]true[/code]. + Note: Some nodes derived from this class can have a different default value, and potentially their own built-in logic overriding this setting. For example [FileDialog] defaults to [code]false[/code], and has its own input validation code that is called when you press OK, which eventually hides the dialog if the input is valid. As such this property can't be used in [FileDialog] to disable hiding the dialog when pressing OK. </member> <member name="dialog_text" type="String" setter="set_text" getter="get_text"> The text displayed by this dialog. @@ -69,7 +70,7 @@ <signals> <signal name="confirmed"> <description> - Emitted when the dialog is accepted. + Emitted when the dialog is accepted, i.e. the OK button is pressed. </description> </signal> <signal name="custom_action"> diff --git a/doc/classes/ReferenceRect.xml b/doc/classes/ReferenceRect.xml index 4453e8726f..4c6f014965 100644 --- a/doc/classes/ReferenceRect.xml +++ b/doc/classes/ReferenceRect.xml @@ -14,8 +14,8 @@ </methods> <constants> </constants> - <theme_items> - <theme_item name="border" type="StyleBox"> - </theme_item> - </theme_items> + <members> + <member name="border_color" type="Color" setter="set_border_color" getter="get_border_color"> + </member> + </members> </class> diff --git a/drivers/convex_decomp/b2d_decompose.h b/drivers/convex_decomp/b2d_decompose.h index 068689d73d..b21792047e 100644 --- a/drivers/convex_decomp/b2d_decompose.h +++ b/drivers/convex_decomp/b2d_decompose.h @@ -31,8 +31,8 @@ #ifndef B2D_DECOMPOSE_H #define B2D_DECOMPOSE_H -#include "math_2d.h" #include "vector.h" +#include "vector2.h" Vector<Vector<Vector2> > b2d_decompose(const Vector<Vector2> &p_polygon); #endif // B2D_DECOMPOSE_H diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 3d388c031a..d6fbf04353 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -75,6 +75,7 @@ void RasterizerCanvasGLES2::canvas_begin() { } if (storage->frame.clear_request) { + glColorMask(true, true, true, true); glClearColor(storage->frame.clear_request_color.r, storage->frame.clear_request_color.g, storage->frame.clear_request_color.b, diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index a1a0b9e2c6..73d93f7b46 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -392,6 +392,12 @@ void RasterizerGLES2::end_frame(bool p_swap_buffers) { OS::get_singleton()->swap_buffers(); else glFinish(); + + if (p_swap_buffers) { + glColorMask(true, true, true, true); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + } } void RasterizerGLES2::finalize() { diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 1bd3c0a935..6ff6bd7ced 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -3641,6 +3641,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { texture_set_flags(rt->texture, texture->flags); + glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // copy texscreen buffers diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index 9251e21080..3e64c92e96 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -526,7 +526,7 @@ FRAGMENT_SHADER_CODE #if defined(ENABLE_NORMALMAP) normalmap.xy = normalmap.xy * 2.0 - 1.0; - normalmap.z = sqrt(1.0 - dot(normalmap.xy, normalmap.xy)); + normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); // normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side; normal = normalmap; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index dee8bcbc58..2d6f42679f 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1700,7 +1700,7 @@ FRAGMENT_SHADER_CODE #if defined(ENABLE_NORMALMAP) normalmap.xy=normalmap.xy*2.0-1.0; - normalmap.z=sqrt(1.0-dot(normalmap.xy,normalmap.xy)); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. + normalmap.z=sqrt(max(0.0, 1.0-dot(normalmap.xy,normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. normal = normalize( mix(normal_interp,tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z,normaldepth) ) * side; diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 5dd5b7fcc5..0bc4244642 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -157,6 +157,18 @@ Ref<Texture> CreateDialog::_get_editor_icon(const String &p_type) const { return get_icon(p_type, "EditorIcons"); } + if (ScriptServer::is_global_class(p_type)) { + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(p_type); + RES icon; + if (FileAccess::exists(icon_path)) { + icon = ResourceLoader::load(icon_path); + } + if (!icon.is_valid()) { + icon = get_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons"); + } + return icon; + } + const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types(); for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) { const Vector<EditorData::CustomType> &ct = E->value(); @@ -180,7 +192,7 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p return; bool cpp_type = ClassDB::class_exists(p_type); - EditorData &ed = EditorNode::get_singleton()->get_editor_data(); + EditorData &ed = EditorNode::get_editor_data(); if (p_type == base_type) return; @@ -262,13 +274,7 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p const String &description = EditorHelp::get_doc_data()->class_list[p_type].brief_description; item->set_tooltip(0, description); - if (cpp_type && has_icon(p_type, "EditorIcons")) { - - item->set_icon(0, get_icon(p_type, "EditorIcons")); - } else if (!cpp_type && has_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")) { - - item->set_icon(0, get_icon(ScriptServer::get_global_class_base(p_type), "EditorIcons")); - } + item->set_icon(0, _get_editor_icon(p_type)); p_types[p_type] = item; } @@ -287,7 +293,7 @@ void CreateDialog::_update_search() { HashMap<String, TreeItem *> types; TreeItem *root = search_options->create_item(); - EditorData &ed = EditorNode::get_singleton()->get_editor_data(); + EditorData &ed = EditorNode::get_editor_data(); root->set_text(0, base_type); if (has_icon(base_type, "EditorIcons")) { @@ -330,7 +336,7 @@ void CreateDialog::_update_search() { break; } - type = ClassDB::get_parent_class(type); + type = cpp_type ? ClassDB::get_parent_class(type) : ed.script_class_get_base(type); } if (found) @@ -490,16 +496,8 @@ Object *CreateDialog::instance_selected() { custom = md; if (custom != String()) { - if (ScriptServer::is_global_class(custom)) { - RES script = ResourceLoader::load(ScriptServer::get_global_class_path(custom)); - ERR_FAIL_COND_V(!script.is_valid(), NULL); - - Object *obj = ClassDB::instance(ScriptServer::get_global_class_base(custom)); - ERR_FAIL_COND_V(!obj, NULL); - - obj->set_script(script.get_ref_ptr()); - return obj; + return EditorNode::get_editor_data().script_class_instance(custom); } return EditorNode::get_editor_data().instance_custom_type(selected->get_text(0), custom); } else { diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index f4ef11eb36..69c120bb3c 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -888,11 +888,56 @@ StringName EditorData::script_class_get_base(const String &p_class) { return script->get_language()->get_global_class_name(base_script->get_path()); } +Object *EditorData::script_class_instance(const String &p_class) { + if (ScriptServer::is_global_class(p_class)) { + Object *obj = ClassDB::instance(ScriptServer::get_global_class_base(p_class)); + if (obj) { + RES script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class)); + if (script.is_valid()) + obj->set_script(script.get_ref_ptr()); + + RES icon = ResourceLoader::load(script_class_get_icon_path(p_class)); + if (icon.is_valid()) + obj->set_meta("_editor_icon", icon); + + return obj; + } + } + return NULL; +} + +void EditorData::script_class_save_icon_paths() { + List<StringName> keys; + _script_class_icon_paths.get_key_list(&keys); + + Dictionary d; + for (List<StringName>::Element *E = keys.front(); E; E = E->next()) { + d[E->get()] = _script_class_icon_paths[E->get()]; + } + + ProjectSettings::get_singleton()->set("_global_script_class_icons", d); + ProjectSettings::get_singleton()->save(); +} + +void EditorData::script_class_load_icon_paths() { + script_class_clear_icon_paths(); + + Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons"); + List<Variant> keys; + d.get_key_list(&keys); + + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { + String key = E->get().operator String(); + _script_class_icon_paths[key] = d[key]; + } +} + EditorData::EditorData() { current_edited_scene = -1; //load_imported_scenes_from_globals(); + script_class_load_icon_paths(); } /////////// diff --git a/editor/editor_data.h b/editor/editor_data.h index fac6635cd2..285769aa78 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -146,6 +146,8 @@ private: bool _find_updated_instances(Node *p_root, Node *p_node, Set<String> &checked_paths); + HashMap<StringName, String> _script_class_icon_paths; + public: EditorPlugin *get_editor(Object *p_object); EditorPlugin *get_subeditor(Object *p_object); @@ -213,6 +215,12 @@ public: bool script_class_is_parent(const String &p_class, const String &p_inherits); StringName script_class_get_base(const String &p_class); + Object *script_class_instance(const String &p_class); + String script_class_get_icon_path(const String &p_class) const { return _script_class_icon_paths.has(p_class) ? _script_class_icon_paths[p_class] : String(); } + void script_class_set_icon_path(const String &p_class, const String &p_icon_path) { _script_class_icon_paths[p_class] = p_icon_path; } + void script_class_clear_icon_paths() { _script_class_icon_paths.clear(); } + void script_class_save_icon_paths(); + void script_class_load_icon_paths(); EditorData(); }; diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 671ac755b2..9562a8c63c 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -133,6 +133,10 @@ String EditorFileSystemDirectory::get_file_script_class_extends(int p_idx) const return files[p_idx]->script_class_extends; } +String EditorFileSystemDirectory::get_file_script_class_icon_path(int p_idx) const { + return files[p_idx]->script_class_icon_path; +} + StringName EditorFileSystemDirectory::get_file_type(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, files.size(), ""); @@ -233,6 +237,7 @@ void EditorFileSystem::_scan_filesystem() { fc.import_valid = split[4].to_int64() != 0; fc.script_class_name = split[5].get_slice("<>", 0); fc.script_class_extends = split[5].get_slice("<>", 1); + fc.script_class_icon_path = split[5].get_slice("<>", 2); String deps = split[6].strip_edges(); if (deps.length()) { @@ -721,6 +726,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess fi->import_valid = fc->import_valid; fi->script_class_name = fc->script_class_name; fi->script_class_extends = fc->script_class_extends; + fi->script_class_icon_path = fc->script_class_icon_path; if (fc->type == String()) { fi->type = ResourceLoader::get_resource_type(path); @@ -731,7 +737,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess } else { fi->type = ResourceFormatImporter::get_singleton()->get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->modified_time = 0; fi->import_modified_time = 0; fi->import_valid = ResourceLoader::is_import_valid(path); @@ -753,10 +759,11 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess fi->import_valid = true; fi->script_class_name = fc->script_class_name; fi->script_class_extends = fc->script_class_extends; + fi->script_class_icon_path = fc->script_class_icon_path; } else { //new or modified time fi->type = ResourceLoader::get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->deps = _get_dependencies(path); fi->modified_time = mt; fi->import_modified_time = 0; @@ -855,7 +862,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const fi->modified_time = FileAccess::get_modified_time(path); fi->import_modified_time = 0; fi->type = ResourceLoader::get_resource_type(path); - fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends); + fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path); fi->import_valid = ResourceLoader::is_import_valid(path); { @@ -1110,7 +1117,7 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, for (int i = 0; i < p_dir->files.size(); i++) { - String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends; + String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path; s += "::"; for (int j = 0; j < p_dir->files[i]->deps.size(); j++) { @@ -1316,19 +1323,22 @@ Vector<String> EditorFileSystem::_get_dependencies(const String &p_path) { return ret; } -String EditorFileSystem::_get_global_script_class(const String &p_type, const String &p_path, String *r_extends) const { +String EditorFileSystem::_get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const { for (int i = 0; i < ScriptServer::get_language_count(); i++) { if (ScriptServer::get_language(i)->handles_global_class_type(p_type)) { String global_name; String extends; + String icon_path; - global_name = ScriptServer::get_language(i)->get_global_class_name(p_path, &extends); + global_name = ScriptServer::get_language(i)->get_global_class_name(p_path, &extends, &icon_path); *r_extends = extends; + *r_icon_path = icon_path; return global_name; } } *r_extends = String(); + *r_icon_path = String(); return String(); } @@ -1346,8 +1356,8 @@ void EditorFileSystem::_scan_script_classes(EditorFileSystemDirectory *p_dir) { lang = ScriptServer::get_language(j)->get_name(); } } - ScriptServer::add_global_class(files[i]->script_class_name, files[i]->script_class_extends, lang, p_dir->get_file_path(i)); + EditorNode::get_editor_data().script_class_set_icon_path(files[i]->script_class_name, files[i]->script_class_icon_path); } for (int i = 0; i < p_dir->get_subdir_count(); i++) { _scan_script_classes(p_dir->get_subdir(i)); @@ -1366,6 +1376,7 @@ void EditorFileSystem::update_script_classes() { } ScriptServer::save_global_classes(); + EditorNode::get_editor_data().script_class_save_icon_paths(); emit_signal("script_classes_updated"); } @@ -1438,7 +1449,7 @@ void EditorFileSystem::update_file(const String &p_file) { } fs->files[cpos]->type = type; - fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends); + fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path); fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); fs->files[cpos]->deps = _get_dependencies(p_file); fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file); diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 1aa35f4782..75ca79932f 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -60,6 +60,7 @@ class EditorFileSystemDirectory : public Object { bool verified; //used for checking changes String script_class_name; String script_class_extends; + String script_class_icon_path; }; struct FileInfoSort { @@ -90,6 +91,7 @@ public: bool get_file_import_is_valid(int p_idx) const; String get_file_script_class_name(int p_idx) const; //used for scripts String get_file_script_class_extends(int p_idx) const; //used for scripts + String get_file_script_class_icon_path(int p_idx) const; //used for scripts EditorFileSystemDirectory *get_parent(); @@ -163,6 +165,7 @@ class EditorFileSystem : public Node { bool import_valid; String script_class_name; String script_class_extends; + String script_class_icon_path; }; HashMap<String, FileCache> file_cache; @@ -225,7 +228,7 @@ class EditorFileSystem : public Node { volatile bool update_script_classes_queued; void _queue_update_script_classes(); - String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends) const; + String _get_global_script_class(const String &p_type, const String &p_path, String *r_extends, String *r_icon_path) const; protected: void _notification(int p_what); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4e6f3853c6..0be6ee8759 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -411,6 +411,18 @@ void EditorNode::_notification(int p_what) { } } +void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_name) { + Ref<Script> script = Object::cast_to<Script>(p_script); + if (script.is_null()) + return; + if (p_activate_name.length()) { + set_addon_plugin_enabled(p_activate_name, true); + } + project_settings->update_plugins(); + project_settings->hide(); + push_item(script.operator->()); +} + void EditorNode::_fs_changed() { for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) { @@ -2547,6 +2559,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled) EditorPlugin *ep = memnew(EditorPlugin); ep->set_script(script.get_ref_ptr()); + ep->set_dir_cache(p_addon); plugin_addons[p_addon] = ep; add_editor_plugin(ep); @@ -4548,6 +4561,8 @@ void EditorNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_resources_reimported"), &EditorNode::_resources_reimported); ClassDB::bind_method(D_METHOD("_bottom_panel_raise_toggled"), &EditorNode::_bottom_panel_raise_toggled); + ClassDB::bind_method(D_METHOD("_on_plugin_ready"), &EditorNode::_on_plugin_ready); + ClassDB::bind_method(D_METHOD("_video_driver_selected"), &EditorNode::_video_driver_selected); ADD_SIGNAL(MethodInfo("play_pressed")); @@ -5134,6 +5149,10 @@ EditorNode::EditorNode() { p->connect("id_pressed", this, "_menu_option"); p->add_item(TTR("Export"), FILE_EXPORT_PROJECT); + plugin_config_dialog = memnew(PluginConfigDialog); + plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready"); + gui_base->add_child(plugin_config_dialog); + tool_menu = memnew(PopupMenu); tool_menu->set_name("Tools"); tool_menu->connect("index_pressed", this, "_tool_menu_option"); @@ -5409,7 +5428,7 @@ EditorNode::EditorNode() { } filesystem_dock = memnew(FileSystemDock(this)); - filesystem_dock->set_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); + filesystem_dock->set_file_list_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"))); if (use_single_dock_column) { dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(filesystem_dock); diff --git a/editor/editor_node.h b/editor/editor_node.h index 85aa37ec7e..5a17ab6ca0 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -56,6 +56,7 @@ #include "editor/inspector_dock.h" #include "editor/node_dock.h" #include "editor/pane_drag.h" +#include "editor/plugin_config_dialog.h" #include "editor/progress_dialog.h" #include "editor/project_export.h" #include "editor/project_settings_editor.h" @@ -257,6 +258,8 @@ private: ToolButton *search_button; TextureProgress *audio_vu; + PluginConfigDialog *plugin_config_dialog; + RichTextLabel *load_errors; AcceptDialog *load_error_dialog; @@ -416,6 +419,8 @@ private: void _tool_menu_option(int p_idx); void _update_debug_options(); + void _on_plugin_ready(Object *p_script, const String &p_activate_name); + void _fs_changed(); void _resources_reimported(const Vector<String> &p_resources); void _sources_changed(bool p_exist); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index a926401558..137e710c5c 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -309,6 +309,12 @@ void EditorPlugin::remove_autoload_singleton(const String &p_name) { EditorNode::get_singleton()->get_project_settings()->get_autoload_settings()->autoload_remove(p_name); } +Ref<ConfigFile> EditorPlugin::get_config() { + Ref<ConfigFile> cf = memnew(ConfigFile); + cf->load(_dir_cache.plus_file("plugin.cfg")); + return cf; +} + ToolButton *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) { ERR_FAIL_NULL_V(p_control, NULL); return EditorNode::get_singleton()->add_bottom_panel_item(p_title, p_control); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index c417f487dc..903b82937f 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -114,6 +114,7 @@ class EditorPlugin : public Node { bool force_draw_over_forwarding_enabled; String last_main_screen_name; + String _dir_cache; protected: static void _bind_methods(); @@ -221,6 +222,10 @@ public: void add_autoload_singleton(const String &p_name, const String &p_path); void remove_autoload_singleton(const String &p_name); + void set_dir_cache(const String &p_dir) { _dir_cache = p_dir; } + String get_dir_cache() { return _dir_cache; } + Ref<ConfigFile> get_config(); + EditorPlugin(); virtual ~EditorPlugin(); }; diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index ea1e0fe99e..68f8ed6d94 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -41,6 +41,9 @@ void EditorPluginSettings::_notification(int p_what) { if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) { update_plugins(); + } else if (p_what == Node::NOTIFICATION_READY) { + plugin_config_dialog->connect("plugin_ready", EditorNode::get_singleton(), "_on_plugin_ready"); + plugin_list->connect("button_pressed", this, "_cell_button_pressed"); } } @@ -124,6 +127,7 @@ void EditorPluginSettings::update_plugins() { item->set_range_config(3, 0, 1, 1); item->set_text(3, "Inactive,Active"); item->set_editable(3, true); + item->add_button(4, get_icon("Edit", "EditorIcons"), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin")); if (EditorNode::get_singleton()->is_addon_plugin_enabled(d)) { item->set_custom_color(3, get_color("success_color", "Editor")); @@ -164,17 +168,44 @@ void EditorPluginSettings::_plugin_activity_changed() { ti->set_custom_color(3, get_color("disabled_font_color", "Editor")); } +void EditorPluginSettings::_create_clicked() { + plugin_config_dialog->config(""); + plugin_config_dialog->popup_centered(); +} + +void EditorPluginSettings::_cell_button_pressed(Object *p_item, int p_column, int p_id) { + TreeItem *item = Object::cast_to<TreeItem>(p_item); + if (!item) + return; + if (p_id == BUTTON_PLUGIN_EDIT) { + if (p_column == 4) { + String dir = item->get_metadata(0); + plugin_config_dialog->config("res://addons/" + dir + "/plugin.cfg"); + plugin_config_dialog->popup_centered(); + } + } +} + void EditorPluginSettings::_bind_methods() { ClassDB::bind_method("update_plugins", &EditorPluginSettings::update_plugins); + ClassDB::bind_method("_create_clicked", &EditorPluginSettings::_create_clicked); ClassDB::bind_method("_plugin_activity_changed", &EditorPluginSettings::_plugin_activity_changed); + ClassDB::bind_method("_cell_button_pressed", &EditorPluginSettings::_cell_button_pressed); } EditorPluginSettings::EditorPluginSettings() { + plugin_config_dialog = memnew(PluginConfigDialog); + plugin_config_dialog->config(""); + add_child(plugin_config_dialog); + HBoxContainer *title_hb = memnew(HBoxContainer); title_hb->add_child(memnew(Label(TTR("Installed Plugins:")))); title_hb->add_spacer(); + create_plugin = memnew(Button(TTR("Create"))); + create_plugin->connect("pressed", this, "_create_clicked"); + title_hb->add_child(create_plugin); update_list = memnew(Button(TTR("Update"))); update_list->connect("pressed", this, "update_plugins"); title_hb->add_child(update_list); @@ -182,19 +213,22 @@ EditorPluginSettings::EditorPluginSettings() { plugin_list = memnew(Tree); plugin_list->set_v_size_flags(SIZE_EXPAND_FILL); - plugin_list->set_columns(4); + plugin_list->set_columns(5); plugin_list->set_column_titles_visible(true); plugin_list->set_column_title(0, TTR("Name:")); plugin_list->set_column_title(1, TTR("Version:")); plugin_list->set_column_title(2, TTR("Author:")); plugin_list->set_column_title(3, TTR("Status:")); + plugin_list->set_column_title(4, TTR("Edit:")); plugin_list->set_column_expand(0, true); plugin_list->set_column_expand(1, false); plugin_list->set_column_expand(2, false); plugin_list->set_column_expand(3, false); + plugin_list->set_column_expand(4, false); plugin_list->set_column_min_width(1, 100 * EDSCALE); plugin_list->set_column_min_width(2, 250 * EDSCALE); plugin_list->set_column_min_width(3, 80 * EDSCALE); + plugin_list->set_column_min_width(4, 40 * EDSCALE); plugin_list->set_hide_root(true); plugin_list->connect("item_edited", this, "_plugin_activity_changed"); diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h index aacbd05dd4..310cab699f 100644 --- a/editor/editor_plugin_settings.h +++ b/editor/editor_plugin_settings.h @@ -31,6 +31,7 @@ #ifndef EDITORPLUGINSETTINGS_H #define EDITORPLUGINSETTINGS_H +#include "editor/plugin_config_dialog.h"; #include "editor_data.h" #include "property_editor.h" #include "scene/gui/dialogs.h" @@ -40,11 +41,19 @@ class EditorPluginSettings : public VBoxContainer { GDCLASS(EditorPluginSettings, VBoxContainer); + enum { + BUTTON_PLUGIN_EDIT + }; + + PluginConfigDialog *plugin_config_dialog; + Button *create_plugin; Button *update_list; Tree *plugin_list; bool updating; void _plugin_activity_changed(); + void _create_clicked(); + void _cell_button_pressed(Object *p_item, int p_column, int p_id); protected: void _notification(int p_what); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 8e079b1f67..d24816ee02 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -511,6 +511,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("filesystem/file_dialog/thumbnail_size", 64); hints["filesystem/file_dialog/thumbnail_size"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16"); + _initial_set("docks/filesystem/disable_split", false); + _initial_set("docks/filesystem/split_mode_minimum_height", 600); _initial_set("docks/filesystem/display_mode", 0); hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"); _initial_set("docks/filesystem/thumbnail_size", 64); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index f2c8cde151..ec1153a015 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -139,41 +139,56 @@ void FileSystemDock::_update_tree(bool keep_collapse_state, bool p_uncollapse_ro updating_tree = false; } -void FileSystemDock::_notification(int p_what) { +void FileSystemDock::_update_display_mode() { - switch (p_what) { + bool disable_split = bool(EditorSettings::get_singleton()->get("docks/filesystem/disable_split")); + bool compact_mode = get_size().height < int(EditorSettings::get_singleton()->get("docks/filesystem/split_mode_minimum_height")); + DisplayMode new_mode; + if (disable_split || compact_mode) { + new_mode = file_list_view ? DISPLAY_FILE_LIST_ONLY : DISPLAY_TREE_ONLY; + } else { + new_mode = DISPLAY_SPLIT; + } - case NOTIFICATION_RESIZED: { + if (new_mode != display_mode) { + switch (new_mode) { + case DISPLAY_TREE_ONLY: + tree->show(); + tree->set_v_size_flags(SIZE_EXPAND_FILL); + _update_tree(true); - bool new_mode = get_size().height < get_viewport_rect().size.height / 2; + file_list_vb->hide(); + break; - if (new_mode != low_height_mode) { + case DISPLAY_FILE_LIST_ONLY: + tree->hide(); + button_tree->show(); - low_height_mode = new_mode; + file_list_vb->show(); + _update_files(true); + break; - if (low_height_mode) { + case DISPLAY_SPLIT: + tree->show(); + tree->set_v_size_flags(SIZE_EXPAND_FILL); + button_tree->hide(); + tree->ensure_cursor_is_visible(); + _update_tree(true); - tree->hide(); - tree->set_v_size_flags(SIZE_EXPAND_FILL); - button_tree->show(); - } else { + file_list_vb->show(); + _update_files(true); + break; + } + display_mode = new_mode; + } +} - tree->set_v_size_flags(SIZE_FILL); - button_tree->hide(); - if (!tree->is_visible()) { - tree->show(); - button_favorite->show(); - _update_tree(true); - } - tree->ensure_cursor_is_visible(); +void FileSystemDock::_notification(int p_what) { - if (!file_list_vb->is_visible()) { - file_list_vb->show(); - _update_files(true); - } - } - } + switch (p_what) { + case NOTIFICATION_RESIZED: { + _update_display_mode(); } break; case NOTIFICATION_ENTER_TREE: { @@ -190,8 +205,8 @@ void FileSystemDock::_notification(int p_what) { //button_instance->set_icon(get_icon("Add", ei)); //button_open->set_icon(get_icon("Folder", ei)); button_tree->set_icon(get_icon("Filesystem", ei)); - _update_file_display_toggle_button(); - button_display_mode->connect("pressed", this, "_change_file_display"); + _update_file_list_display_mode_button(); + button_file_list_display_mode->connect("pressed", this, "_change_file_display"); //file_options->set_icon( get_icon("Tools","ei")); files->connect("item_activated", this, "_select_file"); button_hist_next->connect("pressed", this, "_fw_history"); @@ -208,6 +223,8 @@ void FileSystemDock::_notification(int p_what) { button_tree->connect("pressed", this, "_go_to_tree", varray(), CONNECT_DEFERRED); current_path->connect("text_entered", this, "navigate_to_path"); + _update_display_mode(); + if (EditorFileSystem::get_singleton()->is_scanning()) { _set_scanning_mode(); } else { @@ -241,12 +258,8 @@ void FileSystemDock::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - + // Update icons String ei = "EditorIcons"; - int new_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")); - - //_update_icons - button_reload->set_icon(get_icon("Reload", ei)); button_favorite->set_icon(get_icon("Favorites", ei)); button_tree->set_icon(get_icon("Filesystem", ei)); @@ -256,14 +269,18 @@ void FileSystemDock::_notification(int p_what) { search_box->set_right_icon(get_icon("Search", ei)); search_box->set_clear_button_enabled(true); - if (new_mode != display_mode) { - set_display_mode(new_mode); + // Change size mode + int new_file_list_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")); + if (new_file_list_mode != file_list_display_mode) { + set_file_list_display_mode(new_file_list_mode); } else { - _update_file_display_toggle_button(); + _update_file_list_display_mode_button(); _update_files(true); } - _update_tree(true); + // Change full tree mode + _update_display_mode(); + } break; } } @@ -289,7 +306,7 @@ void FileSystemDock::_dir_selected() { current_path->set_text(path); _push_to_history(); - if (!low_height_mode) { + if (display_mode == DISPLAY_SPLIT) { _update_files(false); } } @@ -360,7 +377,7 @@ void FileSystemDock::navigate_to_path(const String &p_path) { current_path->set_text(path); _push_to_history(); - if (!low_height_mode) { + if (display_mode == DISPLAY_SPLIT) { _update_tree(true); _update_files(false); } else { @@ -390,24 +407,24 @@ void FileSystemDock::_thumbnail_done(const String &p_path, const Ref<Texture> &p } } -void FileSystemDock::_update_file_display_toggle_button() { +void FileSystemDock::_update_file_list_display_mode_button() { - if (button_display_mode->is_pressed()) { - display_mode = DISPLAY_LIST; - button_display_mode->set_icon(get_icon("FileThumbnail", "EditorIcons")); - button_display_mode->set_tooltip(TTR("View items as a grid of thumbnails.")); + if (button_file_list_display_mode->is_pressed()) { + file_list_display_mode = FILE_LIST_DISPLAY_LIST; + button_file_list_display_mode->set_icon(get_icon("FileThumbnail", "EditorIcons")); + button_file_list_display_mode->set_tooltip(TTR("View items as a grid of thumbnails.")); } else { - display_mode = DISPLAY_THUMBNAILS; - button_display_mode->set_icon(get_icon("FileList", "EditorIcons")); - button_display_mode->set_tooltip(TTR("View items as a list.")); + file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; + button_file_list_display_mode->set_icon(get_icon("FileList", "EditorIcons")); + button_file_list_display_mode->set_tooltip(TTR("View items as a list.")); } } void FileSystemDock::_change_file_display() { - _update_file_display_toggle_button(); + _update_file_list_display_mode_button(); - EditorSettings::get_singleton()->set("docks/filesystem/display_mode", display_mode); + EditorSettings::get_singleton()->set("docks/filesystem/display_mode", file_list_display_mode); _update_files(true); } @@ -472,8 +489,8 @@ void FileSystemDock::_update_files(bool p_keep_selection) { bool always_show_folders = EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"); - bool use_thumbnails = (display_mode == DISPLAY_THUMBNAILS); - bool use_folders = search_box->get_text().length() == 0 && (low_height_mode || always_show_folders); + bool use_thumbnails = (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS); + bool use_folders = search_box->get_text().length() == 0 && ((display_mode == DISPLAY_FILE_LIST_ONLY || display_mode == DISPLAY_TREE_ONLY) || always_show_folders); if (use_thumbnails) { @@ -617,24 +634,28 @@ void FileSystemDock::_select_file(int p_idx) { } } -void FileSystemDock::_go_to_tree() { +void FileSystemDock::_go_to_file_list() { - if (low_height_mode) { - tree->show(); - button_favorite->show(); - file_list_vb->hide(); + if (display_mode == DISPLAY_TREE_ONLY) { + file_list_view = true; + _update_display_mode(); + } else { + bool collapsed = tree->get_selected()->is_collapsed(); + tree->get_selected()->set_collapsed(!collapsed); + _update_files(false); } +} +void FileSystemDock::_go_to_tree() { - _update_tree(true); + file_list_view = false; tree->grab_focus(); + _update_display_mode(); tree->ensure_cursor_is_visible(); - //button_open->hide(); - //file_options->hide(); } void FileSystemDock::_preview_invalidated(const String &p_path) { - if (display_mode == DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) { + if (file_list_display_mode == FILE_LIST_DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) { for (int i = 0; i < files->get_item_count(); i++) { @@ -1413,24 +1434,6 @@ void FileSystemDock::_resource_created() const { editor->save_resource_as(current_res, path); } -void FileSystemDock::_go_to_file_list() { - - if (low_height_mode) { - tree->hide(); - file_list_vb->show(); - button_favorite->hide(); - } else { - bool collapsed = tree->get_selected()->is_collapsed(); - tree->get_selected()->set_collapsed(!collapsed); - } - - //file_options->show(); - - _update_files(false); - - //emit_signal("open",path); -} - void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) { folder_options->clear(); folder_options->set_size(Size2(1, 1)); @@ -1474,7 +1477,7 @@ void FileSystemDock::fix_dependencies(const String &p_for_file) { void FileSystemDock::focus_on_filter() { - if (low_height_mode && tree->is_visible()) { + if (display_mode == DISPLAY_FILE_LIST_ONLY && tree->is_visible()) { // Tree mode, switch to files list with search box tree->hide(); file_list_vb->show(); @@ -1484,12 +1487,12 @@ void FileSystemDock::focus_on_filter() { search_box->grab_focus(); } -void FileSystemDock::set_display_mode(int p_mode) { +void FileSystemDock::set_file_list_display_mode(int p_mode) { - if (p_mode == display_mode) + if (p_mode == file_list_display_mode) return; - button_display_mode->set_pressed(p_mode == DISPLAY_LIST); + button_file_list_display_mode->set_pressed(p_mode == FILE_LIST_DISPLAY_LIST); _change_file_display(); } @@ -2030,9 +2033,9 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { search_box->connect("text_changed", this, "_search_changed"); path_hb->add_child(search_box); - button_display_mode = memnew(ToolButton); - button_display_mode->set_toggle_mode(true); - path_hb->add_child(button_display_mode); + button_file_list_display_mode = memnew(ToolButton); + button_file_list_display_mode->set_toggle_mode(true); + path_hb->add_child(button_file_list_display_mode); files = memnew(ItemList); files->set_v_size_flags(SIZE_EXPAND_FILL); @@ -2128,8 +2131,8 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { history_max_size = 20; history.push_back("res://"); - low_height_mode = false; - display_mode = DISPLAY_THUMBNAILS; + display_mode = DISPLAY_SPLIT; + file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; } FileSystemDock::~FileSystemDock() { diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 6a0c73d52e..fbbe87fc16 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -60,12 +60,18 @@ class FileSystemDock : public VBoxContainer { GDCLASS(FileSystemDock, VBoxContainer); public: - enum DisplayMode { - DISPLAY_THUMBNAILS, - DISPLAY_LIST + enum FileListDisplayMode { + FILE_LIST_DISPLAY_THUMBNAILS, + FILE_LIST_DISPLAY_LIST }; private: + enum DisplayMode { + DISPLAY_TREE_ONLY, + DISPLAY_FILE_LIST_ONLY, + DISPLAY_SPLIT, + }; + enum FileMenu { FILE_OPEN, FILE_INSTANCE, @@ -106,7 +112,7 @@ private: Button *button_reload; Button *button_favorite; Button *button_tree; - Button *button_display_mode; + Button *button_file_list_display_mode; Button *button_hist_next; Button *button_hist_prev; Button *button_show; @@ -115,8 +121,9 @@ private: TextureRect *search_icon; HBoxContainer *path_hb; - bool low_height_mode; + FileListDisplayMode file_list_display_mode; DisplayMode display_mode; + bool file_list_view; PopupMenu *file_options; PopupMenu *folder_options; @@ -172,7 +179,7 @@ private: void _files_gui_input(Ref<InputEvent> p_event); void _update_files(bool p_keep_selection); - void _update_file_display_toggle_button(); + void _update_file_list_display_mode_button(); void _change_file_display(); void _fs_changed(); @@ -245,6 +252,8 @@ private: void _preview_invalidated(const String &p_path); void _thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Variant &p_udata); + void _update_display_mode(); + protected: void _notification(int p_what); static void _bind_methods(); @@ -258,7 +267,7 @@ public: void fix_dependencies(const String &p_for_file); - void set_display_mode(int p_mode); + void set_file_list_display_mode(int p_mode); int get_split_offset() { return split_box->get_split_offset(); } void set_split_offset(int p_offset) { split_box->set_split_offset(p_offset); } diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp new file mode 100644 index 0000000000..418936ac9f --- /dev/null +++ b/editor/plugin_config_dialog.cpp @@ -0,0 +1,230 @@ +/*************************************************************************/ +/* plugin_config_dialog.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 "plugin_config_dialog.h" +#include "core/io/config_file.h" +#include "core/os/dir_access.h" +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "modules/gdscript/gdscript.h" +#include "scene/gui/grid_container.h" + +void PluginConfigDialog::_clear_fields() { + name_edit->set_text(""); + subfolder_edit->set_text(""); + desc_edit->set_text(""); + author_edit->set_text(""); + version_edit->set_text(""); + script_edit->set_text(""); +} + +void PluginConfigDialog::_on_confirmed() { + + String path = "res://addons/" + subfolder_edit->get_text(); + + if (!_edit_mode) { + DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (!d || d->make_dir_recursive(path) != OK) + return; + } + + Ref<ConfigFile> cf = memnew(ConfigFile); + cf->set_value("plugin", "name", name_edit->get_text()); + cf->set_value("plugin", "description", desc_edit->get_text()); + cf->set_value("plugin", "author", author_edit->get_text()); + cf->set_value("plugin", "version", version_edit->get_text()); + cf->set_value("plugin", "script", script_edit->get_text()); + + cf->save(path.plus_file("plugin.cfg")); + + if (!_edit_mode) { + String type = script_option_edit->get_item_text(script_option_edit->get_selected()); + + Ref<Script> script; + + if (type == GDScriptLanguage::get_singleton()->get_name()) { + Ref<GDScript> gdscript = memnew(GDScript); + gdscript->set_source_code( + "tool\n" + "extends EditorPlugin\n" + "\n" + "func _enter_tree():\n" + "\tpass"); + String script_path = path.plus_file(script_edit->get_text()); + gdscript->set_path(script_path); + ResourceSaver::save(script_path, gdscript); + script = gdscript; + } + //TODO: other languages + + emit_signal("plugin_ready", script.operator->(), active_edit->is_pressed() ? name_edit->get_text() : ""); + } else { + EditorNode::get_singleton()->get_project_settings()->update_plugins(); + } + _clear_fields(); +} + +void PluginConfigDialog::_on_cancelled() { + _clear_fields(); +} + +void PluginConfigDialog::_on_required_text_changed(const String &p_text) { + String ext = script_option_edit->get_item_metadata(script_option_edit->get_selected()); + get_ok()->set_disabled(script_edit->get_text().get_basename().empty() || script_edit->get_text().get_extension() != ext || name_edit->get_text().empty()); +} + +void PluginConfigDialog::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_READY: { + connect("confirmed", this, "_on_confirmed"); + get_cancel()->connect("pressed", this, "_on_cancelled"); + } break; + } +} + +void PluginConfigDialog::config(const String &p_config_path) { + if (p_config_path.length()) { + Ref<ConfigFile> cf = memnew(ConfigFile); + print_line(p_config_path); + cf->load(p_config_path); + + name_edit->set_text(cf->get_value("plugin", "name", "")); + subfolder_edit->set_text(p_config_path.get_base_dir().get_basename().get_file()); + desc_edit->set_text(cf->get_value("plugin", "description", "")); + author_edit->set_text(cf->get_value("plugin", "author", "")); + version_edit->set_text(cf->get_value("plugin", "version", "")); + script_edit->set_text(cf->get_value("plugin", "script", "")); + + _edit_mode = true; + active_edit->hide(); + Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 1))->hide(); + subfolder_edit->hide(); + Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 1))->hide(); + set_title(TTR("Edit a Plugin")); + } else { + _clear_fields(); + _edit_mode = false; + active_edit->show(); + Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 1))->show(); + subfolder_edit->show(); + Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 1))->show(); + set_title(TTR("Create a Plugin")); + } + get_ok()->set_disabled(!_edit_mode); + get_ok()->set_text(_edit_mode ? TTR("Update") : TTR("Create")); +} + +void PluginConfigDialog::_bind_methods() { + ClassDB::bind_method("_on_required_text_changed", &PluginConfigDialog::_on_required_text_changed); + ClassDB::bind_method("_on_confirmed", &PluginConfigDialog::_on_confirmed); + ClassDB::bind_method("_on_cancelled", &PluginConfigDialog::_on_cancelled); + ADD_SIGNAL(MethodInfo("plugin_ready", PropertyInfo(Variant::STRING, "script_path", PROPERTY_HINT_NONE, ""), PropertyInfo(Variant::STRING, "activate_name"))); +} + +PluginConfigDialog::PluginConfigDialog() { + get_ok()->set_disabled(true); + set_hide_on_ok(true); + + GridContainer *grid = memnew(GridContainer); + grid->set_columns(2); + add_child(grid); + + Label *name_lb = memnew(Label); + name_lb->set_text(TTR("Plugin Name:")); + grid->add_child(name_lb); + + name_edit = memnew(LineEdit); + name_edit->connect("text_changed", this, "_on_required_text_changed"); + name_edit->set_placeholder("MyPlugin"); + grid->add_child(name_edit); + + Label *subfolder_lb = memnew(Label); + subfolder_lb->set_text(TTR("Subfolder:")); + grid->add_child(subfolder_lb); + + subfolder_edit = memnew(LineEdit); + subfolder_edit->set_placeholder("\"my_plugin\" -> res://addons/my_plugin"); + grid->add_child(subfolder_edit); + + Label *desc_lb = memnew(Label); + desc_lb->set_text(TTR("Description:")); + grid->add_child(desc_lb); + + desc_edit = memnew(TextEdit); + desc_edit->set_custom_minimum_size(Size2(400.0f, 50.0f)); + grid->add_child(desc_edit); + + Label *author_lb = memnew(Label); + author_lb->set_text(TTR("Author:")); + grid->add_child(author_lb); + + author_edit = memnew(LineEdit); + author_edit->set_placeholder("Godette"); + grid->add_child(author_edit); + + Label *version_lb = memnew(Label); + version_lb->set_text(TTR("Version:")); + grid->add_child(version_lb); + + version_edit = memnew(LineEdit); + version_edit->set_placeholder("1.0"); + grid->add_child(version_edit); + + Label *script_option_lb = memnew(Label); + script_option_lb->set_text(TTR("Language:")); + grid->add_child(script_option_lb); + + script_option_edit = memnew(OptionButton); + script_option_edit->add_item(GDScriptLanguage::get_singleton()->get_name()); + script_option_edit->set_item_metadata(0, GDScriptLanguage::get_singleton()->get_extension()); + script_option_edit->select(0); + //TODO: add other languages + grid->add_child(script_option_edit); + + Label *script_lb = memnew(Label); + script_lb->set_text(TTR("Script Name:")); + grid->add_child(script_lb); + + script_edit = memnew(LineEdit); + script_edit->connect("text_changed", this, "_on_required_text_changed"); + script_edit->set_placeholder("\"plugin.gd\" -> res://addons/my_plugin/plugin.gd"); + grid->add_child(script_edit); + + Label *active_lb = memnew(Label); + active_lb->set_text(TTR("Activate now?")); + grid->add_child(active_lb); + + active_edit = memnew(CheckBox); + active_edit->set_pressed(true); + grid->add_child(active_edit); +} + +PluginConfigDialog::~PluginConfigDialog() { +} diff --git a/editor/plugin_config_dialog.h b/editor/plugin_config_dialog.h new file mode 100644 index 0000000000..2d321a479d --- /dev/null +++ b/editor/plugin_config_dialog.h @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* plugin_config_dialog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 PLUGIN_CONFIG_DIALOG_H +#define PLUGIN_CONFIG_DIALOG_H + +#include "scene/gui/check_box.h" +#include "scene/gui/dialogs.h" +#include "scene/gui/line_edit.h" +#include "scene/gui/option_button.h" +#include "scene/gui/text_edit.h" + +class PluginConfigDialog : public ConfirmationDialog { + + GDCLASS(PluginConfigDialog, ConfirmationDialog); + + LineEdit *name_edit; + LineEdit *subfolder_edit; + TextEdit *desc_edit; + LineEdit *author_edit; + LineEdit *version_edit; + OptionButton *script_option_edit; + LineEdit *script_edit; + CheckBox *active_edit; + + bool _edit_mode; + + void _clear_fields(); + void _on_confirmed(); + void _on_cancelled(); + void _on_required_text_changed(const String &p_text); + +protected: + virtual void _notification(int p_what); + static void _bind_methods(); + +public: + void config(const String &p_plugin_dir_name); + + PluginConfigDialog(); + ~PluginConfigDialog(); +}; + +#endif // PLUGIN_CONFIG_DIALOG_H diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 97ae72f9f8..8f1640b6d1 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -2409,9 +2409,23 @@ void ScriptEditor::_unhandled_input(const Ref<InputEvent> &p_event) { void ScriptEditor::_script_list_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventMouseButton> mb = ev; - if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { + if (mb.is_valid() && mb->is_pressed()) { + switch (mb->get_button_index()) { + + case BUTTON_MIDDLE: { + // Right-click selects automatically; middle-click does not. + int idx = script_list->get_item_at_position(mb->get_position(), true); + if (idx >= 0) { + script_list->select(idx); + _script_selected(idx); + _menu_option(FILE_CLOSE); + } + } break; - _make_script_list_context_menu(); + case BUTTON_RIGHT: { + _make_script_list_context_menu(); + } break; + } } } diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index c3d48d498c..9782b9d1f4 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -2081,6 +2081,15 @@ void SpatialEditorViewport::set_message(String p_message, float p_time) { message_time = p_time; } +void SpatialEditorPlugin::edited_scene_changed() { + for (int i = 0; i < SpatialEditor::VIEWPORTS_COUNT; i++) { + SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(i); + if (viewport->is_visible()) { + viewport->notification(Control::NOTIFICATION_VISIBILITY_CHANGED); + } + } +} + void SpatialEditorViewport::_notification(int p_what) { if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 0ebc11e5df..4057145c2f 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -741,6 +741,8 @@ public: virtual void set_state(const Dictionary &p_state); virtual void clear() { spatial_editor->clear(); } + virtual void edited_scene_changed(); + SpatialEditorPlugin(EditorNode *p_node); ~SpatialEditorPlugin(); }; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 0419c3d4b1..d13e01dc1e 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -603,7 +603,6 @@ void TextureRegionEditor::_notification(int p_what) { zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons")); zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); zoom_in->set_icon(get_icon("ZoomMore", "EditorIcons")); - icon_zoom->set_texture(get_icon("Zoom", "EditorIcons")); } break; } } @@ -865,7 +864,7 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { hb_grid->add_child(sb_step_y); hb_grid->add_child(memnew(VSeparator)); - hb_grid->add_child(memnew(Label(TTR("Separation:")))); + hb_grid->add_child(memnew(Label(TTR("Sep.:")))); sb_sep_x = memnew(SpinBox); sb_sep_x->set_min(0); @@ -898,10 +897,6 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { separator->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb_tools->add_child(separator); - icon_zoom = memnew(TextureRect); - icon_zoom->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); - hb_tools->add_child(icon_zoom); - zoom_out = memnew(ToolButton); zoom_out->connect("pressed", this, "_zoom_out"); hb_tools->add_child(zoom_out); @@ -940,16 +935,15 @@ bool TextureRegionEditorPlugin::handles(Object *p_object) const { void TextureRegionEditorPlugin::make_visible(bool p_visible) { if (p_visible) { texture_region_button->show(); - if (region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region())) { + if (region_editor->is_stylebox() || region_editor->is_atlas_texture() || region_editor->is_ninepatch() || (region_editor->get_sprite() && region_editor->get_sprite()->is_region()) || texture_region_button->is_pressed()) { editor->make_bottom_panel_item_visible(region_editor); - } else { - if (texture_region_button->is_pressed()) - region_editor->show(); } } else { + if (region_editor->is_visible_in_tree()) { + editor->hide_bottom_panel(); + } texture_region_button->hide(); region_editor->edit(NULL); - region_editor->hide(); } } @@ -1001,10 +995,9 @@ TextureRegionEditorPlugin::TextureRegionEditorPlugin(EditorNode *p_node) { editor = p_node; region_editor = memnew(TextureRegionEditor(p_node)); - texture_region_button = p_node->add_bottom_panel_item(TTR("TextureRegion"), region_editor); - texture_region_button->set_tooltip(TTR("Texture Region Editor")); - region_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); region_editor->hide(); + + texture_region_button = p_node->add_bottom_panel_item(TTR("TextureRegion"), region_editor); texture_region_button->hide(); } diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index bd93be9267..670cc86bbb 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -56,7 +56,6 @@ class TextureRegionEditor : public Control { friend class TextureRegionEditorPlugin; MenuButton *snap_mode_button; - TextureRect *icon_zoom; ToolButton *zoom_in; ToolButton *zoom_reset; ToolButton *zoom_out; diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 8d1db5de8f..490ebeca26 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -307,6 +307,11 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { tool_workspacemode[i]->connect("pressed", this, "_on_workspace_mode_changed", p); tool_hb->add_child(tool_workspacemode[i]); } + Control *spacer = memnew(Control); + spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tool_hb->add_child(spacer); + tool_hb->move_child(spacer, (int)WORKSPACE_CREATE_SINGLE); + tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true); workspace_mode = WORKSPACE_EDIT; @@ -314,9 +319,6 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { main_vb->add_child(memnew(HSeparator)); tool_hb = memnew(HBoxContainer); - Control *spacer = memnew(Control); - spacer->set_custom_minimum_size(Size2(30, 0)); - tool_hb->add_child(spacer); g = Ref<ButtonGroup>(memnew(ButtonGroup)); String label[EDITMODE_MAX] = { "Region", "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon" }; @@ -335,7 +337,8 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { edit_mode = EDITMODE_COLLISION; main_vb->add_child(tool_hb); - main_vb->add_child(memnew(HSeparator)); + separator_editmode = memnew(HSeparator); + main_vb->add_child(separator_editmode); toolbar = memnew(HBoxContainer); Ref<ButtonGroup> tg(memnew(ButtonGroup)); @@ -369,13 +372,17 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { toolbar->add_child(tools[SHAPE_NEW_POLYGON]); tools[SHAPE_NEW_POLYGON]->set_toggle_mode(true); tools[SHAPE_NEW_POLYGON]->set_button_group(tg); - toolbar->add_child(memnew(VSeparator)); + + separator_delete = memnew(VSeparator); + toolbar->add_child(separator_delete); tools[SHAPE_DELETE] = memnew(ToolButton); p = Vector<Variant>(); p.push_back((int)SHAPE_DELETE); tools[SHAPE_DELETE]->connect("pressed", this, "_on_tool_clicked", p); toolbar->add_child(tools[SHAPE_DELETE]); - toolbar->add_child(memnew(VSeparator)); + + separator_grid = memnew(VSeparator); + toolbar->add_child(separator_grid); tools[SHAPE_KEEP_INSIDE_TILE] = memnew(ToolButton); tools[SHAPE_KEEP_INSIDE_TILE]->set_toggle_mode(true); tools[SHAPE_KEEP_INSIDE_TILE]->set_pressed(true); @@ -588,10 +595,16 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->hide(); - if (workspace_mode == WORKSPACE_EDIT) + + if (workspace_mode == WORKSPACE_EDIT) { + separator_delete->show(); tools[SHAPE_DELETE]->show(); - else + } else { + separator_delete->hide(); tools[SHAPE_DELETE]->hide(); + } + + separator_grid->show(); tools[SHAPE_KEEP_INSIDE_TILE]->hide(); tools[TOOL_GRID_SNAP]->show(); @@ -605,7 +618,11 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->show(); tools[BITMASK_CLEAR]->show(); tools[SHAPE_NEW_POLYGON]->hide(); + + separator_delete->hide(); tools[SHAPE_DELETE]->hide(); + + separator_grid->hide(); tools[SHAPE_KEEP_INSIDE_TILE]->hide(); tools[TOOL_GRID_SNAP]->hide(); @@ -621,7 +638,11 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->show(); + + separator_delete->show(); tools[SHAPE_DELETE]->show(); + + separator_grid->show(); tools[SHAPE_KEEP_INSIDE_TILE]->show(); tools[TOOL_GRID_SNAP]->show(); @@ -635,9 +656,14 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); tools[SHAPE_NEW_POLYGON]->hide(); + + separator_delete->hide(); tools[SHAPE_DELETE]->hide(); + + separator_grid->show(); tools[SHAPE_KEEP_INSIDE_TILE]->hide(); tools[TOOL_GRID_SNAP]->show(); + if (edit_mode == EDITMODE_ICON) { tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.\nClick on another Tile to edit it.")); spin_priority->hide(); @@ -661,6 +687,7 @@ void TileSetEditor::_on_workspace_mode_changed(int p_workspace_mode) { tool_editmode[EDITMODE_REGION]->show(); tool_editmode[EDITMODE_REGION]->set_pressed(true); _on_edit_mode_changed(EDITMODE_REGION); + separator_editmode->show(); } } @@ -2076,6 +2103,7 @@ void TileSetEditor::update_workspace_tile_mode() { tool_editmode[EDITMODE_REGION]->show(); tool_editmode[EDITMODE_REGION]->set_pressed(true); _on_edit_mode_changed(EDITMODE_REGION); + separator_editmode->show(); return; } @@ -2086,12 +2114,16 @@ void TileSetEditor::update_workspace_tile_mode() { for (int i = 0; i < ZOOM_OUT; i++) { tools[i]->hide(); } + separator_editmode->hide(); + separator_delete->hide(); + separator_grid->hide(); return; } for (int i = 0; i < EDITMODE_MAX; i++) { tool_editmode[i]->show(); } + separator_editmode->show(); if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { if (tool_editmode[EDITMODE_ICON]->is_pressed() || tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed()) { @@ -2336,12 +2368,10 @@ bool TileSetEditorPlugin::handles(Object *p_node) const { void TileSetEditorPlugin::make_visible(bool p_visible) { if (p_visible) { tileset_editor_button->show(); - if (tileset_editor_button->is_pressed()) { - tileset_editor->show(); - } + editor->make_bottom_panel_item_visible(tileset_editor); get_tree()->connect("idle_frame", tileset_editor, "_on_workspace_process"); } else { - tileset_editor->hide(); + editor->hide_bottom_panel(); tileset_editor_button->hide(); get_tree()->disconnect("idle_frame", tileset_editor, "_on_workspace_process"); } diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 0c175e718c..23bf68b90f 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -40,12 +40,12 @@ #define WORKSPACE_MARGIN Vector2(10, 10) class TilesetEditorContext; -class TileSetEditor : public Panel { +class TileSetEditor : public Control { friend class TileSetEditorPlugin; friend class TilesetEditorContext; - GDCLASS(TileSetEditor, Panel) + GDCLASS(TileSetEditor, Control) enum TextureToolButtons { TOOL_TILESET_ADD_TEXTURE, @@ -131,8 +131,11 @@ class TileSetEditor : public Panel { Control *workspace; Button *tool_workspacemode[WORKSPACE_MODE_MAX]; Button *tool_editmode[EDITMODE_MAX]; + HSeparator *separator_editmode; HBoxContainer *toolbar; ToolButton *tools[TOOL_MAX]; + VSeparator *separator_delete; + VSeparator *separator_grid; SpinBox *spin_priority; WorkspaceMode workspace_mode; EditMode edit_mode; diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index ea697f5da2..970302e058 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -806,6 +806,10 @@ void ProjectSettingsEditor::popup_project_settings() { plugin_settings->update_plugins(); } +void ProjectSettingsEditor::update_plugins() { + plugin_settings->update_plugins(); +} + void ProjectSettingsEditor::_item_selected(const String &p_path) { String selected_path = p_path; diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index b738c4ae20..1344da1de7 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -186,6 +186,7 @@ public: static ProjectSettingsEditor *get_singleton() { return singleton; } void popup_project_settings(); void set_plugins_page(); + void update_plugins(); EditorAutoloadSettings *get_autoload_settings() { return autoload_settings; } diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index b370a711e3..408e67149a 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -287,7 +287,11 @@ void CustomPropertyEditor::_menu_option(int p_which) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_BREAK(!obj); @@ -1132,7 +1136,11 @@ void CustomPropertyEditor::_type_create_selected(int p_idx) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_FAIL_COND(!obj); @@ -1334,7 +1342,11 @@ void CustomPropertyEditor::_action_pressed(int p_which) { Object *obj = ClassDB::instance(intype); if (!obj) { - obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + if (ScriptServer::is_global_class(intype)) { + obj = EditorNode::get_editor_data().script_class_instance(intype); + } else { + obj = EditorNode::get_editor_data().instance_custom_type(intype, "Resource"); + } } ERR_BREAK(!obj); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index d17bcef92b..607d974025 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -365,10 +365,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptLanguage *l = ScriptServer::get_language(i); if (l->get_type() == existing->get_class()) { - if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { - String name = l->get_global_class_name(existing->get_path(), NULL); - inherits = editor->get_editor_data().script_class_get_base(name); - } else if (l->can_inherit_from_file()) { + String name = l->get_global_class_name(existing->get_path()); + if (ScriptServer::is_global_class(name)) { + if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { + inherits = editor->get_editor_data().script_class_get_base(name); + } else if (l->can_inherit_from_file()) { + inherits = "\"" + existing->get_path() + "\""; + } + } else { inherits = "\"" + existing->get_path() + "\""; } } @@ -395,6 +399,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { const RefPtr empty; editor_data->get_undo_redo().add_do_method(E->get(), "set_script", empty); editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + + editor_data->get_undo_redo().add_do_method(E->get(), "set_meta", "_editor_icon", get_icon(E->get()->get_class(), "EditorIcons")); + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", E->get()->get_meta("_editor_icon")); } } @@ -402,7 +409,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_data->get_undo_redo().add_undo_method(this, "_update_script_button"); editor_data->get_undo_redo().commit_action(); - } break; case TOOL_MOVE_UP: case TOOL_MOVE_DOWN: { @@ -1490,9 +1496,23 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { Ref<Script> existing = E->get()->get_script(); editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script.get_ref_ptr()); editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing); + + String icon_path; + String name = p_script->get_language()->get_global_class_name(p_script->get_path(), NULL, &icon_path); + if (ScriptServer::is_global_class(name)) { + RES icon = ResourceLoader::load(icon_path); + editor_data->get_undo_redo().add_do_method(E->get(), "set_meta", "_editor_icon", icon); + String existing_name = existing.is_valid() ? existing->get_language()->get_global_class_name(existing->get_path()) : String(); + if (existing.is_null() || !ScriptServer::is_global_class(existing_name)) { + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", get_icon(E->get()->get_class(), "EditorIcons")); + } else { + editor_data->get_undo_redo().add_undo_method(E->get(), "set_meta", "_editor_icon", editor_data->script_class_get_icon_path(existing_name)); + } + } } editor_data->get_undo_redo().commit_action(); + print_line("test: " + String(Variant(selected.front()->get()->get_meta("_editor_icon")))); editor->push_item(p_script.operator->()); } diff --git a/modules/csg/csg.h b/modules/csg/csg.h index 53303a6533..2e07c23e28 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -34,9 +34,9 @@ #include "aabb.h" #include "dvector.h" #include "map.h" -#include "math_2d.h" #include "oa_hash_map.h" #include "plane.h" +#include "rect2.h" #include "scene/resources/material.h" #include "transform.h" #include "vector3.h" diff --git a/modules/gdnative/gdnative/pool_arrays.cpp b/modules/gdnative/gdnative/pool_arrays.cpp index 6688be1a0d..2b6b7a823a 100644 --- a/modules/gdnative/gdnative/pool_arrays.cpp +++ b/modules/gdnative/gdnative/pool_arrays.cpp @@ -35,7 +35,7 @@ #include "dvector.h" #include "core/color.h" -#include "core/math/math_2d.h" +#include "core/math/vector2.h" #include "core/math/vector3.h" #ifdef __cplusplus diff --git a/modules/gdnative/gdnative/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp index 83c58db520..54b98fc4e5 100644 --- a/modules/gdnative/gdnative/rect2.cpp +++ b/modules/gdnative/gdnative/rect2.cpp @@ -30,7 +30,7 @@ #include "gdnative/rect2.h" -#include "core/math/math_2d.h" +#include "core/math/transform_2d.h" #include "core/variant.h" #ifdef __cplusplus diff --git a/modules/gdnative/gdnative/transform2d.cpp b/modules/gdnative/gdnative/transform2d.cpp index c69607a18a..fa0e15d9d2 100644 --- a/modules/gdnative/gdnative/transform2d.cpp +++ b/modules/gdnative/gdnative/transform2d.cpp @@ -30,7 +30,7 @@ #include "gdnative/transform2d.h" -#include "core/math/math_2d.h" +#include "core/math/transform_2d.h" #include "core/variant.h" #ifdef __cplusplus diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp index 9e40b42373..c7902e06ee 100644 --- a/modules/gdnative/gdnative/vector2.cpp +++ b/modules/gdnative/gdnative/vector2.cpp @@ -30,7 +30,7 @@ #include "gdnative/vector2.h" -#include "core/math/math_2d.h" +#include "core/math/vector2.h" #include "core/variant.h" #ifdef __cplusplus diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 42ec05e6ce..b987d2897f 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1811,7 +1811,7 @@ bool GDScriptLanguage::handles_global_class_type(const String &p_type) const { return p_type == "GDScript"; } -String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type) const { +String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const { PoolVector<uint8_t> sourcef; Error err; @@ -1876,6 +1876,12 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b } } } + if (r_icon_path) { + if (c->icon_path.empty() || c->icon_path.is_abs_path()) + *r_icon_path = c->icon_path; + else if (c->icon_path.is_rel_path()) + *r_icon_path = p_path.get_base_dir().plus_file(c->icon_path).simplify_path(); + } return c->name; } diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 68e89887b0..d400230f43 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -492,7 +492,7 @@ public: /* GLOBAL CLASSES */ virtual bool handles_global_class_type(const String &p_type) const; - virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL) const; + virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL, String *r_icon_path = NULL) const; GDScriptLanguage(); ~GDScriptLanguage(); diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index e0ed2b332b..bec314866d 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -3429,6 +3429,32 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(2); + if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { + tokenizer->advance(); + + if ((tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type() == Variant::STRING)) { + Variant constant = tokenizer->get_token_constant(); + String icon_path = constant.operator String(); + + String abs_icon_path = icon_path.is_rel_path() ? self_path.get_base_dir().plus_file(icon_path).simplify_path() : icon_path; + if (!FileAccess::exists(abs_icon_path)) { + _set_error("No class icon found at: " + abs_icon_path); + return; + } + + p_class->icon_path = icon_path; + + tokenizer->advance(); + } else { + _set_error("Optional parameter after 'class_name' must be a string constant file path to an icon."); + return; + } + + } else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT) { + _set_error("Class icon must be separated by a comma."); + return; + } + } break; case GDScriptTokenizer::TK_PR_TOOL: { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index d8ee4e8159..dbe523a0b9 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -149,6 +149,7 @@ public: StringName extends_file; Vector<StringName> extends_class; DataType base_type; + String icon_path; struct Member { PropertyInfo _export; diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp index 0551c1991a..148bb32398 100644 --- a/modules/mono/glue/collections_glue.cpp +++ b/modules/mono/glue/collections_glue.cpp @@ -182,7 +182,7 @@ bool godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) { } bool godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) { - return ptr->erase_checked(GDMonoMarshal::mono_object_to_variant(key)); + return ptr->erase(GDMonoMarshal::mono_object_to_variant(key)); } bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) { @@ -191,7 +191,7 @@ bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject // no dupes Variant *ret = ptr->getptr(varKey); if (ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value)) { - ptr->erase_checked(varKey); + ptr->erase(varKey); return true; } diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 3b48063fe9..89f71f0013 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -31,7 +31,7 @@ #ifndef OSUWP_H #define OSUWP_H -#include "core/math/math_2d.h" +#include "core/math/transform_2d.h" #include "core/ustring.h" #include "drivers/xaudio2/audio_driver_xaudio2.h" #include "gl_context_egl.h" diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h index b1c62f84e2..edfdf97c47 100644 --- a/scene/2d/line_builder.h +++ b/scene/2d/line_builder.h @@ -33,8 +33,8 @@ #include "color.h" #include "line_2d.h" -#include "math_2d.h" #include "scene/resources/color_ramp.h" +#include "vector2.h" class LineBuilder { public: diff --git a/scene/gui/control.h b/scene/gui/control.h index 6bea04345b..c6bd2f097d 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -31,13 +31,13 @@ #ifndef CONTROL_H #define CONTROL_H -#include "math_2d.h" #include "rid.h" #include "scene/2d/canvas_item.h" #include "scene/gui/shortcut.h" #include "scene/main/node.h" #include "scene/main/timer.h" #include "scene/resources/theme.h" +#include "transform_2d.h" /** @author Juan Linietsky <reduzio@gmail.com> */ diff --git a/scene/gui/reference_rect.cpp b/scene/gui/reference_rect.cpp index 5e25f43daf..74e68598f4 100644 --- a/scene/gui/reference_rect.cpp +++ b/scene/gui/reference_rect.cpp @@ -39,9 +39,25 @@ void ReferenceRect::_notification(int p_what) { if (!is_inside_tree()) return; if (Engine::get_singleton()->is_editor_hint()) - draw_style_box(get_stylebox("border"), Rect2(Point2(), get_size())); + draw_rect(Rect2(Point2(), get_size()), border_color, false); } } +void ReferenceRect::set_border_color(const Color &color) { + border_color = color; +} + +Color ReferenceRect::get_border_color() const { + return border_color; +} + +void ReferenceRect::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_border_color"), &ReferenceRect::get_border_color); + ClassDB::bind_method(D_METHOD("set_border_color", "color"), &ReferenceRect::set_border_color); + + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "border_color"), "set_border_color", "get_border_color"); +} + ReferenceRect::ReferenceRect() { + border_color = Color(1, 0, 0); } diff --git a/scene/gui/reference_rect.h b/scene/gui/reference_rect.h index 473e348c85..9fad1a06b0 100644 --- a/scene/gui/reference_rect.h +++ b/scene/gui/reference_rect.h @@ -36,12 +36,17 @@ class ReferenceRect : public Control { GDCLASS(ReferenceRect, Control); + Color border_color; protected: void _notification(int p_what); + static void _bind_methods(); public: ReferenceRect(); + + void set_border_color(const Color &color); + Color get_border_color() const; }; #endif // REFERENCE_RECT_H diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 6144240328..d6a80bfb1a 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2555,6 +2555,9 @@ void Node::clear_internal_tree_resource_paths() { String Node::get_configuration_warning() const { + if (get_script_instance() && get_script_instance()->has_method("_get_configuration_warning")) { + return get_script_instance()->call("_get_configuration_warning"); + } return String(); } @@ -2763,6 +2766,7 @@ void Node::_bind_methods() { BIND_VMETHOD(MethodInfo("_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo("_unhandled_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEventKey"))); + BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_configuration_warning")); //ClassDB::bind_method(D_METHOD("get_child",&Node::get_child,PH("index"))); //ClassDB::bind_method(D_METHOD("get_node",&Node::get_node,PH("path"))); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index e717d27069..e4ef373c77 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -31,11 +31,11 @@ #ifndef VIEWPORT_H #define VIEWPORT_H -#include "math_2d.h" #include "scene/main/node.h" #include "scene/resources/texture.h" #include "scene/resources/world_2d.h" #include "servers/visual_server.h" +#include "transform_2d.h" /** @author Juan Linietsky <reduzio@gmail.com> */ diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 2d05f5e19f..0eee2ae393 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -867,7 +867,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<StyleBoxTexture> ttnc = make_stylebox(full_panel_bg_png, 8, 8, 8, 8); ttnc->set_draw_center(false); - theme->set_stylebox("border", "ReferenceRect", make_stylebox(reference_border_png, 4, 4, 4, 4)); theme->set_stylebox("panelnc", "Panel", ttnc); theme->set_stylebox("panelf", "Panel", tc_sb); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index dc29102492..875b72159a 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -694,8 +694,6 @@ void SpatialMaterial::_update_shader() { } code += "\t\tbase_uv=ofs;\n"; - code += "\t\tif(base_uv.x > 1.0 || base_uv.y > 1.0 || base_uv.x < 0.0 || base_uv.y < 0.0)\n"; - code += "\t\t\tdiscard;\n"; if (features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) { code += "\t\tbase_uv2-=ofs;\n"; } diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 536c653a0c..96edb17eea 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -214,9 +214,10 @@ Image::Format ImageTexture::get_format() const { return format; } - +#ifndef DISABLE_DEPRECATED Error ImageTexture::load(const String &p_path) { + WARN_DEPRECATED Ref<Image> img; img.instance(); Error err = img->load(p_path); @@ -225,7 +226,7 @@ Error ImageTexture::load(const String &p_path) { } return err; } - +#endif void ImageTexture::set_data(const Ref<Image> &p_image) { ERR_FAIL_COND(p_image.is_null()); @@ -345,7 +346,9 @@ void ImageTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("create", "width", "height", "format", "flags"), &ImageTexture::create, DEFVAL(FLAGS_DEFAULT)); ClassDB::bind_method(D_METHOD("create_from_image", "image", "flags"), &ImageTexture::create_from_image, DEFVAL(FLAGS_DEFAULT)); ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format); +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("load", "path"), &ImageTexture::load); +#endif ClassDB::bind_method(D_METHOD("set_data", "image"), &ImageTexture::set_data); ClassDB::bind_method(D_METHOD("set_storage", "mode"), &ImageTexture::set_storage); ClassDB::bind_method(D_METHOD("get_storage"), &ImageTexture::get_storage); @@ -618,7 +621,11 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla memdelete(f); - if (bytes != total_size - ofs) { + int expected = total_size - ofs; + if (bytes < expected) { + //this is a compatibility workaround for older format, which saved less mipmaps. It is still recommended the image is reimported. + zeromem(w.ptr() + bytes, (expected - bytes)); + } else if (bytes != expected) { ERR_FAIL_V(ERR_FILE_CORRUPT); } } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 1c18189b2c..c1331fb3fe 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -33,9 +33,9 @@ #include "curve.h" #include "io/resource_loader.h" -#include "math_2d.h" #include "os/mutex.h" #include "os/thread_safe.h" +#include "rect2.h" #include "resource.h" #include "scene/resources/color_ramp.h" #include "servers/visual_server.h" @@ -125,7 +125,9 @@ public: void set_flags(uint32_t p_flags); uint32_t get_flags() const; Image::Format get_format() const; +#ifndef DISABLE_DEPRECATED Error load(const String &p_path); +#endif void set_data(const Ref<Image> &p_image); Ref<Image> get_data() const; diff --git a/servers/physics_2d/broad_phase_2d_sw.h b/servers/physics_2d/broad_phase_2d_sw.h index 80ae970624..d7d236c4c6 100644 --- a/servers/physics_2d/broad_phase_2d_sw.h +++ b/servers/physics_2d/broad_phase_2d_sw.h @@ -31,8 +31,8 @@ #ifndef BROAD_PHASE_2D_SW_H #define BROAD_PHASE_2D_SW_H -#include "math_2d.h" #include "math_funcs.h" +#include "rect2.h" class CollisionObject2DSW; diff --git a/servers/visual_server.h b/servers/visual_server.h index 0ec902c18c..fd7f96339e 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -34,9 +34,9 @@ #include "bsp_tree.h" #include "geometry.h" #include "image.h" -#include "math_2d.h" #include "object.h" #include "rid.h" +#include "transform_2d.h" #include "variant.h" /** diff --git a/thirdparty/b2d_convexdecomp/b2Glue.h b/thirdparty/b2d_convexdecomp/b2Glue.h index 425486356e..10c2f62361 100644 --- a/thirdparty/b2d_convexdecomp/b2Glue.h +++ b/thirdparty/b2d_convexdecomp/b2Glue.h @@ -19,7 +19,7 @@ #ifndef B2GLUE_H #define B2GLUE_H -#include "math_2d.h" +#include "vector2.h" #include <limits.h> namespace b2ConvexDecomp { diff --git a/thirdparty/misc/triangulator.h b/thirdparty/misc/triangulator.h index b6dd7e8236..d1538cfae5 100644 --- a/thirdparty/misc/triangulator.h +++ b/thirdparty/misc/triangulator.h @@ -21,9 +21,9 @@ #ifndef TRIANGULATOR_H #define TRIANGULATOR_H -#include "math_2d.h" #include "list.h" #include "set.h" +#include "vector2.h" //2D point structure |